source: bootcd/isolinux/syslinux-6.03/libinstaller/syslxcom.c @ e16e8f2

Last change on this file since e16e8f2 was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 6.0 KB
Line 
1/* ----------------------------------------------------------------------- *
2 *
3 *   Copyright 2010 Intel Corp. - All Rights Reserved
4 *
5 *   This program is free software; you can redistribute it and/or modify
6 *   it under the terms of the GNU General Public License as published by
7 *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
8 *   Boston MA 02111-1307, USA; either version 2 of the License, or
9 *   (at your option) any later version; incorporated herein by reference.
10 *
11 * ----------------------------------------------------------------------- */
12
13/*
14 * syslxcom.c
15 *
16 * common functions for extlinux & syslinux installer
17 *
18 */
19#define  _GNU_SOURCE
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <stddef.h>
24#include <stdint.h>
25#include <string.h>
26#include <getopt.h>
27#include <unistd.h>
28#include <errno.h>
29#include <sys/stat.h>
30#include <sys/types.h>
31#include <sys/mount.h>
32#include <sys/vfs.h>
33
34#include "linuxioctl.h"
35#include "syslxcom.h"
36#include "syslxfs.h"
37
38const char *program;
39
40int fs_type;
41
42#ifdef DEBUG
43# define dprintf printf
44#else
45# define dprintf(...) ((void)0)
46#endif
47
48#define SECTOR_SHIFT    9
49
50static void die(const char *msg)
51{
52    fputs(msg, stderr);
53    exit(1);
54}
55
56/*
57 * read/write wrapper functions
58 */
59ssize_t xpread(int fd, void *buf, size_t count, off_t offset)
60{
61    char *bufp = (char *)buf;
62    ssize_t rv;
63    ssize_t done = 0;
64
65    while (count) {
66        rv = pread(fd, bufp, count, offset);
67        if (rv == 0) {
68            die("short read");
69        } else if (rv == -1) {
70            if (errno == EINTR) {
71                continue;
72            } else {
73                die(strerror(errno));
74            }
75        } else {
76            bufp += rv;
77            offset += rv;
78            done += rv;
79            count -= rv;
80        }
81    }
82
83    return done;
84}
85
86ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset)
87{
88    const char *bufp = (const char *)buf;
89    ssize_t rv;
90    ssize_t done = 0;
91
92    while (count) {
93        rv = pwrite(fd, bufp, count, offset);
94        if (rv == 0) {
95            die("short write");
96        } else if (rv == -1) {
97            if (errno == EINTR) {
98                continue;
99            } else {
100                die(strerror(errno));
101            }
102        } else {
103            bufp += rv;
104            offset += rv;
105            done += rv;
106            count -= rv;
107        }
108    }
109
110    return done;
111}
112
113/*
114 * Set and clear file attributes
115 */
116void clear_attributes(int fd)
117{
118    struct stat st;
119
120    if (!fstat(fd, &st)) {
121        switch (fs_type) {
122        case EXT2:
123        {
124            int flags;
125
126            if (!ioctl(fd, FS_IOC_GETFLAGS, &flags)) {
127                flags &= ~FS_IMMUTABLE_FL;
128                ioctl(fd, FS_IOC_SETFLAGS, &flags);
129            }
130            break;
131        }
132        case VFAT:
133        {
134            uint32_t attr = 0x00; /* Clear all attributes */
135            ioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &attr);
136            break;
137        }
138    case NTFS:
139        break;
140        default:
141            break;
142        }
143        fchmod(fd, st.st_mode | S_IWUSR);
144    }
145}
146
147void set_attributes(int fd)
148{
149    struct stat st;
150
151    if (!fstat(fd, &st)) {
152        fchmod(fd, st.st_mode & (S_IRUSR | S_IRGRP | S_IROTH));
153        switch (fs_type) {
154        case EXT2:
155        {
156            int flags;
157
158            if (st.st_uid == 0 && !ioctl(fd, FS_IOC_GETFLAGS, &flags)) {
159                flags |= FS_IMMUTABLE_FL;
160                ioctl(fd, FS_IOC_SETFLAGS, &flags);
161            }
162            break;
163        }
164        case VFAT:
165        {
166            uint32_t attr = 0x07; /* Hidden+System+Readonly */
167            ioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &attr);
168            break;
169        }
170    case NTFS:
171        break;
172        default:
173            break;
174        }
175    }
176}
177
178/* New FIEMAP based mapping */
179static int sectmap_fie(int fd, sector_t *sectors, int nsectors)
180{
181    struct fiemap *fm;
182    struct fiemap_extent *fe;
183    unsigned int i, nsec;
184    sector_t sec, *secp, *esec;
185    struct stat st;
186    uint64_t maplen;
187
188    if (fstat(fd, &st))
189        return -1;
190
191    fm = alloca(sizeof(struct fiemap)
192                + nsectors * sizeof(struct fiemap_extent));
193
194    memset(fm, 0, sizeof *fm);
195
196    maplen = (uint64_t)nsectors << SECTOR_SHIFT;
197    if (maplen > (uint64_t)st.st_size)
198        maplen = st.st_size;
199
200    fm->fm_start        = 0;
201    fm->fm_length       = maplen;
202    fm->fm_flags        = FIEMAP_FLAG_SYNC;
203    fm->fm_extent_count = nsectors;
204
205    if (ioctl(fd, FS_IOC_FIEMAP, fm))
206        return -1;
207
208    memset(sectors, 0, nsectors * sizeof *sectors);
209    esec = sectors + nsectors;
210
211    fe = fm->fm_extents;
212
213    if (fm->fm_mapped_extents < 1 ||
214        !(fe[fm->fm_mapped_extents-1].fe_flags & FIEMAP_EXTENT_LAST))
215        return -1;
216
217    for (i = 0; i < fm->fm_mapped_extents; i++) {
218        if (fe->fe_flags & FIEMAP_EXTENT_LAST) {
219            /* If this is the *final* extent, pad the length */
220            fe->fe_length = (fe->fe_length + SECTOR_SIZE - 1)
221                & ~(SECTOR_SIZE - 1);
222        }
223
224        if ((fe->fe_logical | fe->fe_physical| fe->fe_length) &
225            (SECTOR_SIZE - 1))
226            return -1;
227
228        if (fe->fe_flags & (FIEMAP_EXTENT_UNKNOWN|
229                            FIEMAP_EXTENT_DELALLOC|
230                            FIEMAP_EXTENT_ENCODED|
231                            FIEMAP_EXTENT_DATA_ENCRYPTED|
232                            FIEMAP_EXTENT_UNWRITTEN))
233            return -1;
234
235        secp = sectors + (fe->fe_logical >> SECTOR_SHIFT);
236        sec  = fe->fe_physical >> SECTOR_SHIFT;
237        nsec = fe->fe_length >> SECTOR_SHIFT;
238
239        while (nsec--) {
240            if (secp >= esec)
241                break;
242            *secp++ = sec++;
243        }
244
245        fe++;
246    }
247
248    return 0;
249}
250
251/* Legacy FIBMAP based mapping */
252static int sectmap_fib(int fd, sector_t *sectors, int nsectors)
253{
254    unsigned int blk, nblk;
255    unsigned int i;
256    unsigned int blksize;
257    sector_t sec;
258
259    /* Get block size */
260    if (ioctl(fd, FIGETBSZ, &blksize))
261        return -1;
262
263    /* Number of sectors per block */
264    blksize >>= SECTOR_SHIFT;
265
266    nblk = 0;
267    while (nsectors) {
268        blk = nblk++;
269        if (ioctl(fd, FIBMAP, &blk))
270            return -1;
271
272        sec = (sector_t)blk * blksize;
273        for (i = 0; i < blksize; i++) {
274            *sectors++ = sec++;
275            if (! --nsectors)
276                break;
277        }
278    }
279
280    return 0;
281}
282
283/*
284 * Produce file map
285 */
286int sectmap(int fd, sector_t *sectors, int nsectors)
287{
288    if (!sectmap_fie(fd, sectors, nsectors))
289        return 0;
290
291    return sectmap_fib(fd, sectors, nsectors);
292}
293
294/*
295 * SYSLINUX installs the string 'SYSLINUX' at offset 3 in the boot
296 * sector; this is consistent with FAT filesystems.  Earlier versions
297 * would install the string "EXTLINUX" instead, handle both.
298 */
299int syslinux_already_installed(int dev_fd)
300{
301    char buffer[8];
302
303    xpread(dev_fd, buffer, 8, 3);
304    return !memcmp(buffer, "SYSLINUX", 8) || !memcmp(buffer, "EXTLINUX", 8);
305}
Note: See TracBrowser for help on using the repository browser.