1 /* ----------------------------------------------------------------------- *
3 * Copyright 2010 Intel Corp. - All Rights Reserved
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.
11 * ----------------------------------------------------------------------- */
16 * common functions for extlinux & syslinux installer
29 #include <sys/ioctl.h>
31 #include <sys/types.h>
32 #include <sys/mount.h>
34 #include <linux/fs.h> /* FIGETBSZ, FIBMAP */
35 #include <linux/msdos_fs.h> /* FAT_IOCTL_SET_ATTRIBUTES */
36 #undef SECTOR_SIZE /* Defined in msdos_fs.h for no good reason */
37 #include <linux/fiemap.h> /* FIEMAP definitions */
45 # define dprintf printf
47 # define dprintf(...) ((void)0)
50 #define SECTOR_SHIFT 9
51 #define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */
56 #define EXT2_IOC_GETFLAGS _IOR('f', 1, long)
57 #define EXT2_IOC_SETFLAGS _IOW('f', 2, long)
58 #define EXT2_IOC_GETVERSION _IOR('v', 1, long)
59 #define EXT2_IOC_SETVERSION _IOW('v', 2, long)
61 static void die(const char *msg)
68 * read/write wrapper functions
70 ssize_t xpread(int fd, void *buf, size_t count, off_t offset)
72 char *bufp = (char *)buf;
77 rv = pread(fd, bufp, count, offset);
80 } else if (rv == -1) {
97 ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset)
99 const char *bufp = (const char *)buf;
104 rv = pwrite(fd, bufp, count, offset);
107 } else if (rv == -1) {
108 if (errno == EINTR) {
111 die(strerror(errno));
125 * Set and clear file attributes
127 void clear_attributes(int fd)
131 if (!fstat(fd, &st)) {
137 if (!ioctl(fd, EXT2_IOC_GETFLAGS, &flags)) {
138 flags &= ~EXT2_IMMUTABLE_FL;
139 ioctl(fd, EXT2_IOC_SETFLAGS, &flags);
145 uint32_t attr = 0x00; /* Clear all attributes */
146 ioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &attr);
152 fchmod(fd, st.st_mode | S_IWUSR);
156 void set_attributes(int fd)
160 if (!fstat(fd, &st)) {
161 fchmod(fd, st.st_mode & (S_IRUSR | S_IRGRP | S_IROTH));
167 if (st.st_uid == 0 && !ioctl(fd, EXT2_IOC_GETFLAGS, &flags)) {
168 flags |= EXT2_IMMUTABLE_FL;
169 ioctl(fd, EXT2_IOC_SETFLAGS, &flags);
175 uint32_t attr = 0x07; /* Hidden+System+Readonly */
176 ioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &attr);
185 /* New FIEMAP based mapping */
186 static int sectmap_fie(int fd, sector_t *sectors, int nsectors)
189 struct fiemap_extent *fe;
190 unsigned int i, nsec;
191 sector_t sec, *secp, *esec;
198 fm = alloca(sizeof(struct fiemap)
199 + nsectors * sizeof(struct fiemap_extent));
201 memset(fm, 0, sizeof *fm);
203 maplen = (uint64_t)nsectors << SECTOR_SHIFT;
204 if (maplen > (uint64_t)st.st_size)
208 fm->fm_length = maplen;
209 fm->fm_flags = FIEMAP_FLAG_SYNC;
210 fm->fm_extent_count = nsectors;
212 if (ioctl(fd, FS_IOC_FIEMAP, &fm))
215 memset(sectors, 0, nsectors * sizeof *sectors);
216 esec = sectors + nsectors;
220 if (fm->fm_mapped_extents < 1 ||
221 !(fe[fm->fm_mapped_extents-1].fe_flags & FIEMAP_EXTENT_LAST))
224 for (i = 0; i < fm->fm_mapped_extents; i++) {
225 if (fe->fe_flags & FIEMAP_EXTENT_LAST) {
226 /* If this is the *final* extent, pad the length */
227 fe->fe_length = (fe->fe_length + SECTOR_SIZE - 1)
231 if ((fe->fe_logical | fe->fe_physical| fe->fe_length) &
235 if (fe->fe_flags & (FIEMAP_EXTENT_UNKNOWN|
236 FIEMAP_EXTENT_DELALLOC|
237 FIEMAP_EXTENT_ENCODED|
238 FIEMAP_EXTENT_DATA_ENCRYPTED|
239 FIEMAP_EXTENT_UNWRITTEN))
242 secp = sectors + (fe->fe_logical >> SECTOR_SHIFT);
243 sec = fe->fe_physical >> SECTOR_SHIFT;
244 nsec = fe->fe_length >> SECTOR_SHIFT;
258 /* Legacy FIBMAP based mapping */
259 static int sectmap_fib(int fd, sector_t *sectors, int nsectors)
261 unsigned int blk, nblk;
263 unsigned int blksize;
267 if (ioctl(fd, FIGETBSZ, &blksize))
270 /* Number of sectors per block */
271 blksize >>= SECTOR_SHIFT;
276 if (ioctl(fd, FIBMAP, &blk))
279 sec = (sector_t)blk * blksize;
280 for (i = 0; i < blksize; i++) {
293 int sectmap(int fd, sector_t *sectors, int nsectors)
295 if (!sectmap_fie(fd, sectors, nsectors))
298 return sectmap_fib(fd, sectors, nsectors);