dmi: check both the AC and ID flags at the same time
[syslinux.git] / libinstaller / syslxcom.c
blobefc6474df4feff9765650e04bbe7cc475d59c13a
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 * ----------------------------------------------------------------------- */
14 * syslxcom.c
16 * common functions for extlinux & syslinux installer
19 #define _GNU_SOURCE
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>
34 #include "linuxioctl.h"
35 #include "syslxrw.h"
36 #include "syslxcom.h"
37 #include "syslxfs.h"
39 const char *program;
41 int fs_type;
43 #ifdef DEBUG
44 # define dprintf printf
45 #else
46 # define dprintf(...) ((void)0)
47 #endif
49 #define SECTOR_SHIFT 9
52 * Set and clear file attributes
54 void clear_attributes(int fd)
56 struct stat st;
58 if (!fstat(fd, &st)) {
59 switch (fs_type) {
60 case EXT2:
62 int flags;
64 if (!ioctl(fd, FS_IOC_GETFLAGS, &flags)) {
65 flags &= ~FS_IMMUTABLE_FL;
66 ioctl(fd, FS_IOC_SETFLAGS, &flags);
68 break;
70 case VFAT:
72 uint32_t attr = 0x00; /* Clear all attributes */
73 ioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &attr);
74 break;
76 case NTFS:
77 break;
78 default:
79 break;
81 fchmod(fd, st.st_mode | S_IWUSR);
85 void set_attributes(int fd)
87 struct stat st;
89 if (!fstat(fd, &st)) {
90 fchmod(fd, st.st_mode & (S_IRUSR | S_IRGRP | S_IROTH));
91 switch (fs_type) {
92 case EXT2:
94 int flags;
96 if (st.st_uid == 0 && !ioctl(fd, FS_IOC_GETFLAGS, &flags)) {
97 flags |= FS_IMMUTABLE_FL;
98 ioctl(fd, FS_IOC_SETFLAGS, &flags);
100 break;
102 case VFAT:
104 uint32_t attr = 0x07; /* Hidden+System+Readonly */
105 ioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &attr);
106 break;
108 case NTFS:
109 break;
110 default:
111 break;
116 /* New FIEMAP based mapping */
117 static int sectmap_fie(int fd, sector_t *sectors, int nsectors)
119 struct fiemap *fm;
120 struct fiemap_extent *fe;
121 unsigned int i, nsec;
122 sector_t sec, *secp, *esec;
123 struct stat st;
124 uint64_t maplen;
126 if (fstat(fd, &st))
127 return -1;
129 fm = alloca(sizeof(struct fiemap)
130 + nsectors * sizeof(struct fiemap_extent));
132 memset(fm, 0, sizeof *fm);
134 maplen = (uint64_t)nsectors << SECTOR_SHIFT;
135 if (maplen > (uint64_t)st.st_size)
136 maplen = st.st_size;
138 fm->fm_start = 0;
139 fm->fm_length = maplen;
140 fm->fm_flags = FIEMAP_FLAG_SYNC;
141 fm->fm_extent_count = nsectors;
143 if (ioctl(fd, FS_IOC_FIEMAP, fm))
144 return -1;
146 memset(sectors, 0, nsectors * sizeof *sectors);
147 esec = sectors + nsectors;
149 fe = fm->fm_extents;
151 if (fm->fm_mapped_extents < 1 ||
152 !(fe[fm->fm_mapped_extents-1].fe_flags & FIEMAP_EXTENT_LAST))
153 return -1;
155 for (i = 0; i < fm->fm_mapped_extents; i++) {
156 if (fe->fe_flags & FIEMAP_EXTENT_LAST) {
157 /* If this is the *final* extent, pad the length */
158 fe->fe_length = (fe->fe_length + SECTOR_SIZE - 1)
159 & ~(SECTOR_SIZE - 1);
162 if ((fe->fe_logical | fe->fe_physical| fe->fe_length) &
163 (SECTOR_SIZE - 1))
164 return -1;
166 if (fe->fe_flags & (FIEMAP_EXTENT_UNKNOWN|
167 FIEMAP_EXTENT_DELALLOC|
168 FIEMAP_EXTENT_ENCODED|
169 FIEMAP_EXTENT_DATA_ENCRYPTED|
170 FIEMAP_EXTENT_UNWRITTEN))
171 return -1;
173 secp = sectors + (fe->fe_logical >> SECTOR_SHIFT);
174 sec = fe->fe_physical >> SECTOR_SHIFT;
175 nsec = fe->fe_length >> SECTOR_SHIFT;
177 while (nsec--) {
178 if (secp >= esec)
179 break;
180 *secp++ = sec++;
183 fe++;
186 return 0;
189 /* Legacy FIBMAP based mapping */
190 static int sectmap_fib(int fd, sector_t *sectors, int nsectors)
192 unsigned int blk, nblk;
193 unsigned int i;
194 unsigned int blksize;
195 sector_t sec;
197 /* Get block size */
198 if (ioctl(fd, FIGETBSZ, &blksize))
199 return -1;
201 /* Number of sectors per block */
202 blksize >>= SECTOR_SHIFT;
204 nblk = 0;
205 while (nsectors) {
206 blk = nblk++;
207 if (ioctl(fd, FIBMAP, &blk))
208 return -1;
210 sec = (sector_t)blk * blksize;
211 for (i = 0; i < blksize; i++) {
212 *sectors++ = sec++;
213 if (! --nsectors)
214 break;
218 return 0;
222 * Produce file map
224 int sectmap(int fd, sector_t *sectors, int nsectors)
226 if (!sectmap_fie(fd, sectors, nsectors))
227 return 0;
229 return sectmap_fib(fd, sectors, nsectors);
233 * SYSLINUX installs the string 'SYSLINUX' at offset 3 in the boot
234 * sector; this is consistent with FAT filesystems. Earlier versions
235 * would install the string "EXTLINUX" instead, handle both.
237 int syslinux_already_installed(int dev_fd)
239 char buffer[8];
241 xpread(dev_fd, buffer, 8, 3);
242 return !memcmp(buffer, "SYSLINUX", 8) || !memcmp(buffer, "EXTLINUX", 8);