From 108013b4178a6ad992d4c86fffb0d9351b8c02c5 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 18 Jan 2010 12:50:36 +0100 Subject: libblkid: restrict RAID/FS proving for small devices (1.4MiB) - don't ignore @size in blkid_probe_set_device() - ignore extremely small devices (<= 1024 bytes, e.g. extended partitions) - don't use safe probing for small devices - don't probe for RAIDs on small devices Signed-off-by: Karel Zak --- shlibs/blkid/src/blkidP.h | 4 +++- shlibs/blkid/src/probe.c | 37 ++++++++++++++++++++++++++---- shlibs/blkid/src/superblocks/superblocks.c | 27 ++++++++++++++++++---- 3 files changed, 58 insertions(+), 10 deletions(-) diff --git a/shlibs/blkid/src/blkidP.h b/shlibs/blkid/src/blkidP.h index 90900e27..20cf765a 100644 --- a/shlibs/blkid/src/blkidP.h +++ b/shlibs/blkid/src/blkidP.h @@ -357,7 +357,9 @@ extern blkid_dev blkid_new_dev(void); extern void blkid_free_dev(blkid_dev dev); /* probe.c */ -unsigned char *blkid_probe_get_buffer(blkid_probe pr, +extern int blkid_probe_is_tiny(blkid_probe pr); + +extern unsigned char *blkid_probe_get_buffer(blkid_probe pr, blkid_loff_t off, blkid_loff_t len); extern unsigned char *blkid_probe_get_sector(blkid_probe pr, unsigned int sector); diff --git a/shlibs/blkid/src/probe.c b/shlibs/blkid/src/probe.c index 7ed80072..6aad7ab4 100644 --- a/shlibs/blkid/src/probe.c +++ b/shlibs/blkid/src/probe.c @@ -471,17 +471,23 @@ int __blkid_probe_filter_types(blkid_probe pr, int chain, int flag, char *names[ } /* + * @off: offset within probing area + * @len: size of requested buffer + * + * The probing area is between pr->off and pr->size. The @off = 0 is pr->off, the + * max @len is pr->size. + * * Note that we have two offsets: * * 1/ general device offset (pr->off), that's useful for example when we * probe a partition from whole disk image: - * blkid-low --offset disk.img + * blkid -O -S disk.img * - * 2/ buffer offset (the 'off' argument), that useful for offsets in + * 2/ buffer offset (the @off argument), that useful for offsets in * superbloks, ... * - * That means never use lseek(fd, 0, SEEK_SET), the zero position is always - * pr->off, so lseek(fd, pr->off, SEEK_SET). + * That means never use lseek(fd, 0, SEEK_SET), the zero position is always + * pr->off, so lseek(fd, pr->off, SEEK_SET). * */ unsigned char *blkid_probe_get_buffer(blkid_probe pr, @@ -494,6 +500,13 @@ unsigned char *blkid_probe_get_buffer(blkid_probe pr, printf("unexpected offset or length of buffer requested\n")); return NULL; } + + if (off + len > pr->size) + return NULL; + + DBG(DEBUG_LOWPROBE, + printf("\tbuffer: offset=%jd size=%jd\n", off, len)); + if (off + len <= BLKID_SB_BUFSIZ) { if (!pr->sbbuf) { pr->sbbuf = malloc(BLKID_SB_BUFSIZ); @@ -525,7 +538,6 @@ unsigned char *blkid_probe_get_buffer(blkid_probe pr, } if (newbuf || off < pr->buf_off || off + len > pr->buf_off + pr->buf_len) { - if (blkid_llseek(pr->fd, pr->off + off, SEEK_SET) < 0) return NULL; @@ -539,6 +551,14 @@ unsigned char *blkid_probe_get_buffer(blkid_probe pr, } } +/* + * Small devices need a special care. + */ +int blkid_probe_is_tiny(blkid_probe pr) +{ + return (pr && pr->size <= 1440 * 1024 && !S_ISCHR(pr->mode)); +} + /** * blkid_probe_set_device: * @pr: probe @@ -589,6 +609,13 @@ int blkid_probe_set_device(blkid_probe pr, int fd, if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode)) pr->devno = sb.st_rdev; + + if (pr->off > pr->size) + goto err; + + /* The probing area cannot be larger than whole device, pr->off + * is offset within the device */ + pr->size -= pr->off; } if (!pr->size) diff --git a/shlibs/blkid/src/superblocks/superblocks.c b/shlibs/blkid/src/superblocks/superblocks.c index e77c511d..dbb48562 100644 --- a/shlibs/blkid/src/superblocks/superblocks.c +++ b/shlibs/blkid/src/superblocks/superblocks.c @@ -310,6 +310,12 @@ static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn) printf("--> starting probing loop [SUBLKS idx=%d]\n", chn->idx)); + if (pr->size <= 1024 && !S_ISCHR(pr->mode)) + /* Ignore very very small block devices or regular files (e.g. + * extended partitions). Note that size of the UBI char devices + * is 1 byte */ + return 1; + i = chn->idx + 1; for ( ; i < ARRAY_SIZE(idinfos); i++) { @@ -327,6 +333,12 @@ static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn) id = idinfos[i]; mag = id->magics ? &id->magics[0] : NULL; + /* don't probe for RAIDs on floppies */ + if ((id->usage & BLKID_USAGE_RAID) && blkid_probe_is_tiny(pr)) + continue; + + DBG(DEBUG_LOWPROBE, printf("[%d] %s:\n", i, id->name)); + /* try to detect by magic string */ while(mag && mag->magic) { unsigned char *buf; @@ -337,8 +349,8 @@ static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn) if (buf && !memcmp(mag->magic, buf + (mag->sboff & 0x3ff), mag->len)) { DBG(DEBUG_LOWPROBE, printf( - "%s: magic sboff=%u, kboff=%ld\n", - id->name, mag->sboff, mag->kboff)); + "\tmagic sboff=%u, kboff=%ld\n", + mag->sboff, mag->kboff)); hasmag = 1; off += mag->sboff & 0x3ff; break; @@ -352,8 +364,7 @@ static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn) /* final check by probing function */ if (id->probefunc) { - DBG(DEBUG_LOWPROBE, printf( - "%s: call probefunc()\n", id->name)); + DBG(DEBUG_LOWPROBE, printf("\tcall probefunc()\n")); if (id->probefunc(pr, mag) != 0) continue; } @@ -393,6 +404,9 @@ static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn) * The function does not check for filesystems when a RAID or crypto signature * is detected. The function also does not check for collision between RAIDs * and crypto devices. The first detected RAID or crypto device is returned. + * + * The function does not probe for ambivalent results on very small devices + * (e.g. floppies), on small devices the first detected filesystem is returned. */ static int superblocks_safeprobe(blkid_probe pr, struct blkid_chain *chn) { @@ -404,6 +418,11 @@ static int superblocks_safeprobe(blkid_probe pr, struct blkid_chain *chn) int rc; while ((rc = superblocks_probe(pr, chn)) == 0) { + + if (blkid_probe_is_tiny(pr) && !count) + /* floppy or so -- returns the first result. */ + return 0; + if (!count) { /* save the first result */ nvals = blkid_probe_chain_copy_vals(pr, chn, vals, nvals); -- cgit v1.2.3 From 1ca17f911a4a039941185077b285378129eafb09 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 18 Jan 2010 15:43:25 +0100 Subject: libblkid: read() optimization for small devices - don't read the begin (69kB) of the device by one large read() - fill in the SB buffer dynamically - use extra buffer for FATs root dir entries (FAT FS label) on small devices to avoid large reads Detect FAT12 on 1.4MB device (number of bytes): Old version: $ strace -e read blkid -p floppy.img 2>&1 | \ awk -F ' = ' 'BEGIN {x=0} /read/ && !/.*ELF/ {x += $2} END { print x }' 73292 New version: $ strace -e read blkid -p floppy.img 2>&1 | \ awk -F ' = ' 'BEGIN {x=0} /read/ && !/.*ELF/ {x += $2} END { print x }' 8192 Reported-by: Linus Torvalds Signed-off-by: Karel Zak --- shlibs/blkid/src/blkidP.h | 3 +- shlibs/blkid/src/probe.c | 149 ++++++++++++++++++++++++------------ shlibs/blkid/src/superblocks/vfat.c | 9 ++- 3 files changed, 106 insertions(+), 55 deletions(-) diff --git a/shlibs/blkid/src/blkidP.h b/shlibs/blkid/src/blkidP.h index 20cf765a..4a3ae200 100644 --- a/shlibs/blkid/src/blkidP.h +++ b/shlibs/blkid/src/blkidP.h @@ -358,9 +358,10 @@ extern void blkid_free_dev(blkid_dev dev); /* probe.c */ extern int blkid_probe_is_tiny(blkid_probe pr); - extern unsigned char *blkid_probe_get_buffer(blkid_probe pr, blkid_loff_t off, blkid_loff_t len); +extern unsigned char *blkid_probe_get_extra_buffer(blkid_probe pr, + blkid_loff_t off, blkid_loff_t len); extern unsigned char *blkid_probe_get_sector(blkid_probe pr, unsigned int sector); diff --git a/shlibs/blkid/src/probe.c b/shlibs/blkid/src/probe.c index 6aad7ab4..2d3cafec 100644 --- a/shlibs/blkid/src/probe.c +++ b/shlibs/blkid/src/probe.c @@ -470,6 +470,102 @@ int __blkid_probe_filter_types(blkid_probe pr, int chain, int flag, char *names[ return 0; } +static int blkid_probe_has_buffer(blkid_probe pr, + blkid_loff_t off, blkid_loff_t len) +{ + return pr && (off + len <= pr->sbbuf_len || + (pr->buf_off < off && off + len < pr->buf_len)); +} + +/* + * Returns buffer from the begin (69kB) of the device. + */ +static unsigned char *blkid_probe_get_sb_buffer(blkid_probe pr, + blkid_loff_t off, blkid_loff_t len) +{ + if (off + len > BLKID_SB_BUFSIZ) + return NULL; + if (!pr->sbbuf) { + pr->sbbuf = malloc(BLKID_SB_BUFSIZ); + if (!pr->sbbuf) + return NULL; + } + if (off + len > pr->sbbuf_len) { + /* + * The sbbuf is not completely in memory. + * + * We don't read whole BLKID_SB_BUFSIZ by one read(), it's too + * aggresive to small devices (floppies). We read necessary + * data to complete the current request (off + len) only. + */ + ssize_t ret_read; + + blkid_loff_t have = pr->sbbuf_len, + want = off + len - have; + + DBG(DEBUG_LOWPROBE, + printf("\tsb-buffer read() off=%jd len=%jd\n", have, want)); + + if (lseek(pr->fd, pr->off + have, SEEK_SET) < 0) + return NULL; + + ret_read = read(pr->fd, pr->sbbuf + have, want); + if (ret_read < 0) + ret_read = 0; + pr->sbbuf_len = have + ret_read; + } + if (off + len > pr->sbbuf_len) + return NULL; + return pr->sbbuf + off; +} + +/* + * Returns pointer to the buffer on arbitrary offset on the device + */ +unsigned char *blkid_probe_get_extra_buffer(blkid_probe pr, + blkid_loff_t off, blkid_loff_t len) +{ + unsigned char *newbuf = NULL; + + if (off + len <= BLKID_SB_BUFSIZ && + (!blkid_probe_is_tiny(pr) || blkid_probe_has_buffer(pr, off, len))) + /* + * Don't use extra buffer for superblock data if + * - data are already in SB buffer + * - or the device is large and we needn't extra + * optimalization for tiny devices + */ + return blkid_probe_get_sb_buffer(pr, off, len); + + if (len > pr->buf_max) { + newbuf = realloc(pr->buf, len); + if (!newbuf) + return NULL; + pr->buf = newbuf; + pr->buf_max = len; + pr->buf_off = 0; + pr->buf_len = 0; + } + if (newbuf || off < pr->buf_off || + off + len > pr->buf_off + pr->buf_len) { + ssize_t ret_read; + + if (blkid_llseek(pr->fd, pr->off + off, SEEK_SET) < 0) + return NULL; + + DBG(DEBUG_LOWPROBE, + printf("\textra-buffer read: off=%jd len=%jd\n", off, len)); + + ret_read = read(pr->fd, pr->buf, len); + if (ret_read != (ssize_t) len) + return NULL; + pr->buf_off = off; + pr->buf_len = len; + } + return off ? pr->buf + (off - pr->buf_off) : pr->buf; +} + + /* * @off: offset within probing area * @len: size of requested buffer @@ -493,62 +589,16 @@ int __blkid_probe_filter_types(blkid_probe pr, int chain, int flag, char *names[ unsigned char *blkid_probe_get_buffer(blkid_probe pr, blkid_loff_t off, blkid_loff_t len) { - ssize_t ret_read = 0; - if (off < 0 || len < 0) { DBG(DEBUG_LOWPROBE, printf("unexpected offset or length of buffer requested\n")); return NULL; } - if (off + len > pr->size) return NULL; - - DBG(DEBUG_LOWPROBE, - printf("\tbuffer: offset=%jd size=%jd\n", off, len)); - - if (off + len <= BLKID_SB_BUFSIZ) { - if (!pr->sbbuf) { - pr->sbbuf = malloc(BLKID_SB_BUFSIZ); - if (!pr->sbbuf) - return NULL; - } - if (!pr->sbbuf_len) { - if (lseek(pr->fd, pr->off, SEEK_SET) < 0) - return NULL; - ret_read = read(pr->fd, pr->sbbuf, BLKID_SB_BUFSIZ); - if (ret_read < 0) - ret_read = 0; - pr->sbbuf_len = ret_read; - } - if (off + len > pr->sbbuf_len) - return NULL; - return pr->sbbuf + off; - } else { - unsigned char *newbuf = NULL; - - if (len > pr->buf_max) { - newbuf = realloc(pr->buf, len); - if (!newbuf) - return NULL; - pr->buf = newbuf; - pr->buf_max = len; - pr->buf_off = 0; - pr->buf_len = 0; - } - if (newbuf || off < pr->buf_off || - off + len > pr->buf_off + pr->buf_len) { - if (blkid_llseek(pr->fd, pr->off + off, SEEK_SET) < 0) - return NULL; - - ret_read = read(pr->fd, pr->buf, len); - if (ret_read != (ssize_t) len) - return NULL; - pr->buf_off = off; - pr->buf_len = len; - } - return off ? pr->buf + (off - pr->buf_off) : pr->buf; - } + if (off + len <= BLKID_SB_BUFSIZ) + return blkid_probe_get_sb_buffer(pr, off, len); + return blkid_probe_get_extra_buffer(pr, off, len); } /* @@ -620,7 +670,6 @@ int blkid_probe_set_device(blkid_probe pr, int fd, if (!pr->size) goto err; - DBG(DEBUG_LOWPROBE, printf("ready for low-probing, offset=%zd, size=%zd\n", pr->off, pr->size)); return 0; diff --git a/shlibs/blkid/src/superblocks/vfat.c b/shlibs/blkid/src/superblocks/vfat.c index 7587f8dd..8ea6b087 100644 --- a/shlibs/blkid/src/superblocks/vfat.c +++ b/shlibs/blkid/src/superblocks/vfat.c @@ -248,8 +248,9 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag) (vs->vs_dir_entries[1] << 8); buf_size = root_dir_entries * sizeof(struct vfat_dir_entry); + dir = (struct vfat_dir_entry *) - blkid_probe_get_buffer(pr, root_start, buf_size); + blkid_probe_get_extra_buffer(pr, root_start, buf_size); if (dir) vol_label = search_fat_label(dir, root_dir_entries); @@ -285,7 +286,7 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag) sector_size; dir = (struct vfat_dir_entry *) - blkid_probe_get_buffer(pr, next_off, buf_size); + blkid_probe_get_extra_buffer(pr, next_off, buf_size); if (dir == NULL) break; @@ -298,7 +299,7 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag) /* get FAT entry */ fat_entry_off = (reserved * sector_size) + (next * sizeof(uint32_t)); - buf = blkid_probe_get_buffer(pr, fat_entry_off, buf_size); + buf = blkid_probe_get_extra_buffer(pr, fat_entry_off, buf_size); if (buf == NULL) break; @@ -319,7 +320,7 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag) if (fsinfo_sect) { struct fat32_fsinfo *fsinfo; - buf = blkid_probe_get_buffer(pr, + buf = blkid_probe_get_extra_buffer(pr, fsinfo_sect * sector_size, sizeof(struct fat32_fsinfo)); if (buf == NULL) -- cgit v1.2.3 From 49b1508ee28577deea76654de5c27401f99c36f8 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 18 Jan 2010 16:49:38 +0100 Subject: tests: fix RAIDs tests - test images was too small (limit is 1474560 bytes) Signed-off-by: Karel Zak --- tests/ts/blkid/images-fs/adaptec-raid.img.bz2 | Bin 250 -> 256 bytes tests/ts/blkid/images-fs/ddf-raid.img.bz2 | Bin 534 -> 535 bytes tests/ts/blkid/images-fs/hpt37x-raid.img.bz2 | Bin 116 -> 123 bytes tests/ts/blkid/images-fs/isw-raid.img.bz2 | Bin 252 -> 251 bytes tests/ts/blkid/images-fs/jmicron-raid.img.bz2 | Bin 158 -> 159 bytes tests/ts/blkid/images-fs/lvm2.img.bz2 | Bin 173 -> 177 bytes tests/ts/blkid/images-fs/nvidia-raid.img.bz2 | Bin 170 -> 175 bytes tests/ts/blkid/images-fs/promise-raid.img.bz2 | Bin 781 -> 784 bytes tests/ts/blkid/images-fs/romfs.img.bz2 | Bin 105 -> 115 bytes tests/ts/blkid/images-fs/silicon-raid.img.bz2 | Bin 321 -> 328 bytes tests/ts/blkid/images-fs/via-raid.img.bz2 | Bin 97 -> 99 bytes tests/ts/blkid/images-fs/vmfs_volume.img.bz2 | Bin 276 -> 287 bytes 12 files changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/ts/blkid/images-fs/adaptec-raid.img.bz2 b/tests/ts/blkid/images-fs/adaptec-raid.img.bz2 index 63e66946..d3c10d79 100644 Binary files a/tests/ts/blkid/images-fs/adaptec-raid.img.bz2 and b/tests/ts/blkid/images-fs/adaptec-raid.img.bz2 differ diff --git a/tests/ts/blkid/images-fs/ddf-raid.img.bz2 b/tests/ts/blkid/images-fs/ddf-raid.img.bz2 index 1dc48925..c8f0c8ac 100644 Binary files a/tests/ts/blkid/images-fs/ddf-raid.img.bz2 and b/tests/ts/blkid/images-fs/ddf-raid.img.bz2 differ diff --git a/tests/ts/blkid/images-fs/hpt37x-raid.img.bz2 b/tests/ts/blkid/images-fs/hpt37x-raid.img.bz2 index 91ad30bc..52e13bb3 100644 Binary files a/tests/ts/blkid/images-fs/hpt37x-raid.img.bz2 and b/tests/ts/blkid/images-fs/hpt37x-raid.img.bz2 differ diff --git a/tests/ts/blkid/images-fs/isw-raid.img.bz2 b/tests/ts/blkid/images-fs/isw-raid.img.bz2 index 4bac5708..9214c96f 100644 Binary files a/tests/ts/blkid/images-fs/isw-raid.img.bz2 and b/tests/ts/blkid/images-fs/isw-raid.img.bz2 differ diff --git a/tests/ts/blkid/images-fs/jmicron-raid.img.bz2 b/tests/ts/blkid/images-fs/jmicron-raid.img.bz2 index 337dd051..3b4b2367 100644 Binary files a/tests/ts/blkid/images-fs/jmicron-raid.img.bz2 and b/tests/ts/blkid/images-fs/jmicron-raid.img.bz2 differ diff --git a/tests/ts/blkid/images-fs/lvm2.img.bz2 b/tests/ts/blkid/images-fs/lvm2.img.bz2 index a699b84b..7bb84bf4 100644 Binary files a/tests/ts/blkid/images-fs/lvm2.img.bz2 and b/tests/ts/blkid/images-fs/lvm2.img.bz2 differ diff --git a/tests/ts/blkid/images-fs/nvidia-raid.img.bz2 b/tests/ts/blkid/images-fs/nvidia-raid.img.bz2 index c2d13c73..21f062e1 100644 Binary files a/tests/ts/blkid/images-fs/nvidia-raid.img.bz2 and b/tests/ts/blkid/images-fs/nvidia-raid.img.bz2 differ diff --git a/tests/ts/blkid/images-fs/promise-raid.img.bz2 b/tests/ts/blkid/images-fs/promise-raid.img.bz2 index efb3de54..64a5a08b 100644 Binary files a/tests/ts/blkid/images-fs/promise-raid.img.bz2 and b/tests/ts/blkid/images-fs/promise-raid.img.bz2 differ diff --git a/tests/ts/blkid/images-fs/romfs.img.bz2 b/tests/ts/blkid/images-fs/romfs.img.bz2 index b5e31099..f94d77b6 100644 Binary files a/tests/ts/blkid/images-fs/romfs.img.bz2 and b/tests/ts/blkid/images-fs/romfs.img.bz2 differ diff --git a/tests/ts/blkid/images-fs/silicon-raid.img.bz2 b/tests/ts/blkid/images-fs/silicon-raid.img.bz2 index c75b7653..e3ccbf97 100644 Binary files a/tests/ts/blkid/images-fs/silicon-raid.img.bz2 and b/tests/ts/blkid/images-fs/silicon-raid.img.bz2 differ diff --git a/tests/ts/blkid/images-fs/via-raid.img.bz2 b/tests/ts/blkid/images-fs/via-raid.img.bz2 index 99569704..9266f5e9 100644 Binary files a/tests/ts/blkid/images-fs/via-raid.img.bz2 and b/tests/ts/blkid/images-fs/via-raid.img.bz2 differ diff --git a/tests/ts/blkid/images-fs/vmfs_volume.img.bz2 b/tests/ts/blkid/images-fs/vmfs_volume.img.bz2 index 77f0a6a2..cc0ec664 100644 Binary files a/tests/ts/blkid/images-fs/vmfs_volume.img.bz2 and b/tests/ts/blkid/images-fs/vmfs_volume.img.bz2 differ -- cgit v1.2.3 From 45835b734574264fcd45d9e6c1736061f6f7c200 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 18 Jan 2010 23:58:46 +0100 Subject: libblkid: call read() per FAT root dir entry Signed-off-by: Karel Zak --- shlibs/blkid/src/superblocks/vfat.c | 50 ++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/shlibs/blkid/src/superblocks/vfat.c b/shlibs/blkid/src/superblocks/vfat.c index 8ea6b087..1662f131 100644 --- a/shlibs/blkid/src/superblocks/vfat.c +++ b/shlibs/blkid/src/superblocks/vfat.c @@ -111,22 +111,29 @@ struct fat32_fsinfo { static const char *no_name = "NO NAME "; -static unsigned char *search_fat_label(struct vfat_dir_entry *dir, int count) +static unsigned char *search_fat_label(blkid_probe pr, + uint32_t offset, uint32_t entries) { + struct vfat_dir_entry *dir; int i; - for (i = 0; i < count; i++) { - if (dir[i].name[0] == 0x00) + for (i = 0; i < entries; i++) { + + dir = (struct vfat_dir_entry *) + blkid_probe_get_extra_buffer(pr, + offset + (i * sizeof(struct vfat_dir_entry)), + sizeof(struct vfat_dir_entry)); + if (dir->name[0] == 0x00) break; - if ((dir[i].name[0] == FAT_ENTRY_FREE) || - (dir[i].cluster_high != 0 || dir[i].cluster_low != 0) || - ((dir[i].attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME)) + if ((dir->name[0] == FAT_ENTRY_FREE) || + (dir->cluster_high != 0 || dir->cluster_low != 0) || + ((dir->attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME)) continue; - if ((dir[i].attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == + if ((dir->attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == FAT_ATTR_VOLUME_ID) { - return dir[i].name; + return dir->name; } } return 0; @@ -188,9 +195,8 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag) { struct vfat_super_block *vs; struct msdos_super_block *ms; - struct vfat_dir_entry *dir; const unsigned char *vol_label = 0, *tmp; - unsigned char *vol_serno; + unsigned char *vol_serno, vol_label_buf[11]; int maxloop = 100; uint16_t sector_size, dir_entries, reserved; uint32_t sect_count, fat_size, dir_size, cluster_count, fat_length; @@ -198,6 +204,7 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag) const char *version = NULL; + /* non-standard magic strings */ if (mag->len <= 2 && probe_fat_nomagic(pr, mag) != 0) return 1; @@ -247,12 +254,11 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag) root_dir_entries = vs->vs_dir_entries[0] + (vs->vs_dir_entries[1] << 8); - buf_size = root_dir_entries * sizeof(struct vfat_dir_entry); - - dir = (struct vfat_dir_entry *) - blkid_probe_get_extra_buffer(pr, root_start, buf_size); - if (dir) - vol_label = search_fat_label(dir, root_dir_entries); + vol_label = search_fat_label(pr, root_start, root_dir_entries); + if (vol_label) { + memcpy(vol_label_buf, vol_label, 11); + vol_label = vol_label_buf; + } if (!vol_label || !memcmp(vol_label, no_name, 11)) vol_label = ms->ms_label; @@ -285,16 +291,14 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag) next_off = (start_data_sect + next_sect_off) * sector_size; - dir = (struct vfat_dir_entry *) - blkid_probe_get_extra_buffer(pr, next_off, buf_size); - if (dir == NULL) - break; - count = buf_size / sizeof(struct vfat_dir_entry); - vol_label = search_fat_label(dir, count); - if (vol_label) + vol_label = search_fat_label(pr, next_off, count); + if (vol_label) { + memcpy(vol_label_buf, vol_label, 11); + vol_label = vol_label_buf; break; + } /* get FAT entry */ fat_entry_off = (reserved * sector_size) + -- cgit v1.2.3 From a67bb3bff5dc51400294fdfb4c77c0827afd5d14 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 19 Jan 2010 00:09:21 +0100 Subject: libblkid: disable read-ahead when probing device files Read-ahead doesn't work very well on device probing, and can hurt a lot when we do essentially random accesses on very slow devices. So disable it if possible. [kzak@redhat.com: - add posix_fadvise() configure test] Signed-off-by: Linus Torvalds Signed-off-by: Karel Zak --- configure.ac | 1 + shlibs/blkid/src/probe.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/configure.ac b/configure.ac index 5ddeaa5d..1fef9444 100644 --- a/configure.ac +++ b/configure.ac @@ -163,6 +163,7 @@ AC_CHECK_FUNCS( setresuid \ inotify_init \ prctl \ + posix_fadvise \ getmntinfo \ __secure_getenv \ rpmatch]) diff --git a/shlibs/blkid/src/probe.c b/shlibs/blkid/src/probe.c index 2d3cafec..b2c96a6b 100644 --- a/shlibs/blkid/src/probe.c +++ b/shlibs/blkid/src/probe.c @@ -640,6 +640,10 @@ int blkid_probe_set_device(blkid_probe pr, int fd, pr->mode = 0; pr->blkssz = 0; +#if defined(POSIX_FADV_RANDOM) && defined(HAVE_POSIX_FADVISE) + /* Disable read-ahead */ + posix_fadvise(fd, 0, 0, POSIX_FADV_RANDOM); +#endif if (size) pr->size = size; else { -- cgit v1.2.3 From 8c2b156e5a0893a0a82af82c50205b0a78352151 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 19 Jan 2010 01:12:06 +0100 Subject: libblkid: set minimal size for jfs, reiser, swap and zfs .. and don't probe for swap or ext. journal on tiny disks. Signed-off-by: Karel Zak --- shlibs/blkid/src/blkidP.h | 1 + shlibs/blkid/src/superblocks/jfs.c | 1 + shlibs/blkid/src/superblocks/reiserfs.c | 2 ++ shlibs/blkid/src/superblocks/superblocks.c | 9 +++++++-- shlibs/blkid/src/superblocks/swap.c | 2 ++ shlibs/blkid/src/superblocks/zfs.c | 1 + 6 files changed, 14 insertions(+), 2 deletions(-) diff --git a/shlibs/blkid/src/blkidP.h b/shlibs/blkid/src/blkidP.h index 4a3ae200..55850349 100644 --- a/shlibs/blkid/src/blkidP.h +++ b/shlibs/blkid/src/blkidP.h @@ -155,6 +155,7 @@ struct blkid_idinfo const char *name; /* fs, raid or partition table name */ int usage; /* BLKID_USAGE_* flag */ int flags; /* BLKID_IDINFO_* flags */ + int minsz; /* minimal device size */ /* probe function */ int (*probefunc)(blkid_probe pr, const struct blkid_idmag *mag); diff --git a/shlibs/blkid/src/superblocks/jfs.c b/shlibs/blkid/src/superblocks/jfs.c index e6e44505..9a49c674 100644 --- a/shlibs/blkid/src/superblocks/jfs.c +++ b/shlibs/blkid/src/superblocks/jfs.c @@ -61,6 +61,7 @@ const struct blkid_idinfo jfs_idinfo = .name = "jfs", .usage = BLKID_USAGE_FILESYSTEM, .probefunc = probe_jfs, + .minsz = 16 * 1024 * 1024, .magics = { { .magic = "JFS1", .len = 4, .kboff = 32 }, diff --git a/shlibs/blkid/src/superblocks/reiserfs.c b/shlibs/blkid/src/superblocks/reiserfs.c index 4222a307..921f5237 100644 --- a/shlibs/blkid/src/superblocks/reiserfs.c +++ b/shlibs/blkid/src/superblocks/reiserfs.c @@ -98,6 +98,7 @@ const struct blkid_idinfo reiser_idinfo = .name = "reiserfs", .usage = BLKID_USAGE_FILESYSTEM, .probefunc = probe_reiser, + .minsz = 4096 * 512, /* not sure, this is minimal size of journal */ .magics = { { .magic = "ReIsErFs", .len = 8, .kboff = 8, .sboff = 0x34 }, @@ -114,6 +115,7 @@ const struct blkid_idinfo reiser4_idinfo = .name = "reiser4", .usage = BLKID_USAGE_FILESYSTEM, .probefunc = probe_reiser4, + .minsz = 4096 * 512, /* not sure, this is minimal size of journal */ .magics = { { .magic = "ReIsEr4", .len = 7, .kboff = 64 }, diff --git a/shlibs/blkid/src/superblocks/superblocks.c b/shlibs/blkid/src/superblocks/superblocks.c index dbb48562..689f31bd 100644 --- a/shlibs/blkid/src/superblocks/superblocks.c +++ b/shlibs/blkid/src/superblocks/superblocks.c @@ -331,10 +331,15 @@ static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn) continue; id = idinfos[i]; + + if (id->minsz && id->minsz > pr->size) + continue; /* the device is too small */ + mag = id->magics ? &id->magics[0] : NULL; - /* don't probe for RAIDs on floppies */ - if ((id->usage & BLKID_USAGE_RAID) && blkid_probe_is_tiny(pr)) + /* don't probe for RAIDs, swap or journal on floppies */ + if ((id->usage & (BLKID_USAGE_RAID | BLKID_USAGE_OTHER)) && + blkid_probe_is_tiny(pr)) continue; DBG(DEBUG_LOWPROBE, printf("[%d] %s:\n", i, id->name)); diff --git a/shlibs/blkid/src/superblocks/swap.c b/shlibs/blkid/src/superblocks/swap.c index 4fb4ab7a..8aaa6f31 100644 --- a/shlibs/blkid/src/superblocks/swap.c +++ b/shlibs/blkid/src/superblocks/swap.c @@ -99,6 +99,7 @@ const struct blkid_idinfo swap_idinfo = .name = "swap", .usage = BLKID_USAGE_OTHER, .probefunc = probe_swap, + .minsz = 10 * 4096, /* 10 pages */ .magics = { { "SWAP-SPACE", 10, 0, 0xff6 }, @@ -121,6 +122,7 @@ const struct blkid_idinfo swsuspend_idinfo = .name = "swsuspend", .usage = BLKID_USAGE_OTHER, .probefunc = probe_swsuspend, + .minsz = 10 * 4096, /* 10 pages */ .magics = { { "S1SUSPEND", 9, 0, 0xff6 }, diff --git a/shlibs/blkid/src/superblocks/zfs.c b/shlibs/blkid/src/superblocks/zfs.c index 2d626427..0f580262 100644 --- a/shlibs/blkid/src/superblocks/zfs.c +++ b/shlibs/blkid/src/superblocks/zfs.c @@ -54,6 +54,7 @@ const struct blkid_idinfo zfs_idinfo = .name = "zfs", .usage = BLKID_USAGE_FILESYSTEM, .probefunc = probe_zfs, + .minsz = 64 * 1024 * 1024, .magics = { { .magic = "\0\0\x02\xf5\xb0\x07\xb1\x0c", .len = 8, .kboff = 8 }, -- cgit v1.2.3 From d0465c3c00f75d7247cbbf02c1b3ff879c3f7bd3 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 19 Jan 2010 13:43:39 +0100 Subject: libblkid: read whole SB buffer (69kB) on large disks - on large disks read whole SB buffer - new blkid_probe_is_tiny() version based on flags Signed-off-by: Karel Zak --- shlibs/blkid/src/blkidP.h | 3 +++ shlibs/blkid/src/probe.c | 26 ++++++++++++++++++-------- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/shlibs/blkid/src/blkidP.h b/shlibs/blkid/src/blkidP.h index 55850349..fb40505b 100644 --- a/shlibs/blkid/src/blkidP.h +++ b/shlibs/blkid/src/blkidP.h @@ -204,6 +204,7 @@ struct blkid_struct_probe /* flags */ #define BLKID_PRIVATE_FD (1 << 1) /* see blkid_new_probe_from_filename() */ +#define BLKID_TINY_DEV (1 << 2) /* <= 1.47MiB (floppy or so) */ /* * Evaluation methods (for blkid_eval_* API) @@ -359,6 +360,8 @@ extern void blkid_free_dev(blkid_dev dev); /* probe.c */ extern int blkid_probe_is_tiny(blkid_probe pr); +extern int blkid_probe_has_buffer(blkid_probe pr, + blkid_loff_t off, blkid_loff_t len); extern unsigned char *blkid_probe_get_buffer(blkid_probe pr, blkid_loff_t off, blkid_loff_t len); extern unsigned char *blkid_probe_get_extra_buffer(blkid_probe pr, diff --git a/shlibs/blkid/src/probe.c b/shlibs/blkid/src/probe.c index b2c96a6b..1bd98b55 100644 --- a/shlibs/blkid/src/probe.c +++ b/shlibs/blkid/src/probe.c @@ -470,7 +470,7 @@ int __blkid_probe_filter_types(blkid_probe pr, int chain, int flag, char *names[ return 0; } -static int blkid_probe_has_buffer(blkid_probe pr, +int blkid_probe_has_buffer(blkid_probe pr, blkid_loff_t off, blkid_loff_t len) { return pr && (off + len <= pr->sbbuf_len || @@ -494,14 +494,20 @@ static unsigned char *blkid_probe_get_sb_buffer(blkid_probe pr, /* * The sbbuf is not completely in memory. * - * We don't read whole BLKID_SB_BUFSIZ by one read(), it's too - * aggresive to small devices (floppies). We read necessary - * data to complete the current request (off + len) only. */ ssize_t ret_read; - - blkid_loff_t have = pr->sbbuf_len, - want = off + len - have; + blkid_loff_t want, have = pr->sbbuf_len; + + if (blkid_probe_is_tiny(pr)) + /* We don't read whole BLKID_SB_BUFSIZ by one read(), + * it's too aggresive to small devices (floppies). We + * read necessary data to complete the current request + * (off + len) only. + */ + want = off + len - have; + else + /* large disk -- read all SB */ + want = BLKID_SB_BUFSIZ - have; DBG(DEBUG_LOWPROBE, printf("\tsb-buffer read() off=%jd len=%jd\n", have, want)); @@ -606,7 +612,7 @@ unsigned char *blkid_probe_get_buffer(blkid_probe pr, */ int blkid_probe_is_tiny(blkid_probe pr) { - return (pr && pr->size <= 1440 * 1024 && !S_ISCHR(pr->mode)); + return pr && (pr->flags & BLKID_TINY_DEV); } /** @@ -676,6 +682,10 @@ int blkid_probe_set_device(blkid_probe pr, int fd, goto err; DBG(DEBUG_LOWPROBE, printf("ready for low-probing, offset=%zd, size=%zd\n", pr->off, pr->size)); + + if (pr->size <= 1440 * 1024 && !S_ISCHR(pr->mode)) + pr->flags |= BLKID_TINY_DEV; + return 0; err: DBG(DEBUG_LOWPROBE, -- cgit v1.2.3 From a47b2ddd0ab6600b53f30b0eaeb67a0d8b3e8668 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 19 Jan 2010 13:45:51 +0100 Subject: libblkid: don't call read() per FAT dir-entry on large disks Signed-off-by: Karel Zak --- shlibs/blkid/src/superblocks/vfat.c | 45 +++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/shlibs/blkid/src/superblocks/vfat.c b/shlibs/blkid/src/superblocks/vfat.c index 1662f131..29066c34 100644 --- a/shlibs/blkid/src/superblocks/vfat.c +++ b/shlibs/blkid/src/superblocks/vfat.c @@ -111,32 +111,59 @@ struct fat32_fsinfo { static const char *no_name = "NO NAME "; +/* + * Look for LABEL (name) in the FAT root directory. + */ static unsigned char *search_fat_label(blkid_probe pr, uint32_t offset, uint32_t entries) { - struct vfat_dir_entry *dir; + struct vfat_dir_entry *ent, *dir = NULL; int i; - for (i = 0; i < entries; i++) { + DBG(DEBUG_LOWPROBE, + printf("\tlook for label in root-dir " + "(entries: %d, offset: %d)\n", entries, offset)); + if (!blkid_probe_is_tiny(pr)) { + /* large disk, read whole root directory */ dir = (struct vfat_dir_entry *) + blkid_probe_get_buffer(pr, + offset, + entries * sizeof(struct vfat_dir_entry)); + if (!dir) + return NULL; + } + + for (i = 0; i < entries; i++) { + /* + * The root directory could be relatively large (4-16kB). + * Fortunately, the LABEL is usually the first entry in the + * directory. On tiny disks we call read() per entry. + */ + if (!dir) + ent = (struct vfat_dir_entry *) blkid_probe_get_extra_buffer(pr, offset + (i * sizeof(struct vfat_dir_entry)), sizeof(struct vfat_dir_entry)); - if (dir->name[0] == 0x00) + else + ent = &dir[i]; + + if (!ent || ent->name[0] == 0x00) break; - if ((dir->name[0] == FAT_ENTRY_FREE) || - (dir->cluster_high != 0 || dir->cluster_low != 0) || - ((dir->attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME)) + if ((ent->name[0] == FAT_ENTRY_FREE) || + (ent->cluster_high != 0 || ent->cluster_low != 0) || + ((ent->attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME)) continue; - if ((dir->attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == + if ((ent->attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == FAT_ATTR_VOLUME_ID) { - return dir->name; + DBG(DEBUG_LOWPROBE, + printf("\tfound fs LABEL at entry %d\n", i)); + return ent->name; } } - return 0; + return NULL; } /* -- cgit v1.2.3 From 5c5cc18b8439fee874dd54603b0ca70f4616f2ba Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 19 Jan 2010 16:23:14 +0100 Subject: libblkid: add minimal sizes for OCFS and GFS Signed-off-by: Karel Zak --- shlibs/blkid/src/superblocks/gfs.c | 2 ++ shlibs/blkid/src/superblocks/ocfs.c | 3 +++ 2 files changed, 5 insertions(+) diff --git a/shlibs/blkid/src/superblocks/gfs.c b/shlibs/blkid/src/superblocks/gfs.c index 8ad81bcb..b2c01630 100644 --- a/shlibs/blkid/src/superblocks/gfs.c +++ b/shlibs/blkid/src/superblocks/gfs.c @@ -108,6 +108,7 @@ const struct blkid_idinfo gfs_idinfo = .name = "gfs", .usage = BLKID_USAGE_FILESYSTEM, .probefunc = probe_gfs, + .minsz = 32 * 1024 * 1024, /* minimal size of GFS journal */ .magics = { { .magic = "\x01\x16\x19\x70", .len = 4, .kboff = 64 }, @@ -120,6 +121,7 @@ const struct blkid_idinfo gfs2_idinfo = .name = "gfs2", .usage = BLKID_USAGE_FILESYSTEM, .probefunc = probe_gfs2, + .minsz = 32 * 1024 * 1024, /* minimal size of GFS journal */ .magics = { { .magic = "\x01\x16\x19\x70", .len = 4, .kboff = 64 }, diff --git a/shlibs/blkid/src/superblocks/ocfs.c b/shlibs/blkid/src/superblocks/ocfs.c index 6e58b37a..9dbf41b1 100644 --- a/shlibs/blkid/src/superblocks/ocfs.c +++ b/shlibs/blkid/src/superblocks/ocfs.c @@ -174,6 +174,7 @@ const struct blkid_idinfo ocfs_idinfo = .name = "ocfs", .usage = BLKID_USAGE_FILESYSTEM, .probefunc = probe_ocfs, + .minsz = 108 * 1024 * 1024, .magics = { { .magic = "OracleCFS", .len = 9, .kboff = 8 }, @@ -186,6 +187,7 @@ const struct blkid_idinfo ocfs2_idinfo = .name = "ocfs2", .usage = BLKID_USAGE_FILESYSTEM, .probefunc = probe_ocfs2, + .minsz = 108 * 1024 * 1024, .magics = { { .magic = "OCFSV2", .len = 6, .kboff = 1 }, @@ -196,6 +198,7 @@ const struct blkid_idinfo ocfs2_idinfo = } }; +/* Oracle ASM (Automatic Storage Management) */ const struct blkid_idinfo oracleasm_idinfo = { .name = "oracleasm", -- cgit v1.2.3 From 4ccbf1388ecbff83f578c3052b437d0aab74cb90 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 19 Jan 2010 16:46:08 +0100 Subject: tests: update FS test images Signed-off-by: Karel Zak --- tests/ts/blkid/images-fs/gfs2.img.bz2 | Bin 121 -> 130 bytes tests/ts/blkid/images-fs/jbd.img.bz2 | Bin 205 -> 214 bytes tests/ts/blkid/images-fs/ocfs2.img.bz2 | Bin 1002 -> 1070 bytes tests/ts/blkid/images-fs/reiser4.img.bz2 | Bin 366 -> 372 bytes tests/ts/blkid/images-fs/swap0.img.bz2 | Bin 72 -> 75 bytes tests/ts/blkid/images-fs/swap1.img.bz2 | Bin 120 -> 121 bytes tests/ts/blkid/images-fs/zfs.img.bz2 | Bin 10869 -> 10912 bytes 7 files changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/ts/blkid/images-fs/gfs2.img.bz2 b/tests/ts/blkid/images-fs/gfs2.img.bz2 index e465df50..bab2f901 100644 Binary files a/tests/ts/blkid/images-fs/gfs2.img.bz2 and b/tests/ts/blkid/images-fs/gfs2.img.bz2 differ diff --git a/tests/ts/blkid/images-fs/jbd.img.bz2 b/tests/ts/blkid/images-fs/jbd.img.bz2 index f0d7f918..e6c4fc43 100644 Binary files a/tests/ts/blkid/images-fs/jbd.img.bz2 and b/tests/ts/blkid/images-fs/jbd.img.bz2 differ diff --git a/tests/ts/blkid/images-fs/ocfs2.img.bz2 b/tests/ts/blkid/images-fs/ocfs2.img.bz2 index 0bad915f..7e203dae 100644 Binary files a/tests/ts/blkid/images-fs/ocfs2.img.bz2 and b/tests/ts/blkid/images-fs/ocfs2.img.bz2 differ diff --git a/tests/ts/blkid/images-fs/reiser4.img.bz2 b/tests/ts/blkid/images-fs/reiser4.img.bz2 index b50d12e4..d07571eb 100644 Binary files a/tests/ts/blkid/images-fs/reiser4.img.bz2 and b/tests/ts/blkid/images-fs/reiser4.img.bz2 differ diff --git a/tests/ts/blkid/images-fs/swap0.img.bz2 b/tests/ts/blkid/images-fs/swap0.img.bz2 index e61e375b..d027b6fb 100644 Binary files a/tests/ts/blkid/images-fs/swap0.img.bz2 and b/tests/ts/blkid/images-fs/swap0.img.bz2 differ diff --git a/tests/ts/blkid/images-fs/swap1.img.bz2 b/tests/ts/blkid/images-fs/swap1.img.bz2 index fbab9edb..37adedd9 100644 Binary files a/tests/ts/blkid/images-fs/swap1.img.bz2 and b/tests/ts/blkid/images-fs/swap1.img.bz2 differ diff --git a/tests/ts/blkid/images-fs/zfs.img.bz2 b/tests/ts/blkid/images-fs/zfs.img.bz2 index 92f445a3..dfaaef01 100644 Binary files a/tests/ts/blkid/images-fs/zfs.img.bz2 and b/tests/ts/blkid/images-fs/zfs.img.bz2 differ -- cgit v1.2.3 From 15a8fb429ce7d07d19a7f0044a85f0919fe57b27 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 20 Jan 2010 20:01:59 +0100 Subject: libblkid: rewrite blkid_probe_get_buffer() The library does not use any buffer with fixed size any more. The new version calls read() for necessary data only. Signed-off-by: Karel Zak --- shlibs/blkid/src/blkidP.h | 21 ++-- shlibs/blkid/src/probe.c | 187 +++++++++++------------------------- shlibs/blkid/src/superblocks/vfat.c | 6 +- 3 files changed, 68 insertions(+), 146 deletions(-) diff --git a/shlibs/blkid/src/blkidP.h b/shlibs/blkid/src/blkidP.h index fb40505b..975878c4 100644 --- a/shlibs/blkid/src/blkidP.h +++ b/shlibs/blkid/src/blkidP.h @@ -133,8 +133,6 @@ struct blkid_prval struct blkid_chain *chain; /* owner */ }; -#define BLKID_SB_BUFSIZ 0x11000 - /* * Filesystem / Raid magic strings */ @@ -172,6 +170,13 @@ struct blkid_idinfo */ #define BLKID_IDINFO_TOLERANT (1 << 1) +struct blkid_bufinfo { + unsigned char *data; + blkid_loff_t off; + blkid_loff_t len; + struct list_head bufs; /* list of buffers */ +}; + /* * Low-level probing control struct */ @@ -187,13 +192,7 @@ struct blkid_struct_probe int flags; /* private libray flags */ - unsigned char *sbbuf; /* superblok buffer */ - size_t sbbuf_len; /* size of data in superblock buffer */ - - unsigned char *buf; /* seek buffer */ - blkid_loff_t buf_off; /* offset of seek buffer */ - size_t buf_len; /* size of data in seek buffer */ - size_t buf_max; /* allocated size of seek buffer */ + struct list_head buffers; /* list of buffers */ struct blkid_chain chains[BLKID_NCHAINS]; /* array of chains */ struct blkid_chain *cur_chain; /* current chain */ @@ -360,12 +359,8 @@ extern void blkid_free_dev(blkid_dev dev); /* probe.c */ extern int blkid_probe_is_tiny(blkid_probe pr); -extern int blkid_probe_has_buffer(blkid_probe pr, - blkid_loff_t off, blkid_loff_t len); extern unsigned char *blkid_probe_get_buffer(blkid_probe pr, blkid_loff_t off, blkid_loff_t len); -extern unsigned char *blkid_probe_get_extra_buffer(blkid_probe pr, - blkid_loff_t off, blkid_loff_t len); extern unsigned char *blkid_probe_get_sector(blkid_probe pr, unsigned int sector); diff --git a/shlibs/blkid/src/probe.c b/shlibs/blkid/src/probe.c index 1bd98b55..91366851 100644 --- a/shlibs/blkid/src/probe.c +++ b/shlibs/blkid/src/probe.c @@ -115,6 +115,7 @@ static const struct blkid_chaindrv *chains_drvs[] = { }; static void blkid_probe_reset_vals(blkid_probe pr); +static void blkid_probe_reset_buffer(blkid_probe pr); /** * blkid_new_probe: @@ -137,6 +138,7 @@ blkid_probe blkid_new_probe(void) pr->chains[i].flags = chains_drvs[i]->dflt_flags; pr->chains[i].enabled = chains_drvs[i]->dflt_enabled; } + INIT_LIST_HEAD(&pr->buffers); return pr; } @@ -202,26 +204,13 @@ void blkid_free_probe(blkid_probe pr) ch->driver->free_data(pr, ch->data); free(ch->fltr); } - free(pr->buf); - free(pr->sbbuf); if ((pr->flags & BLKID_PRIVATE_FD) && pr->fd >= 0) close(pr->fd); + blkid_probe_reset_buffer(pr); free(pr); } -static void blkid_probe_reset_buffer(blkid_probe pr) -{ - DBG(DEBUG_LOWPROBE, printf("reseting blkid probe buffer\n")); - if (pr->buf) - memset(pr->buf, 0, pr->buf_max); - pr->buf_off = 0; - pr->buf_len = 0; - if (pr->sbbuf) - memset(pr->sbbuf, 0, BLKID_SB_BUFSIZ); - pr->sbbuf_len = 0; -} - /* * Removes chain values from probing result. @@ -470,141 +459,79 @@ int __blkid_probe_filter_types(blkid_probe pr, int chain, int flag, char *names[ return 0; } -int blkid_probe_has_buffer(blkid_probe pr, +unsigned char *blkid_probe_get_buffer(blkid_probe pr, blkid_loff_t off, blkid_loff_t len) { - return pr && (off + len <= pr->sbbuf_len || - (pr->buf_off < off && off + len < pr->buf_len)); -} + struct list_head *p; + struct blkid_bufinfo *bf = NULL; + + list_for_each(p, &pr->buffers) { + struct blkid_bufinfo *x = + list_entry(p, struct blkid_bufinfo, bufs); + + if (x->off <= off && off + len <= x->off + x->len) { + DBG(DEBUG_LOWPROBE, + printf("\treuse buffer: off=%jd len=%jd\n", + x->off, x->len)); + bf = x; + break; + } + } + if (!bf) { + ssize_t ret; -/* - * Returns buffer from the begin (69kB) of the device. - */ -static unsigned char *blkid_probe_get_sb_buffer(blkid_probe pr, - blkid_loff_t off, blkid_loff_t len) -{ - if (off + len > BLKID_SB_BUFSIZ) - return NULL; - if (!pr->sbbuf) { - pr->sbbuf = malloc(BLKID_SB_BUFSIZ); - if (!pr->sbbuf) + if (blkid_llseek(pr->fd, pr->off + off, SEEK_SET) < 0) return NULL; - } - if (off + len > pr->sbbuf_len) { - /* - * The sbbuf is not completely in memory. - * - */ - ssize_t ret_read; - blkid_loff_t want, have = pr->sbbuf_len; - - if (blkid_probe_is_tiny(pr)) - /* We don't read whole BLKID_SB_BUFSIZ by one read(), - * it's too aggresive to small devices (floppies). We - * read necessary data to complete the current request - * (off + len) only. - */ - want = off + len - have; - else - /* large disk -- read all SB */ - want = BLKID_SB_BUFSIZ - have; + + /* allocate info and space for data by why call */ + bf = calloc(1, sizeof(struct blkid_bufinfo) + len); + if (!bf) + return NULL; + + bf->data = ((unsigned char *) bf) + sizeof(struct blkid_bufinfo); + bf->len = len; + bf->off = off; + INIT_LIST_HEAD(&bf->bufs); DBG(DEBUG_LOWPROBE, - printf("\tsb-buffer read() off=%jd len=%jd\n", have, want)); + printf("\tbuffer read: off=%jd len=%jd\n", off, len)); - if (lseek(pr->fd, pr->off + have, SEEK_SET) < 0) + ret = read(pr->fd, bf->data, len); + if (ret != (ssize_t) len) { + free(bf); return NULL; - - ret_read = read(pr->fd, pr->sbbuf + have, want); - if (ret_read < 0) - ret_read = 0; - pr->sbbuf_len = have + ret_read; + } + list_add_tail(&bf->bufs, &pr->buffers); } - if (off + len > pr->sbbuf_len) - return NULL; - return pr->sbbuf + off; + + return off ? bf->data + (off - bf->off) : bf->data; } -/* - * Returns pointer to the buffer on arbitrary offset on the device - */ -unsigned char *blkid_probe_get_extra_buffer(blkid_probe pr, - blkid_loff_t off, blkid_loff_t len) + +static void blkid_probe_reset_buffer(blkid_probe pr) { - unsigned char *newbuf = NULL; - - if (off + len <= BLKID_SB_BUFSIZ && - (!blkid_probe_is_tiny(pr) || blkid_probe_has_buffer(pr, off, len))) - /* - * Don't use extra buffer for superblock data if - * - data are already in SB buffer - * - or the device is large and we needn't extra - * optimalization for tiny devices - */ - return blkid_probe_get_sb_buffer(pr, off, len); + ssize_t read_ct = 0, len_ct = 0; - if (len > pr->buf_max) { - newbuf = realloc(pr->buf, len); - if (!newbuf) - return NULL; - pr->buf = newbuf; - pr->buf_max = len; - pr->buf_off = 0; - pr->buf_len = 0; - } - if (newbuf || off < pr->buf_off || - off + len > pr->buf_off + pr->buf_len) { - ssize_t ret_read; + if (!pr || list_empty(&pr->buffers)) + return; - if (blkid_llseek(pr->fd, pr->off + off, SEEK_SET) < 0) - return NULL; + DBG(DEBUG_LOWPROBE, printf("reseting probing buffers\n")); - DBG(DEBUG_LOWPROBE, - printf("\textra-buffer read: off=%jd len=%jd\n", off, len)); + while (!list_empty(&pr->buffers)) { + struct blkid_bufinfo *bf = list_entry(pr->buffers.next, + struct blkid_bufinfo, bufs); - ret_read = read(pr->fd, pr->buf, len); - if (ret_read != (ssize_t) len) - return NULL; - pr->buf_off = off; - pr->buf_len = len; + read_ct++; + len_ct += bf->len; + list_del(&bf->bufs); + free(bf); } - return off ? pr->buf + (off - pr->buf_off) : pr->buf; -} + DBG(DEBUG_LOWPROBE, + printf("buffers summary: %jd bytes by %jd read() call(s)\n", + len_ct, read_ct)); -/* - * @off: offset within probing area - * @len: size of requested buffer - * - * The probing area is between pr->off and pr->size. The @off = 0 is pr->off, the - * max @len is pr->size. - * - * Note that we have two offsets: - * - * 1/ general device offset (pr->off), that's useful for example when we - * probe a partition from whole disk image: - * blkid -O -S disk.img - * - * 2/ buffer offset (the @off argument), that useful for offsets in - * superbloks, ... - * - * That means never use lseek(fd, 0, SEEK_SET), the zero position is always - * pr->off, so lseek(fd, pr->off, SEEK_SET). - * - */ -unsigned char *blkid_probe_get_buffer(blkid_probe pr, - blkid_loff_t off, blkid_loff_t len) -{ - if (off < 0 || len < 0) { - DBG(DEBUG_LOWPROBE, - printf("unexpected offset or length of buffer requested\n")); - return NULL; - } - if (off + len > pr->size) - return NULL; - if (off + len <= BLKID_SB_BUFSIZ) - return blkid_probe_get_sb_buffer(pr, off, len); - return blkid_probe_get_extra_buffer(pr, off, len); + INIT_LIST_HEAD(&pr->buffers); } /* diff --git a/shlibs/blkid/src/superblocks/vfat.c b/shlibs/blkid/src/superblocks/vfat.c index 29066c34..71c0fbcb 100644 --- a/shlibs/blkid/src/superblocks/vfat.c +++ b/shlibs/blkid/src/superblocks/vfat.c @@ -142,7 +142,7 @@ static unsigned char *search_fat_label(blkid_probe pr, */ if (!dir) ent = (struct vfat_dir_entry *) - blkid_probe_get_extra_buffer(pr, + blkid_probe_get_buffer(pr, offset + (i * sizeof(struct vfat_dir_entry)), sizeof(struct vfat_dir_entry)); else @@ -330,7 +330,7 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag) /* get FAT entry */ fat_entry_off = (reserved * sector_size) + (next * sizeof(uint32_t)); - buf = blkid_probe_get_extra_buffer(pr, fat_entry_off, buf_size); + buf = blkid_probe_get_buffer(pr, fat_entry_off, buf_size); if (buf == NULL) break; @@ -351,7 +351,7 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag) if (fsinfo_sect) { struct fat32_fsinfo *fsinfo; - buf = blkid_probe_get_extra_buffer(pr, + buf = blkid_probe_get_buffer(pr, fsinfo_sect * sector_size, sizeof(struct fat32_fsinfo)); if (buf == NULL) -- cgit v1.2.3 From e3d8933aaa1786ed78f06e5c9792d2167801d48e Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 20 Jan 2010 21:18:15 +0100 Subject: blkid: probe for PT, don't probe for FS on small whole-disks * blkid(8) in low-level mode probes for PT now (blkid is replacement for devkit-disks-part-id) * add ID_PART_TABLE_TYPE= to blkid(8) udev output * don't probe for FS/RAIDs on small devices when PT is detected Signed-off-by: Karel Zak --- misc-utils/blkid.c | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/misc-utils/blkid.c b/misc-utils/blkid.c index 6e055a95..03e3b807 100644 --- a/misc-utils/blkid.c +++ b/misc-utils/blkid.c @@ -255,7 +255,12 @@ static void print_udev_format(const char *name, const char *value, size_t sz) blkid_encode_string(value, enc, sizeof(enc)); printf("ID_FS_%s_ENC=%s\n", name, enc); - } + + } else if (!strcmp(name, "PTTYPE")) + printf("ID_PART_TABLE_TYPE=%s\n", value); + + /* TODO: ID_PART_ENTRY_{UUID,NAME,FLAG} */ + else printf("ID_FS_%s=%s\n", name, value); } @@ -410,6 +415,7 @@ static int lowprobe_device(blkid_probe pr, const char *devname, char *show[], size_t len; int fd; int rc = 0; + struct stat st; fd = open(devname, O_RDONLY); if (fd < 0) @@ -417,9 +423,35 @@ static int lowprobe_device(blkid_probe pr, const char *devname, char *show[], if (blkid_probe_set_device(pr, fd, offset, size)) goto done; - rc = blkid_do_safeprobe(pr); - if (rc) + + if (fstat(fd, &st)) goto done; + /* + * partitions probing + */ + blkid_probe_enable_superblocks(pr, 0); /* enabled by default ;-( */ + + blkid_probe_enable_partitions(pr, 1); + rc = blkid_do_fullprobe(pr); + blkid_probe_enable_partitions(pr, 0); + + if (rc < 0) + goto done; /* -1 = error, 1 = nothing, 0 = succes */ + + /* + * Don't probe for FS/RAIDs on small devices + */ + if (rc || S_ISCHR(st.st_mode) || + blkid_probe_get_size(pr) > 1024 * 1440) { + /* + * filesystems/RAIDs probing + */ + blkid_probe_enable_superblocks(pr, 1); + + rc = blkid_do_safeprobe(pr); + if (rc < 0) + goto done; + } nvals = blkid_probe_numof_values(pr); @@ -648,8 +680,6 @@ int main(int argc, char **argv) if (!pr) goto exit; - blkid_probe_enable_superblocks(pr, 1); - blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE | -- cgit v1.2.3 From 2b09166ddac2cd671ca28111a25e342304d6223f Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 20 Jan 2010 23:30:20 +0100 Subject: libblkid: add sanity checks for FAT to DOS PT parser Signed-off-by: Karel Zak --- shlibs/blkid/src/Makefile.am | 2 +- shlibs/blkid/src/fat.h | 90 +++++++++++++++++++++++++++++++++++++ shlibs/blkid/src/partitions/dos.c | 25 ++++++++--- shlibs/blkid/src/superblocks/vfat.c | 67 ++------------------------- 4 files changed, 114 insertions(+), 70 deletions(-) create mode 100644 shlibs/blkid/src/fat.h diff --git a/shlibs/blkid/src/Makefile.am b/shlibs/blkid/src/Makefile.am index 90ce9bfc..2d798b6a 100644 --- a/shlibs/blkid/src/Makefile.am +++ b/shlibs/blkid/src/Makefile.am @@ -25,7 +25,7 @@ usrlib_exec_LTLIBRARIES = libblkid.la libblkid_la_SOURCES = cache.c dev.c devname.c devno.c getsize.c llseek.c \ probe.c read.c resolve.c save.c tag.c version.c verify.c \ encode.c list.h blkidP.h superblocks/superblocks.h \ - config.c evaluate.c \ + config.c evaluate.c fat.h \ $(blkidinc_HEADERS) \ $(top_srcdir)/lib/blkdev.c \ $(top_srcdir)/lib/linux_version.c \ diff --git a/shlibs/blkid/src/fat.h b/shlibs/blkid/src/fat.h new file mode 100644 index 00000000..b3664641 --- /dev/null +++ b/shlibs/blkid/src/fat.h @@ -0,0 +1,90 @@ +#ifndef _BLKID_FAT_H +#define _BLKID_FAT_H + +/* This FAT superblock is required for: + * + * superblocks/vfat.c + * partitions/dos.c + */ + +/* Yucky misaligned values */ +struct vfat_super_block { +/* 00*/ unsigned char vs_ignored[3]; +/* 03*/ unsigned char vs_sysid[8]; +/* 0b*/ unsigned char vs_sector_size[2]; +/* 0d*/ uint8_t vs_cluster_size; +/* 0e*/ uint16_t vs_reserved; +/* 10*/ uint8_t vs_fats; +/* 11*/ unsigned char vs_dir_entries[2]; +/* 13*/ unsigned char vs_sectors[2]; +/* 15*/ unsigned char vs_media; +/* 16*/ uint16_t vs_fat_length; +/* 18*/ uint16_t vs_secs_track; +/* 1a*/ uint16_t vs_heads; +/* 1c*/ uint32_t vs_hidden; +/* 20*/ uint32_t vs_total_sect; +/* 24*/ uint32_t vs_fat32_length; +/* 28*/ uint16_t vs_flags; +/* 2a*/ uint8_t vs_version[2]; +/* 2c*/ uint32_t vs_root_cluster; +/* 30*/ uint16_t vs_fsinfo_sector; +/* 32*/ uint16_t vs_backup_boot; +/* 34*/ uint16_t vs_reserved2[6]; +/* 40*/ unsigned char vs_unknown[3]; +/* 43*/ unsigned char vs_serno[4]; +/* 47*/ unsigned char vs_label[11]; +/* 52*/ unsigned char vs_magic[8]; +/* 5a*/ unsigned char vs_dummy2[0x1fe - 0x5a]; +/*1fe*/ unsigned char vs_pmagic[2]; +} __attribute__((packed)); + +/* Yucky misaligned values */ +struct msdos_super_block { +/* 00*/ unsigned char ms_ignored[3]; +/* 03*/ unsigned char ms_sysid[8]; +/* 0b*/ unsigned char ms_sector_size[2]; +/* 0d*/ uint8_t ms_cluster_size; +/* 0e*/ uint16_t ms_reserved; +/* 10*/ uint8_t ms_fats; +/* 11*/ unsigned char ms_dir_entries[2]; +/* 13*/ unsigned char ms_sectors[2]; /* =0 iff V3 or later */ +/* 15*/ unsigned char ms_media; +/* 16*/ uint16_t ms_fat_length; /* Sectors per FAT */ +/* 18*/ uint16_t ms_secs_track; +/* 1a*/ uint16_t ms_heads; +/* 1c*/ uint32_t ms_hidden; +/* V3 BPB */ +/* 20*/ uint32_t ms_total_sect; /* iff ms_sectors == 0 */ +/* V4 BPB */ +/* 24*/ unsigned char ms_unknown[3]; /* Phys drive no., resvd, V4 sig (0x29) */ +/* 27*/ unsigned char ms_serno[4]; +/* 2b*/ unsigned char ms_label[11]; +/* 36*/ unsigned char ms_magic[8]; +/* 3e*/ unsigned char ms_dummy2[0x1fe - 0x3e]; +/*1fe*/ unsigned char ms_pmagic[2]; +} __attribute__((packed)); + + +static inline int blkid_fat_valid_media(struct msdos_super_block *ms) +{ + return 0xf8 <= ms->ms_media || ms->ms_media == 0xf0; +} + +static inline int blkid_fat_valid_sectorsize( + struct msdos_super_block *ms, + uint16_t *sector_size) +{ + unsigned char *tmp = (unsigned char *) &ms->ms_sector_size; + uint16_t ssz; + + ssz = tmp[0] + (tmp[1] << 8); + + if (ssz != 0x200 && ssz != 0x400 && ssz != 0x800 && ssz != 0x1000) + return 0; + if (sector_size) + *sector_size = ssz; + return 1; +} + + +#endif /* _BLKID_FAT_H */ diff --git a/shlibs/blkid/src/partitions/dos.c b/shlibs/blkid/src/partitions/dos.c index 21728a5a..ec2ca1eb 100644 --- a/shlibs/blkid/src/partitions/dos.c +++ b/shlibs/blkid/src/partitions/dos.c @@ -16,6 +16,7 @@ #include "partitions.h" #include "dos.h" #include "aix.h" +#include "fat.h" static const struct dos_subtypes { unsigned char type; @@ -139,18 +140,30 @@ static int probe_dos_pt(blkid_probe pr, const struct blkid_idmag *mag) if (memcmp(data, BLKID_AIX_MAGIC_STRING, BLKID_AIX_MAGIC_STRLEN) == 0) goto nothing; - p0 = (struct dos_partition *) (data + BLKID_MSDOS_PT_OFFSET); - /* * Now that the 55aa signature is present, this is probably * either the boot sector of a FAT filesystem or a DOS-type - * partition table. Reject this in case the boot indicator - * is not 0 or 0x80. + * partition table. */ - for (p = p0, i = 0; i < 4; i++, p++) { + { + struct msdos_super_block *ms = + (struct msdos_super_block *) data; + + if (ms->ms_fats && ms->ms_reserved && + ms->ms_cluster_size && + blkid_fat_valid_media(ms) && + blkid_fat_valid_sectorsize(ms, NULL)) + goto nothing; /* FAT */ + } + + p0 = (struct dos_partition *) (data + BLKID_MSDOS_PT_OFFSET); + + /* + * Reject PT where boot indicator is not 0 or 0x80. + */ + for (p = p0, i = 0; i < 4; i++, p++) if (p->boot_ind != 0 && p->boot_ind != 0x80) goto nothing; - } /* * GPT uses valid MBR diff --git a/shlibs/blkid/src/superblocks/vfat.c b/shlibs/blkid/src/superblocks/vfat.c index 71c0fbcb..b24f6075 100644 --- a/shlibs/blkid/src/superblocks/vfat.c +++ b/shlibs/blkid/src/superblocks/vfat.c @@ -18,62 +18,8 @@ #include "superblocks.h" -/* Yucky misaligned values */ -struct vfat_super_block { -/* 00*/ unsigned char vs_ignored[3]; -/* 03*/ unsigned char vs_sysid[8]; -/* 0b*/ unsigned char vs_sector_size[2]; -/* 0d*/ uint8_t vs_cluster_size; -/* 0e*/ uint16_t vs_reserved; -/* 10*/ uint8_t vs_fats; -/* 11*/ unsigned char vs_dir_entries[2]; -/* 13*/ unsigned char vs_sectors[2]; -/* 15*/ unsigned char vs_media; -/* 16*/ uint16_t vs_fat_length; -/* 18*/ uint16_t vs_secs_track; -/* 1a*/ uint16_t vs_heads; -/* 1c*/ uint32_t vs_hidden; -/* 20*/ uint32_t vs_total_sect; -/* 24*/ uint32_t vs_fat32_length; -/* 28*/ uint16_t vs_flags; -/* 2a*/ uint8_t vs_version[2]; -/* 2c*/ uint32_t vs_root_cluster; -/* 30*/ uint16_t vs_fsinfo_sector; -/* 32*/ uint16_t vs_backup_boot; -/* 34*/ uint16_t vs_reserved2[6]; -/* 40*/ unsigned char vs_unknown[3]; -/* 43*/ unsigned char vs_serno[4]; -/* 47*/ unsigned char vs_label[11]; -/* 52*/ unsigned char vs_magic[8]; -/* 5a*/ unsigned char vs_dummy2[0x1fe - 0x5a]; -/*1fe*/ unsigned char vs_pmagic[2]; -} __attribute__((packed)); - -/* Yucky misaligned values */ -struct msdos_super_block { -/* 00*/ unsigned char ms_ignored[3]; -/* 03*/ unsigned char ms_sysid[8]; -/* 0b*/ unsigned char ms_sector_size[2]; -/* 0d*/ uint8_t ms_cluster_size; -/* 0e*/ uint16_t ms_reserved; -/* 10*/ uint8_t ms_fats; -/* 11*/ unsigned char ms_dir_entries[2]; -/* 13*/ unsigned char ms_sectors[2]; /* =0 iff V3 or later */ -/* 15*/ unsigned char ms_media; -/* 16*/ uint16_t ms_fat_length; /* Sectors per FAT */ -/* 18*/ uint16_t ms_secs_track; -/* 1a*/ uint16_t ms_heads; -/* 1c*/ uint32_t ms_hidden; -/* V3 BPB */ -/* 20*/ uint32_t ms_total_sect; /* iff ms_sectors == 0 */ -/* V4 BPB */ -/* 24*/ unsigned char ms_unknown[3]; /* Phys drive no., resvd, V4 sig (0x29) */ -/* 27*/ unsigned char ms_serno[4]; -/* 2b*/ unsigned char ms_label[11]; -/* 36*/ unsigned char ms_magic[8]; -/* 3e*/ unsigned char ms_dummy2[0x1fe - 0x3e]; -/*1fe*/ unsigned char ms_pmagic[2]; -} __attribute__((packed)); +/* {msdos,vfat}_super_block is defined in ../fat.h */ +#include "fat.h" struct vfat_dir_entry { uint8_t name[11]; @@ -193,7 +139,7 @@ static int probe_fat_nomagic(blkid_probe pr, const struct blkid_idmag *mag) return 1; /* media check */ - if (ms->ms_media < 0xf8 && ms->ms_media != 0xf0) + if (!blkid_fat_valid_media(ms)) return 1; /* fat counts(Linux kernel expects at least 1 FAT table) */ @@ -230,8 +176,6 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag) uint32_t buf_size, start_data_sect, next, root_start, root_dir_entries; const char *version = NULL; - - /* non-standard magic strings */ if (mag->len <= 2 && probe_fat_nomagic(pr, mag) != 0) return 1; @@ -245,10 +189,7 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag) return -1; /* sector size check */ - tmp = (unsigned char *) &ms->ms_sector_size; - sector_size = tmp[0] + (tmp[1] << 8); - if (sector_size != 0x200 && sector_size != 0x400 && - sector_size != 0x800 && sector_size != 0x1000) + if (!blkid_fat_valid_sectorsize(ms, §or_size)) return 1; tmp = (unsigned char *) &ms->ms_dir_entries; -- cgit v1.2.3 From cc62a975a21629d66557ee18ea9f4354b73e9e7f Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 20 Jan 2010 23:51:13 +0100 Subject: libblkid: don't probe for GPT and Unixware PT on floppies Signed-off-by: Karel Zak --- shlibs/blkid/src/partitions/gpt.c | 1 + shlibs/blkid/src/partitions/partitions.c | 3 +++ shlibs/blkid/src/partitions/unixware.c | 1 + 3 files changed, 5 insertions(+) diff --git a/shlibs/blkid/src/partitions/gpt.c b/shlibs/blkid/src/partitions/gpt.c index 2ec3f739..2c3a3267 100644 --- a/shlibs/blkid/src/partitions/gpt.c +++ b/shlibs/blkid/src/partitions/gpt.c @@ -368,6 +368,7 @@ const struct blkid_idinfo gpt_pt_idinfo = { .name = "gpt", .probefunc = probe_gpt_pt, + .minsz = 1024 * 1440 + 1, /* ignore floppies */ /* * It would be possible to check for DOS signature (0xAA55), but diff --git a/shlibs/blkid/src/partitions/partitions.c b/shlibs/blkid/src/partitions/partitions.c index 82861a5b..154365d7 100644 --- a/shlibs/blkid/src/partitions/partitions.c +++ b/shlibs/blkid/src/partitions/partitions.c @@ -505,6 +505,9 @@ static int idinfo_probe(blkid_probe pr, const struct blkid_idinfo *id) int hasmag = 0; int rc = 1; /* = nothing detected */ + if (id->minsz && id->minsz > pr->size) + goto nothing; /* the device is too small */ + mag = id->magics ? &id->magics[0] : NULL; /* try to detect by magic string */ diff --git a/shlibs/blkid/src/partitions/unixware.c b/shlibs/blkid/src/partitions/unixware.c index 70b6626f..62dba764 100644 --- a/shlibs/blkid/src/partitions/unixware.c +++ b/shlibs/blkid/src/partitions/unixware.c @@ -173,6 +173,7 @@ const struct blkid_idinfo unixware_pt_idinfo = { .name = "unixware", .probefunc = probe_unixware_pt, + .minsz = 1024 * 1440 + 1, /* ignore floppies */ .magics = { { -- cgit v1.2.3 From 10f494e1a0ac09e144a42fcaeb72663674eb30fc Mon Sep 17 00:00:00 2001 From: Matthias König Date: Tue, 12 Jan 2010 13:58:28 +0100 Subject: libblkid: fix segfault in drdb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check if blkid_probe_get_buffer() returns NULL to avoid dereferencing a zero pointer resulting in a segfault. Signed-off-by: Matthias König --- shlibs/blkid/src/superblocks/drbd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shlibs/blkid/src/superblocks/drbd.c b/shlibs/blkid/src/superblocks/drbd.c index e0bbb4d6..a56486e9 100644 --- a/shlibs/blkid/src/superblocks/drbd.c +++ b/shlibs/blkid/src/superblocks/drbd.c @@ -78,7 +78,8 @@ static int probe_drbd(blkid_probe pr, const struct blkid_idmag *mag) blkid_probe_get_buffer(pr, off, sizeof(struct md_on_disk_08)); - + if (!md) + return -1; if (be32_to_cpu(md->magic) != DRBD_MD_MAGIC_08) return -1; -- cgit v1.2.3 From ed5de10ed786c6887c4b6ecb138ded4be7149af6 Mon Sep 17 00:00:00 2001 From: Vladimir Brednikov Date: Mon, 11 Jan 2010 00:01:26 +0300 Subject: namei: fix man page formatting --- misc-utils/namei.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc-utils/namei.1 b/misc-utils/namei.1 index f9617dab..a54fa8ac 100644 --- a/misc-utils/namei.1 +++ b/misc-utils/namei.1 @@ -5,7 +5,7 @@ .SH NAME namei - follow a pathname until a terminal point is found .SH SYNOPSIS -.B fBnamei +.B namei .RI [ options ] .IR pathname ... .SH DESCRIPTION -- cgit v1.2.3 From 701094844451477c68d9503a5d4926f6493d9ddd Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 13 Jan 2010 18:07:33 +0100 Subject: mount: update documentation about barrier mount options Signed-off-by: Jan Kara --- mount/mount.8 | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/mount/mount.8 b/mount/mount.8 index 217071ec..2888b46d 100644 --- a/mount/mount.8 +++ b/mount/mount.8 @@ -1267,7 +1267,11 @@ in files after a crash and journal recovery. .TP .BR barrier=0 " / " barrier=1 " This enables/disables barriers. barrier=0 disables it, barrier=1 enables it. -The ext3 filesystem does not enable write barriers by default. +Write barriers enforce proper on-disk ordering of journal commits, making +volatile disk write caches safe to use, at some performance penalty. The ext3 +filesystem does not enable write barriers by default. Be sure to enable +barriers unless your disks are battery-backed one way or another. Otherwise +you risk filesystem corruption in case of power failure. .TP .BI commit= nrsec Sync all data and metadata every @@ -1932,6 +1936,15 @@ manual page. Enable POSIX Access Control Lists. See the .BR acl (5) manual page. +.TP +.BR barrier=none " / " barrier=flush " +This enables/disables the use of write barriers in the journaling code. +barrier=none disables it, barrier=flush enables it. Write barriers enforce +proper on-disk ordering of journal commits, making volatile disk write caches +safe to use, at some performance penalty. The reiserfs filesystem does not +enable write barriers by default. Be sure to enable barriers unless your disks +are battery-backed one way or another. Otherwise you risk filesystem +corruption in case of power failure. .SH "Mount options for romfs" None. -- cgit v1.2.3 From f609e92e497a513ed759dc4166a372fb22d3f995 Mon Sep 17 00:00:00 2001 From: Matthias König Date: Tue, 12 Jan 2010 13:58:38 +0100 Subject: cfdisk: use libblkid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let cfdisk use the internal libblkid if available to get the filesystem type and label. [kzak@redhat.com: - remove old FS probing code from cfdisk - remove "Linux" prefix for filesystem names - enlarge fstype field in partition_info - restrict probing area by partition size] Signed-off-by: Matthias König Signed-off-by: Karel Zak --- fdisk/Makefile.am | 23 +++--- fdisk/cfdisk.c | 232 +++++++++--------------------------------------------- 2 files changed, 49 insertions(+), 206 deletions(-) diff --git a/fdisk/Makefile.am b/fdisk/Makefile.am index 5496e240..50f1dbe8 100644 --- a/fdisk/Makefile.am +++ b/fdisk/Makefile.am @@ -18,26 +18,25 @@ fdisk_SOURCES = fdisk.c fdiskbsdlabel.c fdisksgilabel.c \ fdisk.h fdisksunlabel.h fdisksgilabel.h fdiskaixlabel.h \ fdiskbsdlabel.h fdiskmaclabel.h $(fdisk_common) -cflags_fdisk = $(AM_CFLAGS) -ldadd_fdisk = +cflags_blkid = $(AM_CFLAGS) +ldadd_blkid = if BUILD_LIBBLKID # only in-tree libblkid has topology support -ldadd_fdisk += $(ul_libblkid_la) -cflags_fdisk += -I$(ul_libblkid_incdir) +ldadd_blkid += $(ul_libblkid_la) +cflags_blkid += -I$(ul_libblkid_incdir) endif if HAVE_STATIC_FDISK sbin_PROGRAMS += fdisk.static fdisk_static_SOURCES = $(fdisk_SOURCES) fdisk_static_LDFLAGS = -all-static -fdisk_static_CFLAGS = $(cflags_fdisk) -fdisk_static_LDADD = $(ldadd_fdisk) +fdisk_static_CFLAGS = $(cflags_blkid) +fdisk_static_LDADD = $(ldadd_blkid) endif -fdisk_CFLAGS = $(cflags_fdisk) -fdisk_LDADD = $(ldadd_fdisk) - +fdisk_CFLAGS = $(cflags_blkid) +fdisk_LDADD = $(ldadd_blkid) if !ARCH_SPARC @@ -55,13 +54,15 @@ if USE_SLANG sbin_PROGRAMS += cfdisk dist_man_MANS += cfdisk.8 cfdisk_SOURCES = cfdisk.c $(fdisk_common) -cfdisk_LDADD = -lslang +cfdisk_CFLAGS = $(cflags_blkid) +cfdisk_LDADD = -lslang $(ldadd_blkid) else if HAVE_NCURSES sbin_PROGRAMS += cfdisk dist_man_MANS += cfdisk.8 cfdisk_SOURCES = cfdisk.c $(fdisk_common) -cfdisk_LDADD = @NCURSES_LIBS@ +cfdisk_CFLAGS = $(cflags_blkid) +cfdisk_LDADD = @NCURSES_LIBS@ $(ldadd_blkid) endif endif diff --git a/fdisk/cfdisk.c b/fdisk/cfdisk.c index eec16893..eaf766c8 100644 --- a/fdisk/cfdisk.c +++ b/fdisk/cfdisk.c @@ -79,6 +79,10 @@ #include #include +#ifdef HAVE_LIBBLKID_INTERNAL +#include +#endif + #include "nls.h" #include "blkdev.h" #include "xstrncpy.h" @@ -222,11 +226,6 @@ set_hsc_end(struct partition *p, long long sector) { #define is_extended(x) ((x) == DOS_EXTENDED || (x) == WIN98_EXTENDED || \ (x) == LINUX_EXTENDED) -#define is_dos_partition(x) ((x) == 1 || (x) == 4 || (x) == 6) -#define may_have_dos_label(x) (is_dos_partition(x) \ - || (x) == 7 || (x) == 0xb || (x) == 0xc || (x) == 0xe \ - || (x) == 0x11 || (x) == 0x14 || (x) == 0x16 || (x) == 0x17) - /* start_sect and nr_sects are stored little endian on all machines */ /* moreover, they are not aligned correctly */ static void @@ -289,7 +288,7 @@ typedef struct { char volume_label[LABELSZ+1]; #define OSTYPESZ 8 char ostype[OSTYPESZ+1]; -#define FSTYPESZ 8 +#define FSTYPESZ 12 char fstype[FSTYPESZ+1]; } partition_info; @@ -378,29 +377,9 @@ partition_type_text(int i) { return _("Unusable"); else if (p_info[i].id == FREE_SPACE) return _("Free Space"); - else if (p_info[i].id == LINUX) { - if (!strcmp(p_info[i].fstype, "ext2")) - return _("Linux ext2"); - else if (!strcmp(p_info[i].fstype, "ext3")) - return _("Linux ext3"); - else if (!strcmp(p_info[i].fstype, "xfs")) - return _("Linux XFS"); - else if (!strcmp(p_info[i].fstype, "jfs")) - return _("Linux JFS"); - else if (!strcmp(p_info[i].fstype, "reiserfs")) - return _("Linux ReiserFS"); - else - return _("Linux"); - } else if (p_info[i].id == OS2_OR_NTFS) { - if (!strncmp(p_info[i].fstype, "HPFS", 4)) - return _("OS/2 HPFS"); - else if (!strncmp(p_info[i].ostype, "OS2", 3)) - return _("OS/2 IFS"); - else if (!p_info[i].ostype) - return p_info[i].ostype; - else - return _("NTFS"); - } else + else if (*p_info[i].fstype) + return p_info[i].fstype; + else return _(partition_type_name(p_info[i].id)); } @@ -574,171 +553,36 @@ write_sector(unsigned char *buffer, long long sect_num) { fatal(_("Cannot write disk drive"), 2); } +#ifdef HAVE_LIBBLKID_INTERNAL static void -dos_copy_to_info(char *to, int tosz, char *from, int fromsz) { - int i; - - for(i=0; is_magic, REISERFS_SUPER_MAGIC_STRING, - strlen(REISERFS_SUPER_MAGIC_STRING))) { - *is_3_6 = 0; - return 1; - } - if (!strncmp(rs->s_magic, REISER2FS_SUPER_MAGIC_STRING, - strlen(REISER2FS_SUPER_MAGIC_STRING))) { - *is_3_6 = 1; - return 1; - } - return 0; -} - -static void -get_linux_label(int i) { - -#define EXT2LABELSZ 16 -#define EXT2_SUPER_MAGIC 0xEF53 -#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004 - struct ext2_super_block { - char s_dummy0[56]; - unsigned char s_magic[2]; - char s_dummy1[34]; - unsigned char s_feature_compat[4]; - char s_dummy2[24]; - char s_volume_name[EXT2LABELSZ]; - char s_last_mounted[64]; - char s_dummy3[824]; - } e2fsb; - -#define REISERFS_DISK_OFFSET_IN_BYTES (64 * 1024) - struct reiserfs_super_block reiserfsb; - int reiserfs_is_3_6; - -#define JFS_SUPER1_OFF 0x8000 -#define JFS_MAGIC "JFS1" -#define JFSLABELSZ 16 - struct jfs_super_block { - char s_magic[4]; - u_char s_version[4]; - u_char s_dummy1[93]; - char s_fpack[11]; - u_char s_dummy2[24]; - u_char s_uuid[16]; - char s_label[JFSLABELSZ]; - } jfsb; - -#define XFS_SUPER_MAGIC "XFSB" -#define XFSLABELSZ 12 - struct xfs_super_block { - unsigned char s_magic[4]; - unsigned char s_dummy0[104]; - unsigned char s_fname[XFSLABELSZ]; - unsigned char s_dummy1[904]; - } xfsb; - - char *label; - long long offset; - int j; - - offset = (p_info[i].first_sector + p_info[i].offset) * SECTOR_SIZE - + 1024; - if (lseek(fd, offset, SEEK_SET) == offset - && read(fd, &e2fsb, sizeof(e2fsb)) == sizeof(e2fsb) - && e2fsb.s_magic[0] + (e2fsb.s_magic[1]<<8) == EXT2_SUPER_MAGIC) { - label = e2fsb.s_volume_name; - for(j=0; j Date: Wed, 27 Jan 2010 13:31:16 +0100 Subject: login: don't link PAMed version with libcrypt The login, chsh and chfn utils don't need to be linked against libcrypt. The libcrypt library is necessary only when login utils are not liked with PAM. Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=559196 Signed-off-by: Karel Zak --- login-utils/Makefile.am | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/login-utils/Makefile.am b/login-utils/Makefile.am index 177c0b63..920a6e7c 100644 --- a/login-utils/Makefile.am +++ b/login-utils/Makefile.am @@ -26,7 +26,7 @@ if NEED_LIBCRYPT simpleinit_LDADD = -lcrypt endif -endif +endif # BUILD_INIT if BUILD_LAST usrbin_exec_PROGRAMS += last @@ -40,6 +40,9 @@ usrbin_exec_PROGRAMS += chfn chsh newgrp usrsbin_exec_PROGRAMS += vipw dist_man_MANS += chfn.1 chsh.1 login.1 newgrp.1 vipw.8 vigr.8 +# login, chfn and chsh libs +login_ldadd_common = + chfn_SOURCES = chfn.c $(chfn_chsh_common) chsh_SOURCES = chsh.c $(chfn_chsh_common) chfn_chsh_common = islocal.c setpwnam.c islocal.h my_crypt.h setpwnam.h \ @@ -48,9 +51,9 @@ login_SOURCES = login.c login.h my_crypt.h ../lib/setproctitle.c newgrp_SOURCES = newgrp.c my_crypt.h vipw_SOURCES = vipw.c setpwnam.h -chfn_LDADD = -chsh_LDADD = -login_LDADD = +chfn_LDADD = $(login_ldadd_common) +chsh_LDADD = $(login_ldadd_common) +login_LDADD = $(login_ldadd_common) newgrp_LDADD = vipw_LDADD = @@ -62,19 +65,17 @@ chfn_LDFLAGS = $(SUID_LDFLAGS) $(AM_LDFLAGS) chsh_LDFLAGS = $(SUID_LDFLAGS) $(AM_LDFLAGS) newgrp_LDFLAGS = $(SUID_LDFLAGS) $(AM_LDFLAGS) -if NEED_LIBCRYPT -chfn_LDADD += -lcrypt -chsh_LDADD += -lcrypt -login_LDADD += -lcrypt -newgrp_LDADD += -lcrypt -endif - if HAVE_PAM -chfn_LDADD += -lpam -lpam_misc -chsh_LDADD += -lpam -lpam_misc -login_LDADD += -lpam -lpam_misc +login_ldadd_common += -lpam -lpam_misc else +if NEED_LIBCRYPT +login_ldadd_common += -lcrypt +endif login_SOURCES += checktty.c +endif #! HAVE_PAM + +if NEED_LIBCRYPT +newgrp_LDADD += -lcrypt endif if HAVE_AUDIT @@ -83,10 +84,9 @@ endif if HAVE_SELINUX chfn_SOURCES += selinux_utils.c selinux_utils.h -chfn_LDADD += -lselinux chsh_SOURCES += selinux_utils.c selinux_utils.h -chsh_LDADD += -lselinux vipw_LDADD += -lselinux +login_ldadd_common += -lselinux endif -- cgit v1.2.3 From 75cb940e23a852c81044117753222d163bb3355f Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 27 Jan 2010 15:01:13 +0100 Subject: libblkid: more robust minix probing Signed-off-by: Karel Zak --- shlibs/blkid/src/superblocks/minix.c | 70 ++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 3 deletions(-) diff --git a/shlibs/blkid/src/superblocks/minix.c b/shlibs/blkid/src/superblocks/minix.c index 784f0758..7b314abc 100644 --- a/shlibs/blkid/src/superblocks/minix.c +++ b/shlibs/blkid/src/superblocks/minix.c @@ -11,20 +11,84 @@ #include "superblocks.h" +struct minix_super_block { + uint16_t s_ninodes; + uint16_t s_nzones; + uint16_t s_imap_blocks; + uint16_t s_zmap_blocks; + uint16_t s_firstdatazone; + uint16_t s_log_zone_size; + uint32_t s_max_size; + uint16_t s_magic; + uint16_t s_state; + uint32_t s_zones; +}; + +struct minix3_super_block { + uint32_t s_ninodes; + uint16_t s_pad0; + uint16_t s_imap_blocks; + uint16_t s_zmap_blocks; + uint16_t s_firstdatazone; + uint16_t s_log_zone_size; + uint16_t s_pad1; + uint32_t s_max_size; + uint32_t s_zones; + uint16_t s_magic; + uint16_t s_pad2; + uint16_t s_blocksize; + uint8_t s_disk_version; +}; + +#define MINIX_BLOCK_SIZE_BITS 10 +#define MINIX_BLOCK_SIZE (1 << MINIX_BLOCK_SIZE_BITS) + static int probe_minix(blkid_probe pr, const struct blkid_idmag *mag) { + int version; + /* for more details see magic strings below */ switch(mag->magic[1]) { case '\023': - blkid_probe_set_version(pr, "1"); + version = 1; break; case '\044': - blkid_probe_set_version(pr, "2"); + version = 2; break; case '\115': - blkid_probe_set_version(pr, "3"); + version = 3; break; + default: + return -1; + break; + } + + if (version <= 2) { + struct minix_super_block *sb; + uint32_t zones; + + sb = blkid_probe_get_sb(pr, mag, struct minix_super_block); + if (!sb || sb->s_imap_blocks == 0 || sb->s_zmap_blocks == 0) + return -1; + + zones = version == 2 ? sb->s_zones : sb->s_nzones; + + /* sanity checks to be sure that the FS is really minix */ + if (sb->s_imap_blocks * MINIX_BLOCK_SIZE * 8 < sb->s_ninodes + 1) + return -1; + if (sb->s_zmap_blocks * MINIX_BLOCK_SIZE * 8 < zones - sb->s_firstdatazone + 1) + return -1; + + } else if (version == 3) { + struct minix3_super_block *sb; + + sb = blkid_probe_get_sb(pr, mag, struct minix3_super_block); + if (!sb || sb->s_imap_blocks == 0 || sb->s_zmap_blocks == 0) + return -1; + } + + blkid_probe_sprintf_version(pr, "%d", version); return 0; } -- cgit v1.2.3 From f00aae6d7b6690e030a6596a6fcf9be6f260b8c5 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 27 Jan 2010 18:16:06 +0100 Subject: blkid: add newline when only one value is printed Signed-off-by: Karel Zak --- misc-utils/blkid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc-utils/blkid.c b/misc-utils/blkid.c index 03e3b807..56b25b8b 100644 --- a/misc-utils/blkid.c +++ b/misc-utils/blkid.c @@ -469,7 +469,7 @@ static int lowprobe_device(blkid_probe pr, const char *devname, char *show[], print_value(output, num++, devname, (char *) data, name, len); } - if (nvals > 1 && !(output & (OUTPUT_VALUE_ONLY | OUTPUT_UDEV_LIST))) + if (nvals >= 1 && !(output & (OUTPUT_VALUE_ONLY | OUTPUT_UDEV_LIST))) printf("\n"); done: if (rc == -2) { -- cgit v1.2.3 From 453b36147bcd58962fade1cac76ddebecfa2caf6 Mon Sep 17 00:00:00 2001 From: Yann Droneaud Date: Mon, 25 Jan 2010 23:12:09 +0100 Subject: login: use fd instead of pathname for update tty's owner and permissions To avoid some nasty races, use the only true tty: the one already opened, don't use the path. Signed-off-by: Yann Droneaud --- login-utils/login.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/login-utils/login.c b/login-utils/login.c index 486b30bf..fdc8078d 100644 --- a/login-utils/login.c +++ b/login-utils/login.c @@ -536,8 +536,8 @@ main(int argc, char **argv) ttt.c_cflag &= ~HUPCL; /* These can fail, e.g. with ttyn on a read-only filesystem */ - chown(ttyn, 0, 0); - chmod(ttyn, TTY_MODE); + fchown(0, 0, 0); + fchmod(0, TTY_MODE); /* Kill processes left on this tty */ tcsetattr(0,TCSAFLUSH,&ttt); @@ -1009,9 +1009,9 @@ Michael Riepe logaudit(tty_name, username, hostname, pwd, 1); dolastlog(quietlog); - chown(ttyn, pwd->pw_uid, + fchown(0, pwd->pw_uid, (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid); - chmod(ttyn, TTY_MODE); + fchmod(0, TTY_MODE); #ifdef LOGIN_CHOWN_VCS /* if tty is one of the VC's then change owner and mode of the -- cgit v1.2.3 From 8bee984a93cdf62b3cc84bb9fbfe023b6f554818 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Thu, 28 Jan 2010 16:25:52 +0100 Subject: login: check that after tty reopen we still work with a terminal * the login code assumes that stdin is a terminal, it's better to check (by isatty()) that after tty reopen we still have a terminal * this patch also removes very old obscure fallback for situations where ttyname() returns nothing (then ttyn = "/dev/tty??"). I guess that the fake string was originally for utmp records or so. Currently (in last 10 years...) code requires that the tty name is a real open-able file. It means the fake tty name is completely useless. Reported-by: Yann Droneaud Signed-off-by: Karel Zak --- login-utils/login.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/login-utils/login.c b/login-utils/login.c index fdc8078d..1550388c 100644 --- a/login-utils/login.c +++ b/login-utils/login.c @@ -200,6 +200,13 @@ opentty(const char * tty) { exit(1); } + if (!isatty(fd)) { + close(fd); + syslog(LOG_ERR, _("FATAL: %s is not a terminal"), tty); + sleep(1); + exit(1); + } + flags = fcntl(fd, F_GETFL); flags &= ~O_NONBLOCK; fcntl(fd, F_SETFL, flags); @@ -222,7 +229,9 @@ static void check_ttyname(char *ttyn) { struct stat statbuf; - if (lstat(ttyn, &statbuf) + if (ttyn == NULL + || *ttyn == '\0' + || lstat(ttyn, &statbuf) || !S_ISCHR(statbuf.st_mode) || (statbuf.st_nlink > 1 && strncmp(ttyn, "/dev/", 5)) || (access(ttyn, R_OK | W_OK) != 0)) { @@ -378,7 +387,7 @@ main(int argc, char **argv) int ask, fflag, hflag, pflag, cnt, errsv; int quietlog, passwd_req; char *domain, *ttyn; - char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_DEV_TTY) + 10]; + char tbuf[MAXPATHLEN + 2]; char *termenv; char *childArgv[10]; char *buff; @@ -495,14 +504,9 @@ main(int argc, char **argv) for (cnt = getdtablesize(); cnt > 2; cnt--) close(cnt); + /* note that libc checks that the file descriptor is a terminal, so we don't + * have to call isatty() here */ ttyn = ttyname(0); - - if (ttyn == NULL || *ttyn == '\0') { - /* no snprintf required - see definition of tname */ - snprintf(tname, sizeof(tname), "%s??", _PATH_DEV_TTY); - ttyn = tname; - } - check_ttyname(ttyn); if (strncmp(ttyn, "/dev/", 5) == 0) -- cgit v1.2.3 From 69a6d78a0ef569ecc75e74c17b216580c46846e4 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Thu, 28 Jan 2010 19:42:04 +0100 Subject: fdisk: use optimal_io_size * rename the minimum_io_size variable to io_size * use blkid_topology_get_optimal_io_size() for io_size initialization * use blkid_topology_get_minimum_io_size() as a fallback solution for io_size initialization Signed-off-by: Karel Zak --- fdisk/fdisk.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index 5ef24f66..6b05bf0e 100644 --- a/fdisk/fdisk.c +++ b/fdisk/fdisk.c @@ -222,7 +222,7 @@ unsigned int heads, display_in_cyl_units = 1; unsigned long long total_number_of_sectors; /* (!) 512-byte sectors */ -unsigned long minimum_io_size, alignment_offset; +unsigned long io_size, alignment_offset; #define dos_label (!sun_label && !sgi_label && !aix_label && !mac_label && !osf_label) int sun_label = 0; /* looking at sun disklabel */ @@ -637,7 +637,7 @@ test_c(char **m, char *mesg) { return val; } -#define alignment_required (minimum_io_size != sector_size) +#define alignment_required (io_size != sector_size) static int lba_is_aligned(unsigned long long lba) @@ -645,9 +645,9 @@ lba_is_aligned(unsigned long long lba) unsigned long long bytes, phy_sectors; bytes = lba * sector_size; - phy_sectors = bytes / minimum_io_size; + phy_sectors = bytes / io_size; - return (alignment_offset + (phy_sectors * minimum_io_size) == bytes); + return (alignment_offset + (phy_sectors * io_size) == bytes); } #define ALIGN_UP 1 @@ -662,7 +662,7 @@ align_lba(unsigned long long lba, int direction) if (lba_is_aligned(lba)) return lba; - sects_in_phy = minimum_io_size / sector_size; + sects_in_phy = io_size / sector_size; if (lba < sects_in_phy) /* align to the first physical sector */ @@ -685,7 +685,7 @@ align_lba(unsigned long long lba, int direction) * at LBA < 0 (usually LBA -1). It means we have to move LBA * according the offset to be on the physical boundary. */ - res -= (minimum_io_size - alignment_offset) / sector_size; + res -= (io_size - alignment_offset) / sector_size; /* fprintf(stderr, "LBA %llu -align-> %llu (%s)\n", lba, res, * lba_is_aligned(res) ? "OK" : "FALSE"); @@ -968,7 +968,9 @@ get_topology(int fd) { blkid_topology tp = blkid_probe_get_topology(pr); if (tp) { - minimum_io_size = blkid_topology_get_minimum_io_size(tp); + io_size = blkid_topology_get_optimal_io_size(tp); + if (!io_size) + io_size = blkid_topology_get_minimum_io_size(tp); alignment_offset = blkid_topology_get_alignment_offset(tp); } } @@ -980,8 +982,8 @@ get_topology(int fd) { else if (blkdev_get_sector_size(fd, &arg) == 0) sector_size = arg; - if (!minimum_io_size) - minimum_io_size = sector_size; + if (!io_size) + io_size = sector_size; if (sector_size != DEFAULT_SECTOR_SIZE) printf(_("Note: sector size is %d (not %d)\n"), @@ -1054,7 +1056,7 @@ update_sector_offset(void) /* * Align the begin of the first partition to the physical block */ - unsigned long long x = minimum_io_size / sector_size; + unsigned long long x = io_size / sector_size; sector_offset = align_lba(x, ALIGN_UP); } @@ -1838,7 +1840,7 @@ list_disk_geometry(void) { units_per_sector, sector_size, units_per_sector * sector_size); printf(_("Sector size (logical/physical): %u bytes / %lu bytes\n"), - sector_size, minimum_io_size); + sector_size, io_size); if (alignment_offset) printf(_("Alignment offset: %lu bytes\n"), alignment_offset); if (dos_label) -- cgit v1.2.3 From f80915d220c4beae54c5001c348d44b34f3cc541 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Thu, 28 Jan 2010 23:34:05 +0100 Subject: fdisk: use "optimal I/O size" in warnings Signed-off-by: Karel Zak --- fdisk/fdisk.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index 6b05bf0e..cc573646 100644 --- a/fdisk/fdisk.c +++ b/fdisk/fdisk.c @@ -779,8 +779,8 @@ warn_alignment(void) { fprintf(stderr, _("\n" "The device presents a logical sector size that is smaller than\n" -"the physical sector size. Aligning to a physical sector boundary\n" -"is recommended, or performance may be impacted.\n\n")); +"the optimal I/O size (often physical sector size). Aligning to a optimal\n" +"I/O size boundary is recommended, or performance may be impacted.\n\n")); /* * Print warning when sector_offset is not aligned for DOS mode @@ -1812,7 +1812,7 @@ static void check_alignment(struct partition *p, int partition) { if (!lba_is_aligned(get_start_sect(p))) - printf(_("Partition %i does not start on physical block boundary.\n"), + printf(_("Partition %i does not start on optimal I/O size boundary.\n"), partition + 1); } @@ -1839,7 +1839,7 @@ list_disk_geometry(void) { str_units(PLURAL), units_per_sector, sector_size, units_per_sector * sector_size); - printf(_("Sector size (logical/physical): %u bytes / %lu bytes\n"), + printf(_("Sector size (logical / optimal IO): %u bytes / %lu bytes\n"), sector_size, io_size); if (alignment_offset) printf(_("Alignment offset: %lu bytes\n"), alignment_offset); -- cgit v1.2.3 From d96648b822a69e88e9597315a03ccb28bf55267a Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 1 Feb 2010 13:07:17 +0100 Subject: libblkid: add blkid_openat(), cleanup blkid_fstatat() Signed-off-by: Karel Zak --- shlibs/blkid/src/blkidP.h | 2 ++ shlibs/blkid/src/devno.c | 24 ++++++++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/shlibs/blkid/src/blkidP.h b/shlibs/blkid/src/blkidP.h index 975878c4..4d21304e 100644 --- a/shlibs/blkid/src/blkidP.h +++ b/shlibs/blkid/src/blkidP.h @@ -267,6 +267,8 @@ extern char *blkid_strndup(const char *s, const int length); extern char *blkid_strconcat(const char *a, const char *b, const char *c); extern int blkid_fstatat(DIR *dir, const char *dirname, const char *filename, struct stat *st, int nofollow); +extern int blkid_openat(DIR *dir, const char *dirname, const char *filename, + int flags); #define BLKID_CACHE_FILE "/etc/blkid.tab" #define BLKID_CONFIG_FILE "/etc/blkid.conf" diff --git a/shlibs/blkid/src/devno.c b/shlibs/blkid/src/devno.c index 7b9438ff..284f8733 100644 --- a/shlibs/blkid/src/devno.c +++ b/shlibs/blkid/src/devno.c @@ -96,14 +96,30 @@ int blkid_fstatat(DIR *dir, const char *dirname, const char *filename, return fstatat(dirfd(dir), filename, st, nofollow ? AT_SYMLINK_NOFOLLOW : 0); #else - char device[PATH_MAX]; + char path[PATH_MAX]; + int len; + + len = snprintf(path, sizeof(path), "%s/%s", dirname, filename); + if (len < 0 || len + 1 > sizeof(path)) + return -1; + + return nofollow ? lstat(path, st) : stat(path, st); +#endif +} + +int blkid_openat(DIR *dir, const char *dirname, const char *filename, int flags) +{ +#ifdef HAVE_FSTATAT + return openat(dirfd(dir), filename, flags); +#else + char path[PATH_MAX]; int len; - len = snprintf(device, sizeof(device), "%s/%s", dirname, filename); - if (len < 0 || len + 1 > sizeof(device)) + len = snprintf(path, sizeof(path), "%s/%s", dirname, filename); + if (len < 0 || len + 1 > sizeof(path)) return -1; - return nofollow ? lstat(device, st) : stat(device, st); + return open(path, flags); #endif } -- cgit v1.2.3 From 49361dc4dca0a9079ee57a2a0d8833aabd93277b Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 1 Feb 2010 14:23:55 +0100 Subject: libblkid: add blkid_probe_all_removable() The libblkid probing is based on devices from /proc/partitions by default. This file usually does not contain removable devices (e.g. CDROMs) and this kind of devices are invisible for libblkid. The blkid_probe_all_removable() function adds removable block devices to blkid cache. The probing is based on information from the /sys directory. The devices which were detected by this function won't be written to blkid.tab cache file. Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=533874 Signed-off-by: Karel Zak --- include/pathnames.h | 2 + shlibs/blkid/src/blkid.h.in | 1 + shlibs/blkid/src/blkid.sym | 8 ++++ shlibs/blkid/src/blkidP.h | 1 + shlibs/blkid/src/devname.c | 110 +++++++++++++++++++++++++++++++++++++++++--- shlibs/blkid/src/save.c | 2 +- 6 files changed, 116 insertions(+), 8 deletions(-) diff --git a/include/pathnames.h b/include/pathnames.h index efe5c3bc..9c4eb009 100644 --- a/include/pathnames.h +++ b/include/pathnames.h @@ -76,6 +76,8 @@ #define _PATH_PROC_PARTITIONS "/proc/partitions" #define _PATH_PROC_DEVICES "/proc/devices" +#define _PATH_SYS_BLOCK "/sys/block" + #ifndef _PATH_MOUNTED # ifdef MOUNTED /* deprecated */ # define _PATH_MOUNTED MOUNTED diff --git a/shlibs/blkid/src/blkid.h.in b/shlibs/blkid/src/blkid.h.in index febb4372..4e53b39f 100644 --- a/shlibs/blkid/src/blkid.h.in +++ b/shlibs/blkid/src/blkid.h.in @@ -142,6 +142,7 @@ extern int blkid_devno_to_wholedisk(dev_t dev, char *diskname, /* devname.c */ extern int blkid_probe_all(blkid_cache cache); extern int blkid_probe_all_new(blkid_cache cache); +extern int blkid_probe_all_removable(blkid_cache cache); extern blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags); diff --git a/shlibs/blkid/src/blkid.sym b/shlibs/blkid/src/blkid.sym index 97255526..4d01aa20 100644 --- a/shlibs/blkid/src/blkid.sym +++ b/shlibs/blkid/src/blkid.sym @@ -114,3 +114,11 @@ global: blkid_topology_get_optimal_io_size; blkid_topology_get_physical_sector_size; } BLKID_2.15; + +/* + * version(s) since util-linux-ng 2.18 + */ +BLKID_2.18 { +global: + blkid_probe_all_removable; +} BLKID_2.17; diff --git a/shlibs/blkid/src/blkidP.h b/shlibs/blkid/src/blkidP.h index 4d21304e..d15b5305 100644 --- a/shlibs/blkid/src/blkidP.h +++ b/shlibs/blkid/src/blkidP.h @@ -51,6 +51,7 @@ struct blkid_struct_dev #define BLKID_BID_FL_VERIFIED 0x0001 /* Device data validated from disk */ #define BLKID_BID_FL_INVALID 0x0004 /* Device is invalid */ +#define BLKID_BID_FL_REMOVABLE 0x0008 /* Device added by blkid_probe_all_removable() */ /* * Each tag defines a NAME=value pair for a particular device. The tags diff --git a/shlibs/blkid/src/devname.c b/shlibs/blkid/src/devname.c index d048c722..5d6da891 100644 --- a/shlibs/blkid/src/devname.c +++ b/shlibs/blkid/src/devname.c @@ -22,6 +22,7 @@ #include #include #include +#include #if HAVE_SYS_TYPES_H #include #endif @@ -38,7 +39,9 @@ #include #include "blkidP.h" + #include "canonicalize.h" /* $(top_srcdir)/include */ +#include "pathnames.h" /* * Find a dev struct in the cache by device name, if available. @@ -157,7 +160,7 @@ static int is_dm_leaf(const char *devname) * Probe a single block device to add to the device cache. */ static void probe_one(blkid_cache cache, const char *ptname, - dev_t devno, int pri, int only_if_new) + dev_t devno, int pri, int only_if_new, int removable) { blkid_dev dev = NULL; struct list_head *p, *pnext; @@ -237,6 +240,8 @@ set_pri: dev->bid_pri += 5; } else if (!strncmp(ptname, "md", 2)) dev->bid_pri = BLKID_PRI_MD; + if (removable) + dev->bid_flags |= BLKID_BID_FL_REMOVABLE; } return; } @@ -328,7 +333,7 @@ static void lvm_probe_all(blkid_cache cache, int only_if_new) lvm_device, (unsigned int) dev)); probe_one(cache, lvm_device, dev, BLKID_PRI_LVM, - only_if_new); + only_if_new, 0); free(lvm_device); } closedir(lv_list); @@ -360,7 +365,7 @@ evms_probe_all(blkid_cache cache, int only_if_new) device, ma, mi)); probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS, - only_if_new); + only_if_new, 0); num++; } fclose(procpt); @@ -408,7 +413,7 @@ ubi_probe_all(blkid_cache cache, int only_if_new) continue; DBG(DEBUG_DEVNAME, printf("UBI vol %s/%s: devno 0x%04X\n", *dirname, name, (int) dev)); - probe_one(cache, name, dev, BLKID_PRI_UBI, only_if_new); + probe_one(cache, name, dev, BLKID_PRI_UBI, only_if_new, 0); } closedir(dir); } @@ -485,7 +490,7 @@ static int probe_all(blkid_cache cache, int only_if_new) if (sz > 1) probe_one(cache, ptname, devs[which], 0, - only_if_new); + only_if_new, 0); lens[which] = 0; /* mark as checked */ } @@ -522,20 +527,81 @@ static int probe_all(blkid_cache cache, int only_if_new) printf("whole dev %s, devno 0x%04X\n", ptnames[last], (unsigned int) devs[last])); probe_one(cache, ptnames[last], devs[last], 0, - only_if_new); + only_if_new, 0); lens[last] = 0; } } /* Handle the last device if it wasn't partitioned */ if (lens[which]) - probe_one(cache, ptname, devs[which], 0, only_if_new); + probe_one(cache, ptname, devs[which], 0, only_if_new, 0); fclose(proc); blkid_flush_cache(cache); return 0; } +/* Don't use it by default -- it's pretty slow (because cdroms, floppy, ...) + */ +static int probe_all_removable(blkid_cache cache) +{ + DIR *dir; + struct dirent *d; + char buf[PATH_MAX]; + + if (!cache) + return -BLKID_ERR_PARAM; + + dir = opendir(_PATH_SYS_BLOCK); + if (!dir) + return -BLKID_ERR_PROC; + + while((d = readdir(dir))) { + int fd, rc, ma, mi; + +#ifdef _DIRENT_HAVE_D_TYPE + if (d->d_type != DT_UNKNOWN && d->d_type != DT_LNK) + continue; +#endif + if (d->d_name[0] == '.' && + ((d->d_name[1] == 0) || + ((d->d_name[1] == '.') && (d->d_name[2] == 0)))) + continue; + + snprintf(buf, sizeof(buf), "%s/removable", d->d_name); + fd = blkid_openat(dir, _PATH_SYS_BLOCK, buf, O_RDONLY); + if (fd < 0) + continue; + + rc = read(fd, buf, 1); + close(fd); + + if (rc != 1 || *buf != '1') + continue; /* not removable device */ + + /* get devno */ + snprintf(buf, sizeof(buf), "%s/dev", d->d_name); + fd = blkid_openat(dir, _PATH_SYS_BLOCK, buf, O_RDONLY); + if (fd < 0) + continue; + + rc = read(fd, buf, sizeof(buf)); + close(fd); + + if (rc < 3) + continue; /* M:N */ + buf[rc] = '\0'; + if (sscanf(buf, "%d:%d", &ma, &mi) != 2) + continue; + + probe_one(cache, d->d_name, makedev(ma, mi), 0, 0, 1); + } + + closedir(dir); + return 0; +} + + /** * blkid_probe_all: * @cache: cache handler @@ -574,6 +640,33 @@ int blkid_probe_all_new(blkid_cache cache) return ret; } +/** + * blkid_probe_all_removable: + * @cache: cache handler + * + * The libblkid probing is based on devices from /proc/partitions by default. + * This file usually does not contain removable devices (e.g. CDROMs) and this kind + * of devices are invisible for libblkid. + * + * This function adds removable block devices to @cache (probing is based on + * information from the /sys directory). Don't forget that removable devices + * (floppies, CDROMs, ...) could be pretty slow. It's very bad idea to call + * this function by default. + * + * Note that devices which were detected by this function won't be written to + * blkid.tab cache file. + * + * Returns: 0 on success, or number less than zero in case of error. + */ +int blkid_probe_all_removable(blkid_cache cache) +{ + int ret; + + DBG(DEBUG_PROBE, printf("Begin blkid_probe_all_removable()\n")); + ret = probe_all_removable(cache); + DBG(DEBUG_PROBE, printf("End blkid_probe_all_removable()\n")); + return ret; +} #ifdef TEST_PROGRAM int main(int argc, char **argv) @@ -595,6 +688,9 @@ int main(int argc, char **argv) if (blkid_probe_all(cache) < 0) printf("%s: error probing devices\n", argv[0]); + if (blkid_probe_all_removable(cache) < 0) + printf("%s: error probing removable devices\n", argv[0]); + blkid_put_cache(cache); return (0); } diff --git a/shlibs/blkid/src/save.c b/shlibs/blkid/src/save.c index c61373d5..a1583ecc 100644 --- a/shlibs/blkid/src/save.c +++ b/shlibs/blkid/src/save.c @@ -119,7 +119,7 @@ int blkid_flush_cache(blkid_cache cache) list_for_each(p, &cache->bic_devs) { blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs); - if (!dev->bid_type) + if (!dev->bid_type || (dev->bid_flags & BLKID_BID_FL_REMOVABLE)) continue; if ((ret = save_dev(dev, file)) < 0) break; -- cgit v1.2.3 From bb4cb69df2a7fba3098f073aa4b758a8011d826f Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 24 Jan 2010 22:36:55 -0500 Subject: fsck/mkfs/mount: unify default search paths for helpers Rather than each fs util having its own search policy, unify the paths in configure and allow them to be tweaked by downstream. In the process, drop the /etc paths as no one has ever really used these. [kzak@redhat.com: - backport to autoconf < 2.64 (remove AS_{SET,IF,CASE,APPEND} macros)] Signed-off-by: Mike Frysinger Signed-off-by: Karel Zak --- configure.ac | 28 ++++++++++ disk-utils/mkfs.c | 2 +- fsck/fsck.c | 2 +- mount/mount.c | 149 ++++++++++++++++++++++++++++++------------------------ 4 files changed, 112 insertions(+), 69 deletions(-) diff --git a/configure.ac b/configure.ac index 1fef9444..e36b8f6b 100644 --- a/configure.ac +++ b/configure.ac @@ -960,6 +960,34 @@ if test "x$enable_require_password" = xyes; then fi +AC_DEFUN([FS_PATHS_DEFAULT], [/sbin:/sbin/fs.d:/sbin/fs]) +AC_ARG_ENABLE([fs-paths-default], + AS_HELP_STRING([--enable-fs-paths-default=paths], [default search path for fs helpers @<:@FS_PATHS_DEFAULT@:>@]), + [case "$enableval" in + yes) fs_paths_defaults="FS_PATHS_DEFAULT" ;; + no) fs_paths_defaults="" ;; + *) fs_paths_defaults="$enableval" ;; + esac], + [fs_paths_defaults="FS_PATHS_DEFAULT"] +) +AC_ARG_ENABLE([fs-paths-extra], + AS_HELP_STRING([--enable-fs-paths-extra=paths], [additional search paths for fs helpers]), + [case "$enableval" in + yes|no) fs_paths_extra="" ;; + *) fs_paths_extra="$enableval" ;; + esac], + [fs_paths_extra=""] +) +fs_paths="$fs_paths_defaults" +if test "x$fs_paths_extra" != "x"; then + if test "x$fs_paths" != "x"; then + fs_paths="${fs_paths}:" + fi + fs_paths="${fs_paths}${fs_paths_extra}" +fi +AC_DEFINE_UNQUOTED([FS_SEARCH_PATH], "$fs_paths", [search path for fs helpers]) + + AC_ARG_ENABLE([use-tty-group], AS_HELP_STRING([--disable-use-tty-group], [do not install wall and write setgid tty]), [], enable_use_tty_group=yes diff --git a/disk-utils/mkfs.c b/disk-utils/mkfs.c index 120da063..a0ccd16f 100644 --- a/disk-utils/mkfs.c +++ b/disk-utils/mkfs.c @@ -27,7 +27,7 @@ # define DEFAULT_FSTYPE "ext2" #endif -#define SEARCH_PATH "PATH=/sbin:/sbin/fs:/sbin/fs.d:/etc/fs:/etc" +#define SEARCH_PATH "PATH=" FS_SEARCH_PATH #define PROGNAME "mkfs.%s" diff --git a/fsck/fsck.c b/fsck/fsck.c index 66c027c7..45d8484a 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -105,7 +105,7 @@ char *progname; char *fstype = NULL; struct fs_info *filesys_info = NULL, *filesys_last = NULL; struct fsck_instance *instance_list; -const char *fsck_prefix_path = "/sbin:/sbin/fs.d:/sbin/fs:/etc/fs:/etc"; +const char fsck_prefix_path[] = FS_SEARCH_PATH; char *fsck_path = 0; static char *string_copy(const char *s) diff --git a/mount/mount.c b/mount/mount.c index 0cef101a..5cefdccc 100644 --- a/mount/mount.c +++ b/mount/mount.c @@ -639,74 +639,89 @@ do_mount (struct mountargs *args, int *special, int *status) { static int check_special_mountprog(const char *spec, const char *node, const char *type, int flags, char *extra_opts, int *status) { - char mountprog[120]; - struct stat statbuf; - int res; - - if (!external_allowed) - return 0; - - if (type == NULL || strcmp(type, "none") == 0) - return 0; - - if (strlen(type) < 100) { - sprintf(mountprog, "/sbin/mount.%s", type); - if (stat(mountprog, &statbuf) == 0) { - if (verbose) - fflush(stdout); - res = fork(); - if (res == 0) { - char *oo, *mountargs[10]; - int i = 0; - - if(setgid(getgid()) < 0) - die(EX_FAIL, _("mount: cannot set group id: %s"), strerror(errno)); - - if(setuid(getuid()) < 0) - die(EX_FAIL, _("mount: cannot set user id: %s"), strerror(errno)); - - oo = fix_opts_string (flags, extra_opts, NULL); - mountargs[i++] = mountprog; /* 1 */ - mountargs[i++] = (char *) spec; /* 2 */ - mountargs[i++] = (char *) node; /* 3 */ - if (sloppy && strncmp(type, "nfs", 3) == 0) - mountargs[i++] = "-s"; /* 4 */ - if (fake) - mountargs[i++] = "-f"; /* 5 */ - if (nomtab) - mountargs[i++] = "-n"; /* 6 */ - if (verbose) - mountargs[i++] = "-v"; /* 7 */ - if (oo && *oo) { - mountargs[i++] = "-o"; /* 8 */ - mountargs[i++] = oo; /* 9 */ - } - mountargs[i] = NULL; /* 10 */ - - if (verbose > 2) { - i = 0; - while(mountargs[i]) { - printf("mount: external mount: argv[%d] = \"%s\"\n", - i, mountargs[i]); - i++; - } + char search_path[] = FS_SEARCH_PATH; + char *path, mountprog[150]; + struct stat statbuf; + int res; + + if (!external_allowed) + return 0; + + if (type == NULL || strcmp(type, "none") == 0) + return 0; + + path = strtok(search_path, ":"); + while (path) { + res = snprintf(mountprog, sizeof(mountprog), "%s/mount.%s", + path, type); + path = strtok(NULL, ":"); + if (res >= sizeof(mountprog) || res < 0) + continue; + + if (stat(mountprog, &statbuf)) + continue; + + if (verbose) fflush(stdout); - } - - execv(mountprog, mountargs); - exit(1); /* exec failed */ - } else if (res != -1) { - int st; - wait(&st); - *status = (WIFEXITED(st) ? WEXITSTATUS(st) : EX_SYSERR); - return 1; - } else { - int errsv = errno; - error(_("mount: cannot fork: %s"), strerror(errsv)); - } - } - } - return 0; + + switch (fork()) { + case 0: { /* child */ + char *oo, *mountargs[10]; + int i = 0; + + if (setgid(getgid()) < 0) + die(EX_FAIL, _("mount: cannot set group id: %s"), strerror(errno)); + + if (setuid(getuid()) < 0) + die(EX_FAIL, _("mount: cannot set user id: %s"), strerror(errno)); + + oo = fix_opts_string (flags, extra_opts, NULL); + mountargs[i++] = mountprog; /* 1 */ + mountargs[i++] = (char *) spec; /* 2 */ + mountargs[i++] = (char *) node; /* 3 */ + if (sloppy && strncmp(type, "nfs", 3) == 0) + mountargs[i++] = "-s"; /* 4 */ + if (fake) + mountargs[i++] = "-f"; /* 5 */ + if (nomtab) + mountargs[i++] = "-n"; /* 6 */ + if (verbose) + mountargs[i++] = "-v"; /* 7 */ + if (oo && *oo) { + mountargs[i++] = "-o"; /* 8 */ + mountargs[i++] = oo; /* 9 */ + } + mountargs[i] = NULL; /* 10 */ + + if (verbose > 2) { + i = 0; + while (mountargs[i]) { + printf("mount: external mount: argv[%d] = \"%s\"\n", + i, mountargs[i]); + i++; + } + fflush(stdout); + } + + execv(mountprog, mountargs); + exit(1); /* exec failed */ + } + + default: { /* parent */ + int st; + wait(&st); + *status = (WIFEXITED(st) ? WEXITSTATUS(st) : EX_SYSERR); + return 1; + } + + case -1: { /* error */ + int errsv = errno; + error(_("mount: cannot fork: %s"), strerror(errsv)); + } + } + } + + return 0; } -- cgit v1.2.3 From 5f9fb168f3b710e4ff17139182112e2594fdb583 Mon Sep 17 00:00:00 2001 From: Jeroen Oortwijn Date: Thu, 14 Jan 2010 19:01:36 +0100 Subject: libblkid: Add initial support for BeFS detection Add initial support for detection of the Be File System to libblkid. Signed-off-by: Jeroen Oortwijn --- shlibs/blkid/src/superblocks/Makefile.am | 3 ++- shlibs/blkid/src/superblocks/befs.c | 18 ++++++++++++++++++ shlibs/blkid/src/superblocks/superblocks.c | 3 ++- shlibs/blkid/src/superblocks/superblocks.h | 1 + 4 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 shlibs/blkid/src/superblocks/befs.c diff --git a/shlibs/blkid/src/superblocks/Makefile.am b/shlibs/blkid/src/superblocks/Makefile.am index 33e5d0c3..f5b88b8e 100644 --- a/shlibs/blkid/src/superblocks/Makefile.am +++ b/shlibs/blkid/src/superblocks/Makefile.am @@ -45,4 +45,5 @@ libblkid_superblocks_la_SOURCES = \ ubifs.c \ bfs.c \ drbd.c \ - vmfs.c + vmfs.c \ + befs.c diff --git a/shlibs/blkid/src/superblocks/befs.c b/shlibs/blkid/src/superblocks/befs.c new file mode 100644 index 00000000..73d831df --- /dev/null +++ b/shlibs/blkid/src/superblocks/befs.c @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2010 Jeroen Oortwijn + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ + +#include "superblocks.h" + +const struct blkid_idinfo befs_idinfo = +{ + .name = "befs", + .usage = BLKID_USAGE_FILESYSTEM, + .magics = { + { .magic = "1SFB", .len = 4, .sboff = 0x220 }, + { NULL } + } +}; diff --git a/shlibs/blkid/src/superblocks/superblocks.c b/shlibs/blkid/src/superblocks/superblocks.c index 689f31bd..fd12e5ec 100644 --- a/shlibs/blkid/src/superblocks/superblocks.c +++ b/shlibs/blkid/src/superblocks/superblocks.c @@ -138,7 +138,8 @@ static const struct blkid_idinfo *idinfos[] = &btrfs_idinfo, &ubifs_idinfo, &bfs_idinfo, - &vmfs_fs_idinfo + &vmfs_fs_idinfo, + &befs_idinfo }; /* diff --git a/shlibs/blkid/src/superblocks/superblocks.h b/shlibs/blkid/src/superblocks/superblocks.h index 893ae72a..12f197e5 100644 --- a/shlibs/blkid/src/superblocks/superblocks.h +++ b/shlibs/blkid/src/superblocks/superblocks.h @@ -64,6 +64,7 @@ extern const struct blkid_idinfo bfs_idinfo; extern const struct blkid_idinfo vmfs_volume_idinfo; extern const struct blkid_idinfo vmfs_fs_idinfo; extern const struct blkid_idinfo drbd_idinfo; +extern const struct blkid_idinfo befs_idinfo; /* * superblock functions -- cgit v1.2.3 From b39ee04ed85a94b5540a99471421a0703b847f7a Mon Sep 17 00:00:00 2001 From: Jeroen Oortwijn Date: Fri, 29 Jan 2010 23:20:49 +0100 Subject: libblkid: Add probing function for BeFS Add probing function for the Be File System to libblkid. It sets LABEL, VERSION and UUID. But UUID is only set if the be:volume_id attribute is found in the small_data area of the i-node of the root directory. [kzak@redhat.com: - add .minsz = 1024*1440 to avoid BeFS probing on very small devices] Signed-off-by: Jeroen Oortwijn Signed-off-by: Karel Zak --- shlibs/blkid/src/superblocks/befs.c | 183 +++++++++++++++++++++++++++++++++++- 1 file changed, 182 insertions(+), 1 deletion(-) diff --git a/shlibs/blkid/src/superblocks/befs.c b/shlibs/blkid/src/superblocks/befs.c index 73d831df..0ce84975 100644 --- a/shlibs/blkid/src/superblocks/befs.c +++ b/shlibs/blkid/src/superblocks/befs.c @@ -4,15 +4,196 @@ * This file may be redistributed under the terms of the * GNU Lesser General Public License. */ +#include +#include +#include +#include +#include #include "superblocks.h" +#define B_OS_NAME_LENGTH 0x20 +#define SUPER_BLOCK_MAGIC1 0x42465331 /* BFS1 */ +#define SUPER_BLOCK_MAGIC2 0xdd121031 +#define SUPER_BLOCK_MAGIC3 0x15b6830e +#define SUPER_BLOCK_FS_ENDIAN 0x42494745 /* BIGE */ +#define INODE_MAGIC1 0x3bbe0ad9 +#define B_UINT64_TYPE 0x554C4C47 /* ULLG */ + +#define FS16_TO_CPU(value, fs_is_le) (fs_is_le ? le16_to_cpu(value) \ + : be16_to_cpu(value)) +#define FS32_TO_CPU(value, fs_is_le) (fs_is_le ? le32_to_cpu(value) \ + : be32_to_cpu(value)) +#define FS64_TO_CPU(value, fs_is_le) (fs_is_le ? le64_to_cpu(value) \ + : be64_to_cpu(value)) + +typedef struct block_run { + int32_t allocation_group; + uint16_t start; + uint16_t len; +} __attribute__((packed)) block_run, inode_addr; + +struct befs_super_block { + char name[B_OS_NAME_LENGTH]; + int32_t magic1; + int32_t fs_byte_order; + uint32_t block_size; + uint32_t block_shift; + int64_t num_blocks; + int64_t used_blocks; + int32_t inode_size; + int32_t magic2; + int32_t blocks_per_ag; + int32_t ag_shift; + int32_t num_ags; + int32_t flags; + block_run log_blocks; + int64_t log_start; + int64_t log_end; + int32_t magic3; + inode_addr root_dir; + inode_addr indices; + int32_t pad[8]; +} __attribute__((packed)); + +typedef struct data_stream { + block_run direct[12]; + int64_t max_direct_range; + block_run indirect; + int64_t max_indirect_range; + block_run double_indirect; + int64_t max_double_indirect_range; + int64_t size; +} __attribute__((packed)) data_stream; + +struct befs_inode { + int32_t magic1; + inode_addr inode_num; + int32_t uid; + int32_t gid; + int32_t mode; + int32_t flags; + int64_t create_time; + int64_t last_modified_time; + inode_addr parent; + inode_addr attributes; + uint32_t type; + int32_t inode_size; + uint32_t etc; + data_stream data; + int32_t pad[4]; + int32_t small_data[1]; +} __attribute__((packed)); + +struct small_data { + uint32_t type; + uint16_t name_size; + uint16_t data_size; + char name[0]; +} __attribute__((packed)); + +static int probe_befs(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct befs_super_block *bs; + struct befs_inode *bi; + struct small_data *sd; + int fs_le; + uint64_t volume_id = 0; + + bs = (struct befs_super_block *) blkid_probe_get_buffer(pr, + mag->sboff - B_OS_NAME_LENGTH, + sizeof(struct befs_super_block)); + if (!bs) + return -1; + + if (le32_to_cpu(bs->magic1) == SUPER_BLOCK_MAGIC1 + && le32_to_cpu(bs->magic2) == SUPER_BLOCK_MAGIC2 + && le32_to_cpu(bs->magic3) == SUPER_BLOCK_MAGIC3 + && le32_to_cpu(bs->fs_byte_order) == SUPER_BLOCK_FS_ENDIAN) { + fs_le = 1; + blkid_probe_set_version(pr, "little-endian"); + } else if (be32_to_cpu(bs->magic1) == SUPER_BLOCK_MAGIC1 + && be32_to_cpu(bs->magic2) == SUPER_BLOCK_MAGIC2 + && be32_to_cpu(bs->magic3) == SUPER_BLOCK_MAGIC3 + && be32_to_cpu(bs->fs_byte_order) == SUPER_BLOCK_FS_ENDIAN) { + fs_le = 0; + blkid_probe_set_version(pr, "big-endian"); + } else { + return -1; + } + + if (strlen(bs->name)) + blkid_probe_set_label(pr, (unsigned char *) bs->name, + sizeof(bs->name)); + + bi = (struct befs_inode *) blkid_probe_get_buffer(pr, + (FS32_TO_CPU(bs->root_dir.allocation_group, fs_le) + << FS32_TO_CPU(bs->ag_shift, fs_le) + << FS32_TO_CPU(bs->block_shift, fs_le)) + + (FS16_TO_CPU(bs->root_dir.start, fs_le) + << FS32_TO_CPU(bs->block_shift, fs_le)), + FS16_TO_CPU(bs->root_dir.len, fs_le) + << FS32_TO_CPU(bs->block_shift, fs_le)); + if (!bi) + return -1; + + if (FS32_TO_CPU(bi->magic1, fs_le) != INODE_MAGIC1) + return -1; + + sd = (struct small_data *) bi->small_data; + + do { + if (FS32_TO_CPU(sd->type, fs_le) == B_UINT64_TYPE + && FS16_TO_CPU(sd->name_size, fs_le) == 12 + && FS16_TO_CPU(sd->data_size, fs_le) == 8 + && strcmp(sd->name, "be:volume_id") == 0) { + volume_id = *(uint64_t *) ((uint8_t *) sd->name + + FS16_TO_CPU(sd->name_size, fs_le) + + 3); + blkid_probe_sprintf_uuid(pr, + (unsigned char *) &volume_id, + sizeof(volume_id), + "%016" PRIx64, + FS64_TO_CPU(volume_id, fs_le)); + break; + } else if (FS32_TO_CPU(sd->type, fs_le) == 0 + && FS16_TO_CPU(sd->name_size, fs_le) == 0 + && FS16_TO_CPU(sd->data_size, fs_le) == 0) { + break; + } + + sd = (struct small_data *) ((uint8_t *) sd + + sizeof(struct small_data) + + FS16_TO_CPU(sd->name_size, fs_le) + 3 + + FS16_TO_CPU(sd->data_size, fs_le) + 1); + + } while ((intptr_t) sd < (intptr_t) bi + + FS32_TO_CPU(bi->inode_size, fs_le) + - sizeof(struct small_data)); + + if (volume_id == 0) { + /* + * TODO: Search for the be:volume_id attribute in the + * attributes directory of the root directory. + */ + } + + return 0; +} + const struct blkid_idinfo befs_idinfo = { .name = "befs", .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_befs, + .minsz = 1024 * 1440, .magics = { - { .magic = "1SFB", .len = 4, .sboff = 0x220 }, + { .magic = "BFS1", .len = 4, .sboff = B_OS_NAME_LENGTH }, + { .magic = "1SFB", .len = 4, .sboff = B_OS_NAME_LENGTH }, + { .magic = "BFS1", .len = 4, .sboff = 0x200 + + B_OS_NAME_LENGTH }, + { .magic = "1SFB", .len = 4, .sboff = 0x200 + + B_OS_NAME_LENGTH }, { NULL } } }; -- cgit v1.2.3 From 2a986d6a5372710f6f6f287e00809e915359d545 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 2 Feb 2010 15:49:35 +0100 Subject: tests: add BeFS test image Signed-off-by: Karel Zak --- tests/expected/blkid/low-probe-befs | 7 +++++++ tests/ts/blkid/images-fs/befs.img.bz2 | Bin 0 -> 899614 bytes 2 files changed, 7 insertions(+) create mode 100644 tests/expected/blkid/low-probe-befs create mode 100644 tests/ts/blkid/images-fs/befs.img.bz2 diff --git a/tests/expected/blkid/low-probe-befs b/tests/expected/blkid/low-probe-befs new file mode 100644 index 00000000..b7f25cdd --- /dev/null +++ b/tests/expected/blkid/low-probe-befs @@ -0,0 +1,7 @@ +ID_FS_LABEL=befs_test +ID_FS_LABEL_ENC=befs_test +ID_FS_TYPE=befs +ID_FS_USAGE=filesystem +ID_FS_UUID=95d89dec82f6b73b +ID_FS_UUID_ENC=95d89dec82f6b73b +ID_FS_VERSION=little-endian diff --git a/tests/ts/blkid/images-fs/befs.img.bz2 b/tests/ts/blkid/images-fs/befs.img.bz2 new file mode 100644 index 00000000..0913da24 Binary files /dev/null and b/tests/ts/blkid/images-fs/befs.img.bz2 differ -- cgit v1.2.3 From a39ff47a185f23b370f8f5b535dfa69b263e22e3 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 2 Feb 2010 16:01:28 +0100 Subject: libblkid: minor fixes in befs.c The library does not reset the probing result (e.g. LABEL, VERSION) when the probing function failed (return value != 0). We have to be absolutely sure that the FS has been properly detected before we set LABEL or VERSION or so. Signed-off-by: Karel Zak --- shlibs/blkid/src/superblocks/befs.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/shlibs/blkid/src/superblocks/befs.c b/shlibs/blkid/src/superblocks/befs.c index 0ce84975..b341402a 100644 --- a/shlibs/blkid/src/superblocks/befs.c +++ b/shlibs/blkid/src/superblocks/befs.c @@ -99,6 +99,7 @@ static int probe_befs(blkid_probe pr, const struct blkid_idmag *mag) struct small_data *sd; int fs_le; uint64_t volume_id = 0; + const char *version = NULL; bs = (struct befs_super_block *) blkid_probe_get_buffer(pr, mag->sboff - B_OS_NAME_LENGTH, @@ -111,20 +112,15 @@ static int probe_befs(blkid_probe pr, const struct blkid_idmag *mag) && le32_to_cpu(bs->magic3) == SUPER_BLOCK_MAGIC3 && le32_to_cpu(bs->fs_byte_order) == SUPER_BLOCK_FS_ENDIAN) { fs_le = 1; - blkid_probe_set_version(pr, "little-endian"); + version = "little-endian"; } else if (be32_to_cpu(bs->magic1) == SUPER_BLOCK_MAGIC1 && be32_to_cpu(bs->magic2) == SUPER_BLOCK_MAGIC2 && be32_to_cpu(bs->magic3) == SUPER_BLOCK_MAGIC3 && be32_to_cpu(bs->fs_byte_order) == SUPER_BLOCK_FS_ENDIAN) { fs_le = 0; - blkid_probe_set_version(pr, "big-endian"); - } else { + version = "big-endian"; + } else return -1; - } - - if (strlen(bs->name)) - blkid_probe_set_label(pr, (unsigned char *) bs->name, - sizeof(bs->name)); bi = (struct befs_inode *) blkid_probe_get_buffer(pr, (FS32_TO_CPU(bs->root_dir.allocation_group, fs_le) @@ -140,6 +136,18 @@ static int probe_befs(blkid_probe pr, const struct blkid_idmag *mag) if (FS32_TO_CPU(bi->magic1, fs_le) != INODE_MAGIC1) return -1; + /* + * all checks pass, set LABEL and VERSION + */ + if (strlen(bs->name)) + blkid_probe_set_label(pr, (unsigned char *) bs->name, + sizeof(bs->name)); + if (version) + blkid_probe_set_version(pr, version); + + /* + * search for UUID + */ sd = (struct small_data *) bi->small_data; do { -- cgit v1.2.3 From 0fefbedc72f5b8399be50ae0aad8eb9cb3b630a3 Mon Sep 17 00:00:00 2001 From: Adrian Knoth Date: Tue, 2 Feb 2010 17:18:29 +0100 Subject: chrt: add support for SCHED_RESET_ON_FORK From 9262c9832134f8a33ac2ea2854dc6d20acc712d1 Mon Sep 17 00:00:00 2001 From: Adrian Knoth Date: Tue, 2 Feb 2010 16:57:23 +0100 Subject: [PATCH] Add support for SCHED_RESET_ON_FORK to chrt SCHED_RESET_ON_FORK has been added in 2.6.31. If a thread has this flag set, chrt reports "unknown" policy, which is confusing. The patch adds support for this new flag. It will (can) only be applied to SCHED_FIFO or SCHED_RR, so there's no need to catch the other scheduling policies. Signed-off-by: Adrian Knoth --- schedutils/chrt.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/schedutils/chrt.c b/schedutils/chrt.c index 6953addd..6629c2e8 100644 --- a/schedutils/chrt.c +++ b/schedutils/chrt.c @@ -47,6 +47,11 @@ # define SCHED_IDLE 5 #endif +#if defined(__linux__) && !defined(SCHED_RESET_ON_FORK) +#define SCHED_RESET_ON_FORK 0x40000000 +#endif + + static void show_usage(int rc) { fprintf(stdout, _( @@ -92,6 +97,9 @@ static void show_rt_info(const char *what, pid_t pid) case SCHED_FIFO: printf("SCHED_FIFO\n"); break; + case SCHED_FIFO|SCHED_RESET_ON_FORK: + printf("SCHED_FIFO|SCHED_RESET_ON_FORK\n"); + break; #ifdef SCHED_IDLE case SCHED_IDLE: printf("SCHED_IDLE\n"); @@ -100,6 +108,9 @@ static void show_rt_info(const char *what, pid_t pid) case SCHED_RR: printf("SCHED_RR\n"); break; + case SCHED_RR|SCHED_RESET_ON_FORK: + printf("SCHED_RR|SCHED_RESET_ON_FORK\n"); + break; #ifdef SCHED_BATCH case SCHED_BATCH: printf("SCHED_BATCH\n"); -- cgit v1.2.3 From cdfb1e88228c10c28f8bfe0f4b0ff1b3b06d1ed4 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 2 Feb 2010 21:24:52 +0100 Subject: chrt: add --reset-on-fork This new option allows to set SCHED_RESET_ON_FORK flag for FIFO and RR policies. Example: $ chrt --fifo --reset-on-fork 1 /bin/bash $ schedutils/chrt --pid $$ pid 31579's current scheduling policy: SCHED_FIFO|SCHED_RESET_ON_FORK pid 31579's current scheduling priority: 1 Signed-off-by: Karel Zak --- schedutils/chrt.1 | 14 ++++++++++++++ schedutils/chrt.c | 18 ++++++++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/schedutils/chrt.1 b/schedutils/chrt.1 index 06c58b47..9016cfef 100644 --- a/schedutils/chrt.1 +++ b/schedutils/chrt.1 @@ -55,6 +55,11 @@ The policy is supported since Linux 2.6.16. The .BR SCHED_IDLE policy is supported since Linux 2.6.23. +.PP +The +.BR SCHED_RESET_ON_FORK +flag for policies SCHED_RR and SCHED_FIFO is supported +since Linux 2.6.31. .SH OPTIONS .TP .B -p, --pid @@ -69,6 +74,15 @@ set scheduling policy to set scheduling policy to .BR SCHED_FIFO .TP +.B -R, --reset-on-fork +add +.B SCHED_RESET_ON_FORK +flag to the +.B SCHED_FIFO +or +.B SCHED_RR +scheduling policy (Linux specific) +.TP .B -i, --idle set schedulng policy to .BR SCHED_IDLE diff --git a/schedutils/chrt.c b/schedutils/chrt.c index 6629c2e8..0ff9b9bb 100644 --- a/schedutils/chrt.c +++ b/schedutils/chrt.c @@ -66,6 +66,8 @@ static void show_usage(int rc) " -i | --idle set policy to SCHED_IDLE\n" " -o | --other set policy to SCHED_OTHER\n" " -r | --rr set policy to SCHED_RR (default)\n" + "\nScheduling flags:\n" + " -R | --reset-on-fork set SCHED_RESET_ON_FORK for FIFO or RR\n" "\nOptions:\n" " -h | --help display this help\n" " -p | --pid operate on existing given pid\n" @@ -161,7 +163,7 @@ static void show_min_max(void) int main(int argc, char *argv[]) { - int i, policy = SCHED_RR, priority = 0, verbose = 0; + int i, policy = SCHED_RR, priority = 0, verbose = 0, policy_flag = 0; struct sched_param sp; pid_t pid = -1; @@ -174,6 +176,7 @@ int main(int argc, char *argv[]) { "max", 0, NULL, 'm' }, { "other", 0, NULL, 'o' }, { "rr", 0, NULL, 'r' }, + { "reset-on-fork", 0, NULL, 'R' }, { "verbose", 0, NULL, 'v' }, { "version", 0, NULL, 'V' }, { NULL, 0, NULL, 0 } @@ -183,7 +186,7 @@ int main(int argc, char *argv[]) bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); - while((i = getopt_long(argc, argv, "+bfiphmorvV", longopts, NULL)) != -1) + while((i = getopt_long(argc, argv, "+bfiphmoRrvV", longopts, NULL)) != -1) { int ret = EXIT_FAILURE; @@ -196,6 +199,9 @@ int main(int argc, char *argv[]) case 'f': policy = SCHED_FIFO; break; + case 'R': + policy_flag |= SCHED_RESET_ON_FORK; + break; case 'i': #ifdef SCHED_IDLE policy = SCHED_IDLE; @@ -243,6 +249,14 @@ int main(int argc, char *argv[]) if (errno) err(EXIT_FAILURE, _("failed to parse priority")); + /* sanity check */ + if ((policy_flag & SCHED_RESET_ON_FORK) && + !(policy == SCHED_FIFO || policy == SCHED_RR)) + errx(EXIT_FAILURE, _("SCHED_RESET_ON_FORK flag is suppoted for " + "SCHED_FIFO and SCHED_RR policies only")); + + policy |= policy_flag; + if (pid == -1) pid = 0; sp.sched_priority = priority; -- cgit v1.2.3