From a5fd3d685e6c2d0a7d80e7607ac6ff7bf7d05f67 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 25 Oct 2010 14:03:16 +0200 Subject: swapon: add support for "nofail" fstab mount option This option is already supported by mount(8) and fsck(8), there is no reason to have any exception for swap devices. Note that the --ifexists command line option applies to all swap devices, the "nofail" setting is per device. Signed-off-by: Karel Zak --- mount/swapon.8 | 6 ++++++ mount/swapon.c | 8 +++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/mount/swapon.8 b/mount/swapon.8 index a3ebc97c..595198d5 100644 --- a/mount/swapon.8 +++ b/mount/swapon.8 @@ -113,6 +113,12 @@ Devices that are already being used as swap are silently skipped. .TP .B "\-e, \-\-ifexists" Silently skip devices that do not exist. +The +.I /etc/fstab +mount option +.BI nofail +may be also used to skip non-existing device. + .TP .B "\-f, \-\-fixpgsz" Reinitialize (exec /sbin/mkswap) the swap space if its page size does not diff --git a/mount/swapon.c b/mount/swapon.c index d5114925..45cd2669 100644 --- a/mount/swapon.c +++ b/mount/swapon.c @@ -573,7 +573,7 @@ swapon_all(void) { while ((fstab = getmntent(fp)) != NULL) { const char *special; - int skip = 0; + int skip = 0, nofail = ifexists; int pri = priority; char *opt, *opts; @@ -588,6 +588,8 @@ swapon_all(void) { pri = atoi(opt+4); if (strcmp(opt, "noauto") == 0) skip = 1; + if (strcmp(opt, "nofail") == 0) + nofail = 1; } free(opts); @@ -596,13 +598,13 @@ swapon_all(void) { special = fsprobe_get_devname_by_spec(fstab->mnt_fsname); if (!special) { - if (!ifexists) + if (!nofail) status |= cannot_find(fstab->mnt_fsname); continue; } if (!is_in_proc_swaps(special) && - (!ifexists || !access(special, R_OK))) + (!nofail || !access(special, R_OK))) status |= do_swapon(special, pri, CANONIC); free((void *) special); -- cgit v1.2.3 From e4d5b4b3b44bcfe01291c0b0d32e8ba2f68efc4e Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 25 Oct 2010 23:23:48 +0200 Subject: libmount: optimize blkid_devno_to_devname() The brutal force /dev directory scanning should be used as a fallback solution only. Currently, almost all systems use udev and we can read the name from /sys/block/: symlink. Signed-off-by: Karel Zak --- shlibs/blkid/src/devno.c | 88 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 65 insertions(+), 23 deletions(-) diff --git a/shlibs/blkid/src/devno.c b/shlibs/blkid/src/devno.c index 1d389ac6..33466048 100644 --- a/shlibs/blkid/src/devno.c +++ b/shlibs/blkid/src/devno.c @@ -225,17 +225,18 @@ static const char *devdirs[] = { "/devices", "/devfs", "/dev", NULL }; * @short_description: mix of various utils for low-level and high-level API */ -/** - * blkid_devno_to_devname: - * @devno: device number - * - * This function finds the pathname to a block device with a given - * device number. - * - * Returns: a pointer to allocated memory to the pathname on success, - * and NULL on failure. - */ -char *blkid_devno_to_devname(dev_t devno) +/* returns basename and keeps dirname in the @path */ +static char *stripoff_last_component(char *path) +{ + char *p = strrchr(path, '/'); + + if (!p) + return NULL; + *p = '\0'; + return ++p; +} + +static char *scandev_devno_to_devname(dev_t devno) { struct dir_list *list = NULL, *new_list = NULL; char *devname = NULL; @@ -270,6 +271,59 @@ char *blkid_devno_to_devname(dev_t devno) free_dirlist(&list); free_dirlist(&new_list); + return devname; +} + +static char *sysfs_devno_to_devname(dev_t dev) +{ + char path[PATH_MAX]; + char linkpath[PATH_MAX]; + struct stat st; + char *name; + int rc; + + rc = snprintf(path, sizeof(path), "/sys/dev/block/%d:%d", + major(dev), minor(dev)); + if (rc < 0 || rc + 1 > sizeof(path)) + return NULL; + + rc = readlink(path, linkpath, sizeof(linkpath) - 1); + if (rc < 0) + return NULL; + linkpath[rc] = '\0'; + + name = stripoff_last_component(linkpath); /* basename */ + if (!name) + return NULL; + + rc = snprintf(path, sizeof(path), "/dev/%s", name); + if (rc < 0 || rc + 1 > sizeof(path)) + return NULL; + + if (!stat(path, &st) && S_ISBLK(st.st_mode) && st.st_rdev == dev) + return strdup(path); + + return NULL; +} + +/** + * blkid_devno_to_devname: + * @devno: device number + * + * This function finds the pathname to a block device with a given + * device number. + * + * Returns: a pointer to allocated memory to the pathname on success, + * and NULL on failure. + */ +char *blkid_devno_to_devname(dev_t devno) +{ + char *devname = NULL; + + devname = sysfs_devno_to_devname(devno); + if (!devname) + devname = scandev_devno_to_devname(devno); + if (!devname) { DBG(DEBUG_DEVNO, printf("blkid: couldn't find devno 0x%04lx\n", @@ -279,22 +333,10 @@ char *blkid_devno_to_devname(dev_t devno) printf("found devno 0x%04llx as %s\n", (long long)devno, devname)); } - return devname; } -/* returns basename and keeps dirname in the @path */ -static char *stripoff_last_component(char *path) -{ - char *p = strrchr(path, '/'); - - if (!p) - return NULL; - *p = '\0'; - return ++p; -} - /** * blkid_devno_to_wholedisk: * @dev: device number -- cgit v1.2.3 From dd0bd943f94392d165c5903e271c966afb0d7b75 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 26 Oct 2010 12:58:32 +0200 Subject: fsck: add support for whole-disk locking (-l option) This feature allows to call multiple independent fsck instances rather than use only one "fsck -A" process. The lock uses LOCK_EX flock(2). The lock request is ignored if the whole-disk is non-rotating disk. The verbose mode (-V) provides information about disk locking. Note that "fsck -l" does not care if the device is stacked, for example if you want to call "fsck -l /dev/md0" and "fsck -l /dev/md1" then the underlying devices will not be locked. The traditional "fsck -A" does not run in parallel for stacked devices. Requested-by: Lennart Poettering Signed-off-by: Karel Zak --- fsck/fsck.8 | 13 ++++++- fsck/fsck.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----- fsck/fsck.h | 1 + 3 files changed, 123 insertions(+), 10 deletions(-) diff --git a/fsck/fsck.8 b/fsck/fsck.8 index 9cf80785..3d60ac08 100644 --- a/fsck/fsck.8 +++ b/fsck/fsck.8 @@ -7,7 +7,7 @@ fsck \- check and repair a Linux file system .SH SYNOPSIS .B fsck -.RB [ \-sAVRTMNP ] +.RB [ \-lsAVRTMNP ] .RB [ \-C .RI [ fd ]] .RB [ \-t @@ -80,6 +80,17 @@ variable. Please see the file system-specific checker manual pages for further details. .SH OPTIONS .TP +.B \-l +Lock whole-disk device by exclusive +.BR flock (2). +This option can be used with one device only (e.g. -A and -l are mutually +exclusive). This option is recommended when more +.B fsck (8) +instances are executed in the same time. The option is ignored when used for +multiple devices or for non-rotating disk. The fsck does not lock underlying +devices if executed to check stacked devices (e.g. MD or DM) -- this feature is +not implemented yet. +.TP .B \-s Serialize .B fsck diff --git a/fsck/fsck.c b/fsck/fsck.c index 7e1608f9..6a58d7bf 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include #include @@ -87,6 +89,7 @@ char *devices[MAX_DEVICES]; char *args[MAX_ARGS]; int num_devices, num_args; +int lockdisk = 0; int verbose = 0; int doall = 0; int noexecute = 0; @@ -216,8 +219,96 @@ static void parse_escape(char *word) *q = 0; } +static dev_t get_disk(const char *device) +{ + struct stat st; + dev_t disk; + + if (!stat(device, &st) && + !blkid_devno_to_wholedisk(st.st_rdev, NULL, 0, &disk)) + return disk; + + return 0; +} + +static int is_irrotational_disk(dev_t disk) +{ + char path[PATH_MAX]; + FILE *f; + int rc, x; + + rc = snprintf(path, sizeof(path), + "/sys/dev/block/%d:%d/queue/rotational", + major(disk), minor(disk)); + + if (rc < 0 || rc + 1 > sizeof(path)) + return 0; + + f = fopen(path, "r"); + if (!f) + return 0; + + rc = fscanf(f, "%u", &x); + fclose(f); + + return rc == 1 ? !x : 0; +} + +static void lock_disk(struct fsck_instance *inst) +{ + dev_t disk = inst->fs->disk ? : get_disk(inst->fs->device); + char *diskname; + + if (!disk || is_irrotational_disk(disk)) + return; + + diskname = blkid_devno_to_devname(disk); + if (!diskname) + return; + + if (verbose) + printf(_("Locking disk %s ... "), diskname); + + inst->lock = open(diskname, O_CLOEXEC | O_RDONLY); + if (inst->lock >= 0) { + int rc = -1; + + /* inform users that we're waiting on the lock */ + if (verbose && + (rc = flock(inst->lock, LOCK_EX | LOCK_NB)) != 0 && + errno == EWOULDBLOCK) + printf(_("(waiting) ")); + + if (rc != 0 && flock(inst->lock, LOCK_EX) != 0) { + close(inst->lock); /* failed */ + inst->lock = -1; + } + } + + if (verbose) + printf("%s.\n", inst->lock >= 0 ? _("success") : _("failed")); + + free(diskname); + return; +} + +static void unlock_disk(struct fsck_instance *inst) +{ + if (inst->lock >= 0) { + /* explicitly unlock, don't rely on close(), maybe some library + * (e.g. liblkid) has still open the device. + */ + flock(inst->lock, LOCK_UN); + close(inst->lock); + } +} + + + static void free_instance(struct fsck_instance *i) { + if (lockdisk) + unlock_disk(i); free(i->prog); free(i); return; @@ -471,6 +562,13 @@ static int execute(const char *type, struct fs_info *fs, int interactive) printf("\n"); } + + inst->fs = fs; + inst->lock = -1; + + if (lockdisk) + lock_disk(inst); + /* Fork and execute the correct program. */ if (noexecute) pid = -1; @@ -494,7 +592,6 @@ static int execute(const char *type, struct fs_info *fs, int interactive) inst->prog = string_copy(prog); inst->type = string_copy(type); inst->start_time = time(0); - inst->fs = fs; inst->next = NULL; /* @@ -977,14 +1074,9 @@ static int disk_already_active(struct fs_info *fs) return 1; if (!fs->disk) { - struct stat st; - dev_t disk; - - if (!stat(fs->device, &st) && - !blkid_devno_to_wholedisk(st.st_rdev, NULL, 0, &disk)) { - fs->disk = disk; - fs->stacked = count_slaves(disk); - } + fs->disk = get_disk(fs->device); + if (fs->disk) + fs->stacked = count_slaves(fs->disk); } /* @@ -1230,6 +1322,9 @@ static void PRS(int argc, char *argv[]) } } break; + case 'l': + lockdisk++; + break; case 'V': verbose++; break; @@ -1340,6 +1435,12 @@ int main(int argc, char *argv[]) if ((num_devices == 1) || (serialize)) interactive = 1; + if (lockdisk && (doall || num_devices > 1)) { + fprintf(stderr, _("%s: the -l option can be used with one " + "device only -- ignore\n"), progname); + lockdisk = 0; + } + /* If -A was specified ("check all"), do that! */ if (doall) return check_all(); diff --git a/fsck/fsck.h b/fsck/fsck.h index d212622f..5612b218 100644 --- a/fsck/fsck.h +++ b/fsck/fsck.h @@ -58,6 +58,7 @@ struct fs_info { struct fsck_instance { int pid; int flags; + int lock; /* flock()ed whole disk file descriptor or -1 */ int exit_status; time_t start_time; char * prog; -- cgit v1.2.3 From e98f4af950a64db188e0a9f3eed20fefaa463a99 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Fri, 22 Oct 2010 21:24:50 +0200 Subject: agetty: fix -s option (baud rate setup) The problem is pretty visible in strace output: broken version: ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B115200 opost isig icanon echo ...}) = 0 [...] ioctl(0, SNDCTL_TMR_START or TCSETS, {B0 -opost -isig -icanon -echo ...}) = 0 ^^^ fixed version: ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B115200 opost isig icanon echo ...}) = 0 [...] ioctl(0, SNDCTL_TMR_START or TCSETS, {B115200 -opost -isig -icanon -echo ...}) = 0 Reported-by: Jon Masters Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=645640 Signed-off-by: Karel Zak --- login-utils/agetty.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/login-utils/agetty.c b/login-utils/agetty.c index a6e24998..9d463ce4 100644 --- a/login-utils/agetty.c +++ b/login-utils/agetty.c @@ -703,6 +703,13 @@ termio_init(tp, op) struct termios *tp; struct options *op; { + speed_t ispeed, ospeed; + + if (op->flags & F_KEEPSPEED) { + ispeed = cfgetispeed(tp); /* save the original setting */ + ospeed = cfgetospeed(tp); + } else + ospeed = ispeed = op->speeds[FIRST_SPEED]; /* * Initial termios settings: 8-bit characters, raw-mode, blocking i/o. @@ -713,18 +720,21 @@ termio_init(tp, op) /* flush input and output queues, important for modems! */ (void) tcflush(0, TCIOFLUSH); + tp->c_iflag = tp->c_lflag = tp->c_oflag = 0; + if (!(op->flags & F_KEEPCFLAGS)) tp->c_cflag = CS8 | HUPCL | CREAD | (tp->c_cflag & CLOCAL); - if (!(op->flags & F_KEEPSPEED)) { - cfsetispeed(tp, op->speeds[FIRST_SPEED]); - cfsetospeed(tp, op->speeds[FIRST_SPEED]); - } + /* Note that the speed is stored in the c_cflag termios field, so we have + * set the speed always when the cflag se reseted. + */ + cfsetispeed(tp, ispeed); + cfsetospeed(tp, ospeed); + if (op->flags & F_LOCAL) { tp->c_cflag |= CLOCAL; } - tp->c_iflag = tp->c_lflag = tp->c_oflag = 0; #ifdef HAVE_STRUCT_TERMIOS_C_LINE tp->c_line = 0; #endif @@ -984,9 +994,18 @@ next_speed(tp, op) struct termios *tp; struct options *op; { - static int baud_index = FIRST_SPEED;/* current speed index */ + static int baud_index = -1; + + if (baud_index == -1) + /* + * if the F_KEEPSPEED flags is set then the FIRST_SPEED is not + * tested yet (see termio_init()). + */ + baud_index = (op->flags & F_KEEPSPEED) ? FIRST_SPEED : + 1 % op->numspeed; + else + baud_index = (baud_index + 1) % op->numspeed; - baud_index = (baud_index + 1) % op->numspeed; cfsetispeed(tp, op->speeds[baud_index]); cfsetospeed(tp, op->speeds[baud_index]); (void) tcsetattr(0, TCSANOW, tp); -- cgit v1.2.3 From 50644ff4de8126eb132fa94ae4645fb19871f5b6 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Fri, 29 Oct 2010 00:55:07 +0200 Subject: use _exit() instead of exit() in sighandlers Signed-off-by: Marek Polacek --- login-utils/last.c | 2 +- login-utils/shutdown.c | 2 +- misc-utils/write.c | 2 +- text-utils/rev.c | 2 +- text-utils/ul.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/login-utils/last.c b/login-utils/last.c index 0c4c0a16..564e05ca 100644 --- a/login-utils/last.c +++ b/login-utils/last.c @@ -473,6 +473,6 @@ onintr(int signo) { ct = utmp_ctime(&utmpbuf); printf(_("\ninterrupted %10.10s %5.5s \n"), ct, ct + 11); if (signo == SIGINT) - exit(1); + _exit(1); (void)fflush(stdout); /* fix required for rsh */ } diff --git a/login-utils/shutdown.c b/login-utils/shutdown.c index f7bc0005..0078df2d 100644 --- a/login-utils/shutdown.c +++ b/login-utils/shutdown.c @@ -132,7 +132,7 @@ int_handler(int sig) unlink(_PATH_NOLOGIN); signal(SIGINT, SIG_DFL); my_puts(_("Shutdown process aborted")); - exit(1); + _exit(1); } static int diff --git a/misc-utils/write.c b/misc-utils/write.c index 8ed77634..c4f4ecc4 100644 --- a/misc-utils/write.c +++ b/misc-utils/write.c @@ -331,7 +331,7 @@ void do_write(char *tty, char *mytty, uid_t myuid) { static void done(int dummy) { (void)printf("EOF\r\n"); - exit(0); + _exit(0); } /* diff --git a/text-utils/rev.c b/text-utils/rev.c index 907b032b..7a42d7e4 100644 --- a/text-utils/rev.c +++ b/text-utils/rev.c @@ -66,7 +66,7 @@ wchar_t *buf; static void sig_handler(int signo) { free(buf); - exit(EXIT_SUCCESS); + _exit(EXIT_SUCCESS); } static void __attribute__((__noreturn__)) usage(FILE *out) diff --git a/text-utils/ul.c b/text-utils/ul.c index 4601e3c7..dbcc3214 100644 --- a/text-utils/ul.c +++ b/text-utils/ul.c @@ -604,7 +604,7 @@ needcol(int col) { static void sig_handler(int signo) { - exit(EXIT_SUCCESS); + _exit(EXIT_SUCCESS); } static void exitbuf(void) -- cgit v1.2.3 From 98da1298ca82b232bdff0abec81ca325f00031d9 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Fri, 29 Oct 2010 01:04:30 +0200 Subject: chrt: Add noreturn attribute to show_usage() function Signed-off-by: Marek Polacek --- schedutils/chrt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schedutils/chrt.c b/schedutils/chrt.c index 89b12c70..811eb200 100644 --- a/schedutils/chrt.c +++ b/schedutils/chrt.c @@ -54,7 +54,7 @@ #endif -static void show_usage(int rc) +static void __attribute__((__noreturn__)) show_usage(int rc) { FILE *out = rc == EXIT_SUCCESS ? stdout : stderr; -- cgit v1.2.3 From 5d757a9fdeab9bc3be5c9181abe28b3afe0bd199 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Fri, 29 Oct 2010 13:29:28 +0200 Subject: remove free() from atexit() callbacks Signed-off-by: Karel Zak --- disk-utils/mkswap.c | 6 ------ text-utils/ul.c | 7 ------- 2 files changed, 13 deletions(-) diff --git a/disk-utils/mkswap.c b/disk-utils/mkswap.c index 93378076..246b8dd7 100644 --- a/disk-utils/mkswap.c +++ b/disk-utils/mkswap.c @@ -174,11 +174,6 @@ init_signature_page(void) { } } -static void -deinit_signature_page(void) { - free(signature_page); -} - static void write_signature(char *sig) { char *sp = (char *) signature_page; @@ -538,7 +533,6 @@ main(int argc, char ** argv) { #endif init_signature_page(); /* get pagesize */ - atexit(deinit_signature_page); if (!device_name) { fprintf(stderr, diff --git a/text-utils/ul.c b/text-utils/ul.c index dbcc3214..ab0a6e77 100644 --- a/text-utils/ul.c +++ b/text-utils/ul.c @@ -78,7 +78,6 @@ void outc(wint_t c, int width); void setmode(int newmode); static void setcol(int newcol); static void needcol(int col); -static void exitbuf(void); static void sig_handler(int signo); #define IESC '\033' @@ -169,7 +168,6 @@ int main(int argc, char **argv) if ( (tigetflag("os") && ENTER_BOLD==NULL ) || (tigetflag("ul") && ENTER_UNDERLINE==NULL && UNDER_CHAR==NULL)) must_overstrike = 1; - atexit(exitbuf); initbuf(); if (optind == argc) filter(stdin); @@ -607,8 +605,3 @@ static void sig_handler(int signo) _exit(EXIT_SUCCESS); } -static void exitbuf(void) -{ - free(obuf); - obuf = NULL; -} -- cgit v1.2.3 From 29e6ed5e8f8222b4d54dc63ab3b1014de3e9acc4 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Fri, 29 Oct 2010 17:51:35 +0200 Subject: docs: add note about agetty to TODO Signed-off-by: Karel Zak --- TODO | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/TODO b/TODO index 6388f499..e827ac30 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,6 @@ libblkid -------- - - remove strerrr() from debug messages (use %m) to make BLKID_DEBUG= output thread-safe @@ -20,6 +19,12 @@ blkid(8) - add a new option (-r) that allows to print removable block devices that are missing in /proc/partitions, see blkid_probe_all_removable(). +agetty: +------ + + - review code and make it more simple for normal console (see mingetty) + - merge functionality from unmaintained mingetty package to agetty + wipefs ------ -- cgit v1.2.3 From a21640baec08b7b20e7d829c3aae87e35d5dbf04 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Fri, 29 Oct 2010 20:04:00 +0200 Subject: mount: use utimensat(AT_FDCWD) rather than open()+futimens() Thanks to Kay Sievers. Signed-off-by: Karel Zak --- mount/mount.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/mount/mount.c b/mount/mount.c index 0567418d..1c8a55fd 100644 --- a/mount/mount.c +++ b/mount/mount.c @@ -1313,8 +1313,6 @@ cdrom_setspeed(const char *spec) { static int is_readonly(const char *path) { - int fd; - if (access(path, W_OK) == 0) return 0; if (errno == EROFS) @@ -1332,19 +1330,14 @@ is_readonly(const char *path) * * - for read-write filesystem with read-only VFS node (aka -o remount,ro,bind) */ - fd = open(path, O_RDONLY); - if (fd >= 0) { + { struct timespec times[2]; - int errsv = 0; times[0].tv_nsec = UTIME_NOW; /* atime */ times[1].tv_nsec = UTIME_OMIT; /* mtime */ - if (futimens(fd, times) == -1) - errsv = errno; - close(fd); - - return errsv == EROFS; + if (utimensat(AT_FDCWD, path, times, 0) == -1) + return errno == EROFS; } #endif return 0; -- cgit v1.2.3 From f3a342a429b0576efeaf875bfb102f5b55f7c9b4 Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Fri, 22 Oct 2010 12:22:09 -0300 Subject: pg: use xalloc for memory allocation Signed-off-by: Davidlohr Bueso --- text-utils/pg.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/text-utils/pg.c b/text-utils/pg.c index 24c12217..68275238 100644 --- a/text-utils/pg.c +++ b/text-utils/pg.c @@ -60,6 +60,7 @@ #include #include "nls.h" +#include "xalloc.h" #include "widechar.h" #define READBUF LINE_MAX /* size of input buffer */ @@ -212,21 +213,6 @@ quit(int status) exit(status < 0100 ? status : 077); } -/* - * Memory allocator including check. - */ -static char * -smalloc(size_t s) -{ - char *m = (char *)malloc(s); - if (m == NULL) { - const char *p = _("Out of memory\n"); - write(2, p, strlen(p)); - quit(++exitstatus); - } - return m; -} - /* * Usage message and similar routines. */ @@ -549,7 +535,7 @@ endline(unsigned col, char *s) static void cline(void) { - char *buf = (char *)smalloc(ttycols + 2); + char *buf = xmalloc(ttycols + 2); memset(buf, ' ', ttycols + 2); buf[0] = '\r'; buf[ttycols + 1] = '\r'; @@ -601,7 +587,7 @@ getcount(char *cmdstr) if (*cmdstr == '\0') return 1; - buf = (char *)smalloc(strlen(cmdstr) + 1); + buf = xmalloc(strlen(cmdstr) + 1); strcpy(buf, cmdstr); if (cmd.key != '\0') { if (cmd.key == '/' || cmd.key == '?' || cmd.key == '^') { -- cgit v1.2.3 From 0d4e5f8e0d64b358ec2e309d9780e7854a0505ad Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Fri, 22 Oct 2010 12:22:56 -0300 Subject: more: use xalloc for memory allocation Signed-off-by: Davidlohr Bueso --- text-utils/more.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/text-utils/more.c b/text-utils/more.c index 20efc28d..37520598 100644 --- a/text-utils/more.c +++ b/text-utils/more.c @@ -36,6 +36,8 @@ libcurses (and hence can be in /bin with libcurses being in /usr/lib which may not be mounted). However, when termcap is not present curses can still be used. + 2010-10-21 Davidlohr Bueso + - modified mem allocation handling for util-linux-ng */ #include @@ -55,7 +57,9 @@ #include #include #include "xstrncpy.h" + #include "nls.h" +#include "xalloc.h" #include "widechar.h" #define _REGEX_RE_COMP @@ -2015,22 +2019,14 @@ int expand (char **outbuf, char *inbuf) { xtra = strlen (fnames[fnum]) + strlen (shell_line) + 1; tempsz = 200 + xtra; - temp = malloc(tempsz); - if (!temp) { - error (_("Out of memory")); - return -1; - } + temp = xmalloc(tempsz); inpstr = inbuf; outstr = temp; while ((c = *inpstr++) != '\0'){ offset = outstr-temp; if (tempsz-offset-1 < xtra) { tempsz += 200 + xtra; - temp = realloc(temp, tempsz); - if (!temp) { - error (_("Out of memory")); - return -1; - } + temp = xrealloc(temp, tempsz); outstr = temp + offset; } switch (c) { -- cgit v1.2.3 From b7159bd5c901b7f785b0b3370b70a0ec5e4ffcf6 Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Fri, 22 Oct 2010 12:23:31 -0300 Subject: tailf: use xalloc for memory allocation Signed-off-by: Davidlohr Bueso --- text-utils/tailf.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/text-utils/tailf.c b/text-utils/tailf.c index dc18b2a6..2dcdba3f 100644 --- a/text-utils/tailf.c +++ b/text-utils/tailf.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -40,7 +39,9 @@ #ifdef HAVE_INOTIFY_INIT #include #endif + #include "nls.h" +#include "xalloc.h" #include "usleep.h" #define DEFAULT_LINES 10 @@ -57,7 +58,7 @@ tailf(const char *filename, int lines) if (!(str = fopen(filename, "r"))) err(EXIT_FAILURE, _("cannot open \"%s\" for read"), filename); - buf = malloc(lines * BUFSIZ); + buf = xmalloc(lines * BUFSIZ); p = buf; while (fgets(p, BUFSIZ, str)) { if (++tail >= lines) { -- cgit v1.2.3 From 04faca4a1325fe21b90b761e5d3ef37c4a267ecc Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Fri, 22 Oct 2010 12:24:37 -0300 Subject: col: use xalloc for memory allocation Differentiate between malloc and realloc (not done so far) and get rid of local warn() Signed-off-by: Davidlohr Bueso --- text-utils/col.c | 38 +++++++++++--------------------------- 1 file changed, 11 insertions(+), 27 deletions(-) diff --git a/text-utils/col.c b/text-utils/col.c index 3b81a891..580a84c7 100644 --- a/text-utils/col.c +++ b/text-utils/col.c @@ -50,8 +50,9 @@ #include #include #include -#include "nls.h" +#include "nls.h" +#include "xalloc.h" #include "widechar.h" #define BS '\b' /* backspace */ @@ -94,12 +95,10 @@ struct line_str { void usage(void); void wrerr(void); -void warn(int); void free_line(LINE *l); void flush_line(LINE *l); void flush_lines(int); void flush_blanks(void); -void *xmalloc(void *p, size_t size); LINE *alloc_line(void); CSET last_set; /* char_set of last char printed */ @@ -275,7 +274,9 @@ int main(int argc, char **argv) } } else { if (!warned++) - warn(cur_line); + fprintf(stderr, + _("col: warning: can't back up %s.\n"), cur_line < 0 ? + _("past first line") : _("-- line already flushed")); cur_line -= nmove; } } @@ -302,8 +303,8 @@ int main(int argc, char **argv) int need; need = l->l_lsize ? l->l_lsize * 2 : 90; - l->l_line = (CHAR *)xmalloc((void *) l->l_line, - (unsigned) need * sizeof(CHAR)); + l->l_line = (CHAR *)xrealloc((void *) l->l_line, + (unsigned) need * sizeof(CHAR)); l->l_lsize = need; } c = &l->l_line[l->l_line_len++]; @@ -415,12 +416,12 @@ void flush_line(LINE *l) */ if (l->l_lsize > sorted_size) { sorted_size = l->l_lsize; - sorted = (CHAR *)xmalloc((void *)sorted, - (unsigned)sizeof(CHAR) * sorted_size); + sorted = (CHAR *)xrealloc((void *)sorted, + (unsigned)sizeof(CHAR) * sorted_size); } if (l->l_max_col >= count_size) { count_size = l->l_max_col + 1; - count = (int *)xmalloc((void *)count, + count = (int *)xrealloc((void *)count, (unsigned)sizeof(int) * count_size); } memset(count, 0, sizeof(int) * l->l_max_col + 1); @@ -510,7 +511,7 @@ alloc_line() int i; if (!line_freelist) { - l = (LINE *)xmalloc((void *)NULL, sizeof(LINE) * NALLOC); + l = xmalloc(sizeof(LINE) * NALLOC); line_freelist = l; for (i = 1; i < NALLOC; i++, l++) l->l_next = l + 1; @@ -529,16 +530,6 @@ void free_line(LINE *l) line_freelist = l; } -void * -xmalloc(void *p, size_t size) -{ - if (!(p = (void *)realloc(p, size))) { - (void)fprintf(stderr, "col: %s.\n", strerror(ENOMEM)); - exit(1); - } - return(p); -} - void usage() { (void)fprintf(stderr, _("usage: col [-bfpx] [-l nline]\n")); @@ -550,10 +541,3 @@ void wrerr() (void)fprintf(stderr, _("col: write error.\n")); exit(1); } - -void warn(int line) -{ - (void)fprintf(stderr, - _("col: warning: can't back up %s.\n"), line < 0 ? - _("past first line") : _("-- line already flushed")); -} -- cgit v1.2.3 From 2ebef8704da887e47be1270e832f9dc7e74bdf28 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 1 Nov 2010 14:51:08 +0100 Subject: col: use err.h and EXIT_* macros Signed-off-by: Karel Zak --- text-utils/col.c | 50 +++++++++++++++++++++++--------------------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/text-utils/col.c b/text-utils/col.c index 580a84c7..9349720c 100644 --- a/text-utils/col.c +++ b/text-utils/col.c @@ -93,8 +93,6 @@ struct line_str { int l_max_col; /* max column in the line */ }; -void usage(void); -void wrerr(void); void free_line(LINE *l); void flush_line(LINE *l); void flush_lines(int); @@ -114,6 +112,17 @@ int pass_unknown_seqs; /* whether to pass unknown control sequences */ if (putwchar(ch) == WEOF) \ wrerr(); +static void __attribute__((__noreturn__)) usage() +{ + errx(EXIT_FAILURE, _("usage: %s [-bfpx] [-l nline]"), + program_invocation_short_name); +} + +static void __attribute__((__noreturn__)) wrerr() +{ + errx(EXIT_FAILURE, _("write error.")); +} + int main(int argc, char **argv) { register wint_t ch; @@ -127,12 +136,12 @@ int main(int argc, char **argv) int this_line; /* line l points to */ int nflushd_lines; /* number of lines that were flushed */ int adjust, opt, warned; - int ret = 0; + int ret = EXIT_SUCCESS; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); - + max_bufd_lines = 128; compress_spaces = 1; /* compress spaces into tabs */ pass_unknown_seqs = 0; /* remove unknown escape sequences */ @@ -148,11 +157,8 @@ int main(int argc, char **argv) compress_spaces = 1; break; case 'l': /* buffered line count */ - if ((max_bufd_lines = atoi(optarg)) <= 0) { - (void)fprintf(stderr, - _("col: bad -l argument %s.\n"), optarg); - exit(1); - } + if ((max_bufd_lines = atoi(optarg)) <= 0) + errx(EXIT_FAILURE, _("bad -l argument %s."), optarg); break; case 'p': pass_unknown_seqs = 1; @@ -175,16 +181,16 @@ int main(int argc, char **argv) cur_line = max_line = nflushd_lines = this_line = 0; cur_set = last_set = CS_NORMAL; lines = l = alloc_line(); - + while (feof(stdin)==0) { errno = 0; if ((ch = getwchar()) == WEOF) { if (errno==EILSEQ) { - perror("col"); - ret = 1; + warn(NULL); + ret = EXIT_FAILURE; } break; - } + } if (!iswgraph(ch)) { switch (ch) { case BS: /* can't go back further */ @@ -274,9 +280,9 @@ int main(int argc, char **argv) } } else { if (!warned++) - fprintf(stderr, - _("col: warning: can't back up %s.\n"), cur_line < 0 ? - _("past first line") : _("-- line already flushed")); + warnx( + _("warning: can't back up %s."), cur_line < 0 ? + _("past first line") : _("-- line already flushed")); cur_line -= nmove; } } @@ -341,7 +347,7 @@ int main(int argc, char **argv) nblank_lines = 2; flush_blanks(); if (ferror(stdout) || fclose(stdout)) - return 1; + return EXIT_FAILURE; return ret; } @@ -530,14 +536,4 @@ void free_line(LINE *l) line_freelist = l; } -void usage() -{ - (void)fprintf(stderr, _("usage: col [-bfpx] [-l nline]\n")); - exit(1); -} -void wrerr() -{ - (void)fprintf(stderr, _("col: write error.\n")); - exit(1); -} -- cgit v1.2.3 From f0961db21f912511ed6ac7fee02e26b40efe0d8c Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Fri, 22 Oct 2010 12:25:46 -0300 Subject: ul: use xalloc for memory allocation Signed-off-by: Davidlohr Bueso --- text-utils/ul.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/text-utils/ul.c b/text-utils/ul.c index ab0a6e77..30f24e9d 100644 --- a/text-utils/ul.c +++ b/text-utils/ul.c @@ -49,8 +49,9 @@ #include /* for signal() */ #include #include -#include "nls.h" +#include "nls.h" +#include "xalloc.h" #include "widechar.h" #ifdef HAVE_WIDECHAR @@ -426,9 +427,7 @@ void initbuf(void) { if (obuf == NULL) { /* First time. */ obuflen = INITBUF; - obuf = malloc(sizeof(struct CHAR) * obuflen); - if (obuf == NULL) - err(EXIT_FAILURE, _("unable to allocate buffer")); + obuf = xmalloc(sizeof(struct CHAR) * obuflen); } /* assumes NORMAL == 0 */ @@ -594,9 +593,7 @@ needcol(int col) { : obuflen * 2; /* Now we can try to expand obuf. */ - obuf = realloc(obuf, sizeof(struct CHAR) * obuflen); - if (obuf == NULL) - err(EXIT_FAILURE, _("growing buffer failed")); + obuf = xrealloc(obuf, sizeof(struct CHAR) * obuflen); } } -- cgit v1.2.3 From 3924d0f169525270e20b6183ee67bca5822d0291 Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Fri, 22 Oct 2010 12:26:24 -0300 Subject: rev: use xalloc for memory allocation Signed-off-by: Davidlohr Bueso --- text-utils/rev.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/text-utils/rev.c b/text-utils/rev.c index 7a42d7e4..b6924497 100644 --- a/text-utils/rev.c +++ b/text-utils/rev.c @@ -59,6 +59,7 @@ #include #include "nls.h" +#include "xalloc.h" #include "widechar.h" wchar_t *buf; @@ -117,9 +118,7 @@ int main(int argc, char *argv[]) filename = *argv++; } - buf = malloc(bufsiz * sizeof(wchar_t)); - if (!buf) - err(EXIT_FAILURE, _("malloc failed")); + buf = xmalloc(bufsiz * sizeof(wchar_t)); while (fgetws(buf, bufsiz, fp)) { len = wcslen(buf); -- cgit v1.2.3 From c2301380b4d61921971f89661088d1dab7c70ccd Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Sun, 24 Oct 2010 17:32:47 -0700 Subject: swapon: add "discard" support In kernel 2.6.36 (and in stable kernel 2.6.35.5) I made a tiny change to the swapon(const char *path, int swapflags) system call interface: kernel commit 3399446632739fcd05fd8b272b476a69c6e6d14a swap: discard while swapping only if SWAP_FLAG_DISCARD As things stand at present, we could just remove the swap discard support; but since several filesystems (including ext4 and btrfs and fat) are offering a "discard" mount option, I thought swap should take the same course, and offer a "--discard" or "-d" option to swapon(8). [kzak@redhat.com: - update swapon.8 man page - use for -d the same logic as for -p] Signed-off-by: Hugh Dickins Signed-off-by: Karel Zak --- mount/swapon.8 | 11 +++++++++++ mount/swapon.c | 40 ++++++++++++++++++++++++++++------------ 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/mount/swapon.8 b/mount/swapon.8 index 595198d5..e35c6e5f 100644 --- a/mount/swapon.8 +++ b/mount/swapon.8 @@ -54,6 +54,7 @@ Enable/disable: .br .in +5 .B swapon +.RB [ \-d ] .RB [ \-f ] .RB [ \-p .IR priority ] @@ -110,6 +111,16 @@ All devices marked as ``swap'' in .I /etc/fstab are made available, except for those with the ``noauto'' option. Devices that are already being used as swap are silently skipped. +.TP +.B "\-d, \-\-discard" +Swapping will discard clusters of swap pages in between freeing them +and re-writing to them, if the swap device supports that. +The +.I /etc/fstab +mount option +.BI discard +may be also used to enable discard flag. + .TP .B "\-e, \-\-ifexists" Silently skip devices that do not exist. diff --git a/mount/swapon.c b/mount/swapon.c index 45cd2669..d8fad0bf 100644 --- a/mount/swapon.c +++ b/mount/swapon.c @@ -30,6 +30,10 @@ # include #endif +#ifndef SWAP_FLAG_DISCARD +# define SWAP_FLAG_DISCARD 0x10000 /* discard swap cluster after use */ +#endif + #ifndef SWAPON_HAS_TWO_ARGS /* libc is insane, let's call the kernel */ # include @@ -54,6 +58,7 @@ enum { int all; int priority = -1; /* non-prioritized swap by default */ +int discard; /* If true, don't complain if the device/file doesn't exist */ int ifexists; @@ -65,6 +70,7 @@ char *progname; static struct option longswaponopts[] = { /* swapon only */ { "priority", required_argument, 0, 'p' }, + { "discard", 0, 0, 'd' }, { "ifexists", 0, 0, 'e' }, { "summary", 0, 0, 's' }, { "fixpgsz", 0, 0, 'f' }, @@ -92,7 +98,7 @@ static void swapon_usage(FILE *fp, int n) { fprintf(fp, _("\nUsage:\n" " %1$s -a [-e] [-v] [-f] enable all swaps from /etc/fstab\n" - " %1$s [-p priority] [-v] [-f] enable given swap\n" + " %1$s [-p priority] [-d] [-v] [-f] enable given swap\n" " %1$s -s display swap usage summary\n" " %1$s -h display help\n" " %1$s -V display version\n\n"), progname); @@ -471,7 +477,7 @@ err: } static int -do_swapon(const char *orig_special, int prio, int canonic) { +do_swapon(const char *orig_special, int prio, int fl_discard, int canonic) { int status; const char *special = orig_special; int flags = 0; @@ -497,6 +503,9 @@ do_swapon(const char *orig_special, int prio, int canonic) { << SWAP_FLAG_PRIO_SHIFT); } #endif + if (fl_discard) + flags |= SWAP_FLAG_DISCARD; + status = swapon(special, flags); if (status < 0) warn(_("%s: swapon failed"), orig_special); @@ -511,15 +520,17 @@ cannot_find(const char *special) { } static int -swapon_by_label(const char *label, int prio) { +swapon_by_label(const char *label, int prio, int dsc) { const char *special = fsprobe_get_devname_by_label(label); - return special ? do_swapon(special, prio, CANONIC) : cannot_find(label); + return special ? do_swapon(special, prio, dsc, CANONIC) : + cannot_find(label); } static int -swapon_by_uuid(const char *uuid, int prio) { +swapon_by_uuid(const char *uuid, int prio, int dsc) { const char *special = fsprobe_get_devname_by_uuid(uuid); - return special ? do_swapon(special, prio, CANONIC) : cannot_find(uuid); + return special ? do_swapon(special, prio, dsc, CANONIC) : + cannot_find(uuid); } static int @@ -574,7 +585,7 @@ swapon_all(void) { while ((fstab = getmntent(fp)) != NULL) { const char *special; int skip = 0, nofail = ifexists; - int pri = priority; + int pri = priority, dsc = discard; char *opt, *opts; if (!streq(fstab->mnt_type, MNTTYPE_SWAP)) @@ -586,6 +597,8 @@ swapon_all(void) { opt = strtok(NULL, ",")) { if (strncmp(opt, "pri=", 4) == 0) pri = atoi(opt+4); + if (strcmp(opt, "discard") == 0) + dsc = 1; if (strcmp(opt, "noauto") == 0) skip = 1; if (strcmp(opt, "nofail") == 0) @@ -605,7 +618,7 @@ swapon_all(void) { if (!is_in_proc_swaps(special) && (!nofail || !access(special, R_OK))) - status |= do_swapon(special, pri, CANONIC); + status |= do_swapon(special, pri, dsc, CANONIC); free((void *) special); } @@ -638,7 +651,7 @@ main_swapon(int argc, char *argv[]) { int status = 0; int c, i; - while ((c = getopt_long(argc, argv, "ahefp:svVL:U:", + while ((c = getopt_long(argc, argv, "ahdefp:svVL:U:", longswaponopts, NULL)) != -1) { switch (c) { case 'a': /* all */ @@ -656,6 +669,9 @@ main_swapon(int argc, char *argv[]) { case 'U': addu(optarg); break; + case 'd': + discard = 1; + break; case 'e': /* ifexists */ ifexists = 1; break; @@ -690,13 +706,13 @@ main_swapon(int argc, char *argv[]) { status |= swapon_all(); for (i = 0; i < llct; i++) - status |= swapon_by_label(llist[i], priority); + status |= swapon_by_label(llist[i], priority, discard); for (i = 0; i < ulct; i++) - status |= swapon_by_uuid(ulist[i], priority); + status |= swapon_by_uuid(ulist[i], priority, discard); while (*argv != NULL) - status |= do_swapon(*argv++, priority, !CANONIC); + status |= do_swapon(*argv++, priority, discard, !CANONIC); return status; } -- cgit v1.2.3 From 01802c2e6df94aa14609d5628b276bad6bb09968 Mon Sep 17 00:00:00 2001 From: Jeroen Oortwijn Date: Sun, 31 Oct 2010 21:32:21 +0100 Subject: libblkid: add signature to FAT32 fsinfo block Add 0x41645252 to the list of valid signatures of the FAT32 fsinfo block. It isn't a valid signature, but there are devices that use this signature in their FAT32 filesystem. Addresses: https://bugs.launchpad.net/ubuntu/+source/util-linux/+bug/589369 Signed-off-by: Jeroen Oortwijn --- shlibs/blkid/src/superblocks/vfat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/shlibs/blkid/src/superblocks/vfat.c b/shlibs/blkid/src/superblocks/vfat.c index 9027d50d..078b1dda 100644 --- a/shlibs/blkid/src/superblocks/vfat.c +++ b/shlibs/blkid/src/superblocks/vfat.c @@ -380,6 +380,7 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag) fsinfo = (struct fat32_fsinfo *) buf; if (memcmp(fsinfo->signature1, "\x52\x52\x61\x41", 4) != 0 && + memcmp(fsinfo->signature1, "\x52\x52\x64\x41", 4) != 0 && memcmp(fsinfo->signature1, "\x00\x00\x00\x00", 4) != 0) return -1; if (memcmp(fsinfo->signature2, "\x72\x72\x41\x61", 4) != 0 && -- cgit v1.2.3 From 2ab428f6a8966d90ac97ce0ce0c7d73b82fade8f Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Wed, 27 Oct 2010 06:14:46 -0300 Subject: sys-utils: make use xalloc wrappers Signed-off-by: Davidlohr Bueso --- sys-utils/cytune.c | 9 +++------ sys-utils/readprofile.c | 23 +++-------------------- sys-utils/rtcwake.c | 7 ++----- sys-utils/tunelp.c | 34 +++++++++++++--------------------- 4 files changed, 21 insertions(+), 52 deletions(-) diff --git a/sys-utils/cytune.c b/sys-utils/cytune.c index 10a874d4..47b37290 100644 --- a/sys-utils/cytune.c +++ b/sys-utils/cytune.c @@ -63,6 +63,7 @@ #endif #endif +#include "xalloc.h" #include "nls.h" /* Until it gets put in the kernel, toggle by hand. */ @@ -315,12 +316,8 @@ int main(int argc, char *argv[]) { /* query stuff after this line */ - cmon = (struct cyclades_control *) malloc(sizeof (struct cyclades_control) - * numfiles); - if(!cmon) { - perror(_("malloc failed")); - exit(1); - } + cmon = xmalloc(sizeof(struct cyclades_control) * numfiles); + if(signal(SIGINT, summary)|| signal(SIGQUIT, summary)|| signal(SIGTERM, summary)) { diff --git a/sys-utils/readprofile.c b/sys-utils/readprofile.c index 52f5d8c9..91ff3295 100644 --- a/sys-utils/readprofile.c +++ b/sys-utils/readprofile.c @@ -49,6 +49,8 @@ #include #include #include + +#include "xalloc.h" #include "nls.h" #define S_LEN 128 @@ -60,22 +62,6 @@ static char defaultmap[]="/boot/System.map"; static char defaultpro[]="/proc/profile"; static char optstring[]="M:m:np:itvarVbs"; -static void * -xmalloc (size_t size) { - void *t; - - if (size == 0) - return NULL; - - t = malloc (size); - if (t == NULL) { - fprintf(stderr, _("out of memory")); - exit(1); - } - - return t; -} - static FILE * myopen(char *name, char *mode, int *flag) { int len = strlen(name); @@ -242,10 +228,7 @@ main(int argc, char **argv) { exit(1); } - if (!(buf=malloc(len))) { - fprintf(stderr,"%s: malloc(): %s\n", prgname, strerror(errno)); - exit(1); - } + buf = xmalloc(len); if (read(proFd,buf,len) != len) { fprintf(stderr,"%s: %s: %s\n",prgname,proFile,strerror(errno)); diff --git a/sys-utils/rtcwake.c b/sys-utils/rtcwake.c index 26511306..f7ecb162 100644 --- a/sys-utils/rtcwake.c +++ b/sys-utils/rtcwake.c @@ -36,6 +36,7 @@ #include #include "nls.h" +#include "xalloc.h" #include "pathnames.h" #include "usleep.h" @@ -423,11 +424,7 @@ int main(int argc, char **argv) if (strncmp(devname, "/dev/", strlen("/dev/")) != 0) { char *new_devname; - new_devname = malloc(strlen(devname) + strlen("/dev/") + 1); - if (!new_devname) { - perror(_("malloc() failed")); - exit(EXIT_FAILURE); - } + new_devname = xmalloc(strlen(devname) + strlen("/dev/") + 1); strcpy(new_devname, "/dev/"); strcat(new_devname, devname); diff --git a/sys-utils/tunelp.c b/sys-utils/tunelp.c index 00ad5b76..0f22fd8c 100644 --- a/sys-utils/tunelp.c +++ b/sys-utils/tunelp.c @@ -60,7 +60,9 @@ #include #include #include + #include "lp.h" +#include "xalloc.h" #include "nls.h" struct command { @@ -84,16 +86,6 @@ print_version(char *progname) { printf(_("%s (%s)\n"), progname, PACKAGE_STRING); } -static void * -mylloc(long size) { - void *ptr; - if(!(ptr = (void*)malloc(size))) { - perror(_("malloc error")); - exit(2); - } - return ptr; -} - static char *progname; static long @@ -131,7 +123,7 @@ main (int argc, char ** argv) { if (argc < 2) print_usage(progname); - cmdst = cmds = mylloc(sizeof(struct command)); + cmdst = cmds = xmalloc(sizeof(struct command)); cmds->next = 0; show_irq = 1; @@ -143,31 +135,31 @@ main (int argc, char ** argv) { case 'i': cmds->op = LPSETIRQ; cmds->val = get_val(optarg); - cmds->next = mylloc(sizeof(struct command)); + cmds->next = xmalloc(sizeof(struct command)); cmds = cmds->next; cmds->next = 0; break; case 't': cmds->op = LPTIME; cmds->val = get_val(optarg); - cmds->next = mylloc(sizeof(struct command)); + cmds->next = xmalloc(sizeof(struct command)); cmds = cmds->next; cmds->next = 0; break; case 'c': cmds->op = LPCHAR; cmds->val = get_val(optarg); - cmds->next = mylloc(sizeof(struct command)); + cmds->next = xmalloc(sizeof(struct command)); cmds = cmds->next; cmds->next = 0; break; case 'w': cmds->op = LPWAIT; cmds->val = get_val(optarg); - cmds->next = mylloc(sizeof(struct command)); + cmds->next = xmalloc(sizeof(struct command)); cmds = cmds->next; cmds->next = 0; break; case 'a': cmds->op = LPABORT; cmds->val = get_onoff(optarg); - cmds->next = mylloc(sizeof(struct command)); + cmds->next = xmalloc(sizeof(struct command)); cmds = cmds->next; cmds->next = 0; break; case 'q': @@ -180,20 +172,20 @@ main (int argc, char ** argv) { case 'o': cmds->op = LPABORTOPEN; cmds->val = get_onoff(optarg); - cmds->next = mylloc(sizeof(struct command)); + cmds->next = xmalloc(sizeof(struct command)); cmds = cmds->next; cmds->next = 0; break; case 'C': cmds->op = LPCAREFUL; cmds->val = get_onoff(optarg); - cmds->next = mylloc(sizeof(struct command)); + cmds->next = xmalloc(sizeof(struct command)); cmds = cmds->next; cmds->next = 0; break; case 's': show_irq = 0; cmds->op = LPGETSTATUS; cmds->val = 0; - cmds->next = mylloc(sizeof(struct command)); + cmds->next = xmalloc(sizeof(struct command)); cmds = cmds->next; cmds->next = 0; break; #endif @@ -201,7 +193,7 @@ main (int argc, char ** argv) { case 'r': cmds->op = LPRESET; cmds->val = 0; - cmds->next = mylloc(sizeof(struct command)); + cmds->next = xmalloc(sizeof(struct command)); cmds = cmds->next; cmds->next = 0; break; #endif @@ -210,7 +202,7 @@ main (int argc, char ** argv) { /* Note: this will do the wrong thing on 2.0.36 when compiled under 2.2.x */ cmds->op = LPTRUSTIRQ; cmds->val = get_onoff(optarg); - cmds->next = mylloc(sizeof(struct command)); + cmds->next = xmalloc(sizeof(struct command)); cmds = cmds->next; cmds->next = 0; break; #endif -- cgit v1.2.3 From 3f7fc4d43b61e442b81937aa06e079950a8ebb7c Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Thu, 4 Nov 2010 22:22:49 +0100 Subject: column: segfault on empty input Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=579955 Signed-off-by: Karel Zak --- text-utils/column.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/text-utils/column.c b/text-utils/column.c index 87a6fc79..5b52339f 100644 --- a/text-utils/column.c +++ b/text-utils/column.c @@ -308,8 +308,10 @@ maketbl() for (i = lens[coloff] - t->len[coloff] + 2; i > 0; i--) putwchar(' '); } - fputws(t->list[coloff], stdout); - putwchar('\n'); + if (coloff < t->cols) { + fputws(t->list[coloff], stdout); + putwchar('\n'); + } } } -- cgit v1.2.3 From 24d1e474a2d7db57968d406265460a97f6143854 Mon Sep 17 00:00:00 2001 From: Jeroen Oortwijn Date: Tue, 2 Nov 2010 22:13:12 +0100 Subject: libblkid: add magic to vfat Add the "FAT " magic to vfat. There are devices that use this magic in their FAT filesystem. Addresses: https://bugs.launchpad.net/ubuntu/+source/util-linux/+bug/491476 Signed-off-by: Jeroen Oortwijn --- shlibs/blkid/src/superblocks/vfat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/shlibs/blkid/src/superblocks/vfat.c b/shlibs/blkid/src/superblocks/vfat.c index 078b1dda..60191b99 100644 --- a/shlibs/blkid/src/superblocks/vfat.c +++ b/shlibs/blkid/src/superblocks/vfat.c @@ -415,6 +415,7 @@ const struct blkid_idinfo vfat_idinfo = { .magic = "MSDOS", .len = 5, .sboff = 0x36 }, { .magic = "FAT16 ", .len = 8, .sboff = 0x36 }, { .magic = "FAT12 ", .len = 8, .sboff = 0x36 }, + { .magic = "FAT ", .len = 8, .sboff = 0x36 }, { .magic = "\353", .len = 1, }, { .magic = "\351", .len = 1, }, { .magic = "\125\252", .len = 2, .sboff = 0x1fe }, -- cgit v1.2.3 From 688e75f3f062617cf7d129e331a1472decaa97cd Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 9 Nov 2010 12:40:56 +0100 Subject: docs: remove ipc.texi (info with IPC API docs) The IPC API documentation is maintained in the standard man-pages. It does not make sense to maintain this docs in util-linux-ng. Signed-off-by: Karel Zak --- sys-utils/Makefile.am | 2 - sys-utils/ipc.texi | 1313 ------------------------------------------------- 2 files changed, 1315 deletions(-) delete mode 100644 sys-utils/ipc.texi diff --git a/sys-utils/Makefile.am b/sys-utils/Makefile.am index 166d7188..d2b85685 100644 --- a/sys-utils/Makefile.am +++ b/sys-utils/Makefile.am @@ -28,8 +28,6 @@ endif cytune_SOURCES = cytune.c cyclades.h tunelp_SOURCES = tunelp.c lp.h -info_TEXINFOS = ipc.texi - if BUILD_FALLOCATE usrbin_exec_PROGRAMS += fallocate diff --git a/sys-utils/ipc.texi b/sys-utils/ipc.texi deleted file mode 100644 index 672d8b84..00000000 --- a/sys-utils/ipc.texi +++ /dev/null @@ -1,1313 +0,0 @@ -\input texinfo @c -*-texinfo-*- -@comment %**start of header (This is for running Texinfo on a region.) -@setfilename ipc.info -@settitle Inter Process Communication. -@setchapternewpage odd -@comment %**end of header (This is for running Texinfo on a region.) - -@ifinfo -This file documents the System V style inter process communication -primitives available under linux. - -Copyright @copyright{} 1992 krishna balasubramanian - -Permission is granted to use this material and the accompanying -programs within the terms of the GNU GPL. -@end ifinfo - -@titlepage -@sp 10 -@center @titlefont{System V Inter Process Communication} -@sp 2 -@center krishna balasubramanian, - -@comment The following two commands start the copyright page. -@page -@vskip 0pt plus 1filll -Copyright @copyright{} 1992 krishna balasubramanian - -Permission is granted to use this material and the accompanying -programs within the terms of the GNU GPL. -@end titlepage - -@dircategory Miscellaneous -@direntry -* ipc: (ipc). System V style inter process communication -@end direntry - -@node Top, Overview, Notes, (dir) -@chapter System V IPC. - -These facilities are provided to maintain compatibility with -programs developed on system V unix systems and others -that rely on these system V mechanisms to accomplish inter -process communication (IPC).@refill - -The specifics described here are applicable to the Linux implementation. -Other implementations may do things slightly differently. - -@menu -* Overview:: What is system V ipc? Overall mechanisms. -* Messages:: System calls for message passing. -* Semaphores:: System calls for semaphores. -* Shared Memory:: System calls for shared memory access. -* Notes:: Miscellaneous notes. -@end menu - -@node Overview, example, Top, Top -@section Overview - -@noindent System V IPC consists of three mechanisms: - -@itemize @bullet -@item -Messages : exchange messages with any process or server. -@item -Semaphores : allow unrelated processes to synchronize execution. -@item -Shared memory : allow unrelated processes to share memory. -@end itemize - -@menu -* example:: Using shared memory. -* perms:: Description of access permissions. -* syscalls:: Overview of ipc system calls. -@end menu - -Access to all resources is permitted on the basis of permissions -set up when the resource was created.@refill - -A resource here consists of message queue, a semaphore set (array) -or a shared memory segment.@refill - -A resource must first be allocated by a creator before it is used. -The creator can assign a different owner. After use the resource -must be explicitly destroyed by the creator or owner.@refill - -A resource is identified by a numeric @var{id}. Typically a creator -defines a @var{key} that may be used to access the resource. The user -process may then use this @var{key} in the @dfn{get} system call to obtain -the @var{id} for the corresponding resource. This @var{id} is then used for -all further access. A library call @dfn{ftok} is provided to translate -pathnames or strings to numeric keys.@refill - -There are system and implementation defined limits on the number and -sizes of resources of any given type. Some of these are imposed by the -implementation and others by the system administrator -when configuring the kernel (@xref{msglimits}, @xref{semlimits}, -@xref{shmlimits}).@refill - -There is an @code{msqid_ds}, @code{semid_ds} or @code{shmid_ds} struct -associated with each message queue, semaphore array or shared segment. -Each ipc resource has an associated @code{ipc_perm} struct which defines -the creator, owner, access perms ..etc.., for the resource. -These structures are detailed in the following sections.@refill - - - -@node example, perms, Overview, Overview -@section example - -Here is a code fragment with pointers on how to use shared memory. The -same methods are applicable to other resources.@refill - -In a typical access sequence the creator allocates a new instance -of the resource with the @code{get} system call using the IPC_CREAT -flag.@refill - -@noindent creator process:@* - -@example -#include -int id; -key_t key; -char proc_id = 'C'; -int size = 0x5000; /* 20 K */ -int flags = 0664 | IPC_CREAT; /* read-only for others */ - -key = ftok ("~creator/ipckey", proc_id); -id = shmget (key, size, flags); -exit (0); /* quit leaving resource allocated */ -@end example - -@noindent -Users then gain access to the resource using the same key.@* -@noindent -Client process: -@example -#include -char *shmaddr; -int id; -key_t key; -char proc_id = 'C'; - -key = ftok ("~creator/ipckey", proc_id); - -id = shmget (key, 0, 004); /* default size */ -if (id == -1) - perror ("shmget ..."); - -shmaddr = shmat (id, 0, SHM_RDONLY); /* attach segment for reading */ -if (shmaddr == (char *) -1) - perror ("shmat ..."); - -local_var = *(shmaddr + 3); /* read segment etc. */ - -shmdt (shmaddr); /* detach segment */ -@end example - -@noindent -When the resource is no longer needed the creator should remove it.@* -@noindent -Creator/owner process 2: -@example -key = ftok ("~creator/ipckey", proc_id) -id = shmget (key, 0, 0); -shmctl (id, IPC_RMID, NULL); -@end example - - -@node perms, syscalls, example, Overview -@section Permissions - -Each resource has an associated @code{ipc_perm} struct which defines the -creator, owner and access perms for the resource.@refill - -@example -struct ipc_perm - key_t key; /* set by creator */ - ushort uid; /* owner euid and egid */ - ushort gid; - ushort cuid; /* creator euid and egid */ - ushort cgid; - ushort mode; /* access modes in lower 9 bits */ - ushort seq; /* sequence number */ -@end example - -The creating process is the default owner. The owner can be reassigned -by the creator and has creator perms. Only the owner, creator or super-user -can delete the resource.@refill - -The lowest nine bits of the flags parameter supplied by the user to the -system call are compared with the values stored in @code{ipc_perms.mode} -to determine if the requested access is allowed. In the case -that the system call creates the resource, these bits are initialized -from the user supplied value.@refill - -As for files, access permissions are specified as read, write and exec -for user, group or other (though the exec perms are unused). For example -0624 grants read-write to owner, write-only to group and read-only -access to others.@refill - -For shared memory, note that read-write access for segments is determined -by a separate flag which is not stored in the @code{mode} field. -Shared memory segments attached with write access can be read.@refill - -The @code{cuid}, @code{cgid}, @code{key} and @code{seq} fields -cannot be changed by the user.@refill - - - -@node syscalls, Messages, perms, Overview -@section IPC system calls - -This section provides an overview of the IPC system calls. See the -specific sections on each type of resource for details.@refill - -Each type of mechanism provides a @dfn{get}, @dfn{ctl} and one or more -@dfn{op} system calls that allow the user to create or procure the -resource (get), define its behaviour or destroy it (ctl) and manipulate -the resources (op).@refill - - - -@subsection The @dfn{get} system calls - -The @code{get} call typically takes a @var{key} and returns a numeric -@var{id} that is used for further access. -The @var{id} is an index into the resource table. A sequence -number is maintained and incremented when a resource is -destroyed so that access using an obsolete @var{id} is likely to fail.@refill - -The user also specifies the permissions and other behaviour -charecteristics for the current access. The flags are or-ed with the -permissions when invoking system calls as in:@refill -@example -msgflg = IPC_CREAT | IPC_EXCL | 0666; -id = msgget (key, msgflg); -@end example -@itemize @bullet -@item -@code{key} : IPC_PRIVATE => new instance of resource is initialized. -@item -@code{flags} : -@itemize @asis -@item -IPC_CREAT : resource created for @var{key} if it does not exist. -@item -IPC_CREAT | IPC_EXCL : fail if resource exists for @var{key}. -@end itemize -@item -returns : an identifier used for all further access to the resource. -@end itemize - -Note that IPC_PRIVATE is not a flag but a special @code{key} -that ensures (when the call is successful) that a new resource is -created.@refill - -Use of IPC_PRIVATE does not make the resource inaccessible to other -users. For this you must set the access permissions appropriately.@refill - -There is currently no way for a process to ensure exclusive access to a -resource. IPC_CREAT | IPC_EXCL only ensures (on success) that a new -resource was initialized. It does not imply exclusive access.@refill - -@noindent -See Also : @xref{msgget}, @xref{semget}, @xref{shmget}.@refill - - - -@subsection The @dfn{ctl} system calls - -Provides or alters the information stored in the structure that describes -the resource indexed by @var{id}.@refill - -@example -#include -struct msqid_ds buf; -err = msgctl (id, IPC_STAT, &buf); -if (err) - !$#%* -else - printf ("creator uid = %d\n", buf.msg_perm.cuid); - .... -@end example - -@noindent -Commands supported by all @code{ctl} calls:@* -@itemize @bullet -@item -IPC_STAT : read info on resource specified by id into user allocated -buffer. The user must have read access to the resource.@refill -@item -IPC_SET : write info from buffer into resource data structure. The -user must be owner creator or super-user.@refill -@item -IPC_RMID : remove resource. The user must be the owner, creator or -super-user.@refill -@end itemize - -The IPC_RMID command results in immediate removal of a message -queue or semaphore array. Shared memory segments however, are -only destroyed upon the last detach after IPC_RMID is executed.@refill - -The @code{semctl} call provides a number of command options that allow -the user to determine or set the values of the semaphores in an array.@refill - -@noindent -See Also: @xref{msgctl}, @xref{semctl}, @xref{shmctl}.@refill - - -@subsection The @dfn{op} system calls - -Used to send or receive messages, read or alter semaphore values, -attach or detach shared memory segments. -The IPC_NOWAIT flag will cause the operation to fail with error EAGAIN -if the process has to wait on the call.@refill - -@noindent -@code{flags} : IPC_NOWAIT => return with error if a wait is required. - -@noindent -See Also: @xref{msgsnd},@xref{msgrcv},@xref{semop},@xref{shmat}, -@xref{shmdt}.@refill - - - -@node Messages, msgget, syscalls, Top -@section Messages - -A message resource is described by a struct @code{msqid_ds} which is -allocated and initialized when the resource is created. Some fields -in @code{msqid_ds} can then be altered (if desired) by invoking @code{msgctl}. -The memory used by the resource is released when it is destroyed by -a @code{msgctl} call.@refill - -@example -struct msqid_ds - struct ipc_perm msg_perm; - struct msg *msg_first; /* first message on queue (internal) */ - struct msg *msg_last; /* last message in queue (internal) */ - time_t msg_stime; /* last msgsnd time */ - time_t msg_rtime; /* last msgrcv time */ - time_t msg_ctime; /* last change time */ - struct wait_queue *wwait; /* writers waiting (internal) */ - struct wait_queue *rwait; /* readers waiting (internal) */ - ushort msg_cbytes; /* number of bytes used on queue */ - ushort msg_qnum; /* number of messages in queue */ - ushort msg_qbytes; /* max number of bytes on queue */ - ushort msg_lspid; /* pid of last msgsnd */ - ushort msg_lrpid; /* pid of last msgrcv */ -@end example - -To send or receive a message the user allocates a structure that looks -like a @code{msgbuf} but with an array @code{mtext} of the required size. -Messages have a type (positive integer) associated with them so that -(for example) a listener can choose to receive only messages of a -given type.@refill - -@example -struct msgbuf - long mtype; type of message (@xref{msgrcv}). - char mtext[1]; message text .. why is this not a ptr? -@end example - -The user must have write permissions to send and read permissions -to receive messages on a queue.@refill - -When @code{msgsnd} is invoked, the user's message is copied into -an internal struct @code{msg} and added to the queue. A @code{msgrcv} -will then read this message and free the associated struct @code{msg}.@refill - - -@menu -* msgget:: -* msgsnd:: -* msgrcv:: -* msgctl:: -* msglimits:: Implementation defined limits. -@end menu - - -@node msgget, msgsnd, Messages, Messages -@subsection msgget - -@noindent -A message queue is allocated by a msgget system call : - -@example -msqid = msgget (key_t key, int msgflg); -@end example - -@itemize @bullet -@item -@code{key}: an integer usually got from @code{ftok()} or IPC_PRIVATE.@refill -@item -@code{msgflg}: -@itemize @asis -@item -IPC_CREAT : used to create a new resource if it does not already exist. -@item -IPC_EXCL | IPC_CREAT : used to ensure failure of the call if the -resource already exists.@refill -@item -rwxrwxrwx : access permissions. -@end itemize -@item -returns: msqid (an integer used for all further access) on success. --1 on failure.@refill -@end itemize - -A message queue is allocated if there is no resource corresponding -to the given key. The access permissions specified are then copied -into the @code{msg_perm} struct and the fields in @code{msqid_ds} -initialized. The user must use the IPC_CREAT flag or key = IPC_PRIVATE, -if a new instance is to be allocated. If a resource corresponding to -@var{key} already exists, the access permissions are verified.@refill - -@noindent -Errors:@* -@noindent -EACCES : (procure) Do not have permission for requested access.@* -@noindent -EEXIST : (allocate) IPC_CREAT | IPC_EXCL specified and resource exists.@* -@noindent -EIDRM : (procure) The resource was removed.@* -@noindent -ENOSPC : All id's are taken (max of MSGMNI id's system-wide).@* -@noindent -ENOENT : Resource does not exist and IPC_CREAT not specified.@* -@noindent -ENOMEM : A new @code{msqid_ds} was to be created but ... nomem. - - - - -@node msgsnd, msgrcv, msgget, Messages -@subsection msgsnd - -@example -int msgsnd (int msqid, struct msgbuf *msgp, int msgsz, int msgflg); -@end example - -@itemize @bullet -@item -@code{msqid} : id obtained by a call to msgget. -@item -@code{msgsz} : size of msg text (@code{mtext}) in bytes. -@item -@code{msgp} : message to be sent. (msgp->mtype must be positive). -@item -@code{msgflg} : IPC_NOWAIT. -@item -returns : msgsz on success. -1 on error. -@end itemize - -The message text and type are stored in the internal @code{msg} -structure. @code{msg_cbytes}, @code{msg_qnum}, @code{msg_lspid}, -and @code{msg_stime} fields are updated. Readers waiting on the -queue are awakened.@refill - -@noindent -Errors:@* -@noindent -EACCES : Do not have write permission on queue.@* -@noindent -EAGAIN : IPC_NOWAIT specified and queue is full.@* -@noindent -EFAULT : msgp not accessible.@* -@noindent -EIDRM : The message queue was removed.@* -@noindent -EINTR : Full queue ... would have slept but ... was interrupted.@* -@noindent -EINVAL : mtype < 1, msgsz > MSGMAX, msgsz < 0, msqid < 0 or unused.@* -@noindent -ENOMEM : Could not allocate space for header and text.@* - - - -@node msgrcv, msgctl, msgsnd, Messages -@subsection msgrcv - -@example -int msgrcv (int msqid, struct msgbuf *msgp, int msgsz, long msgtyp, - int msgflg); -@end example - -@itemize @bullet -@item -msqid : id obtained by a call to msgget. -@item -msgsz : maximum size of message to receive. -@item -msgp : allocated by user to store the message in. -@item -msgtyp : -@itemize @asis -@item -0 => get first message on queue. -@item -> 0 => get first message of matching type. -@item -< 0 => get message with least type which is <= abs(msgtyp). -@end itemize -@item -msgflg : -@itemize @asis -@item -IPC_NOWAIT : Return immediately if message not found. -@item -MSG_NOERROR : The message is truncated if it is larger than msgsz. -@item -MSG_EXCEPT : Used with msgtyp > 0 to receive any msg except of specified -type.@refill -@end itemize -@item -returns : size of message if found. -1 on error. -@end itemize - -The first message that meets the @code{msgtyp} specification is -identified. For msgtyp < 0, the entire queue is searched for the -message with the smallest type.@refill - -If its length is smaller than msgsz or if the user specified the -MSG_NOERROR flag, its text and type are copied to msgp->mtext and -msgp->mtype, and it is taken off the queue.@refill - -The @code{msg_cbytes}, @code{msg_qnum}, @code{msg_lrpid}, -and @code{msg_rtime} fields are updated. Writers waiting on the -queue are awakened.@refill - -@noindent -Errors:@* -@noindent -E2BIG : msg bigger than msgsz and MSG_NOERROR not specified.@* -@noindent -EACCES : Do not have permission for reading the queue.@* -@noindent -EFAULT : msgp not accessible.@* -@noindent -EIDRM : msg queue was removed.@* -@noindent -EINTR : msg not found ... would have slept but ... was interrupted.@* -@noindent -EINVAL : msgsz > msgmax or msgsz < 0, msqid < 0 or unused.@* -@noindent -ENOMSG : msg of requested type not found and IPC_NOWAIT specified. - - - -@node msgctl, msglimits, msgrcv, Messages -@subsection msgctl - -@example -int msgctl (int msqid, int cmd, struct msqid_ds *buf); -@end example - -@itemize @bullet -@item -msqid : id obtained by a call to msgget. -@item -buf : allocated by user for reading/writing info. -@item -cmd : IPC_STAT, IPC_SET, IPC_RMID (@xref{syscalls}). -@end itemize - -IPC_STAT results in the copy of the queue data structure -into the user supplied buffer.@refill - -In the case of IPC_SET, the queue size (@code{msg_qbytes}) -and the @code{uid}, @code{gid}, @code{mode} (low 9 bits) fields -of the @code{msg_perm} struct are set from the user supplied values. -@code{msg_ctime} is updated.@refill - -Note that only the super user may increase the limit on the size of a -message queue beyond MSGMNB.@refill - -When the queue is destroyed (IPC_RMID), the sequence number is -incremented and all waiting readers and writers are awakened. -These processes will then return with @code{errno} set to EIDRM.@refill - -@noindent -Errors: -@noindent -EPERM : Insufficient privilege to increase the size of the queue (IPC_SET) -or remove it (IPC_RMID).@* -@noindent -EACCES : Do not have permission for reading the queue (IPC_STAT).@* -@noindent -EFAULT : buf not accessible (IPC_STAT, IPC_SET).@* -@noindent -EIDRM : msg queue was removed.@* -@noindent -EINVAL : invalid cmd, msqid < 0 or unused. - - -@node msglimits, Semaphores, msgctl, Messages -@subsection Limis on Message Resources - -@noindent -Sizeof various structures: -@itemize @asis -@item -msqid_ds 52 /* 1 per message queue .. dynamic */ -@item -msg 16 /* 1 for each message in system .. dynamic */ -@item -msgbuf 8 /* allocated by user */ -@end itemize - -@noindent -Limits -@itemize @bullet -@item -MSGMNI : number of message queue identifiers ... policy. -@item -MSGMAX : max size of message. -Header and message space allocated on one page. -MSGMAX = (PAGE_SIZE - sizeof(struct msg)). -Implementation maximum MSGMAX = 4080.@refill -@item -MSGMNB : default max size of a message queue ... policy. -The super-user can increase the size of a -queue beyond MSGMNB by a @code{msgctl} call.@refill -@end itemize - -@noindent -Unused or unimplemented:@* -MSGTQL max number of message headers system-wide.@* -MSGPOOL total size in bytes of msg pool. - - - -@node Semaphores, semget, msglimits, Top -@section Semaphores - -Each semaphore has a value >= 0. An id provides access to an array -of @code{nsems} semaphores. Operations such as read, increment or decrement -semaphores in a set are performed by the @code{semop} call which processes -@code{nsops} operations at a time. Each operation is specified in a struct -@code{sembuf} described below. The operations are applied only if all of -them succeed.@refill - -If you do not have a need for such arrays, you are probably better off using -the @code{test_bit}, @code{set_bit} and @code{clear_bit} bit-operations -defined in .@refill - -Semaphore operations may also be qualified by a SEM_UNDO flag which -results in the operation being undone when the process exits.@refill - -If a decrement cannot go through, a process will be put to sleep -on a queue waiting for the @code{semval} to increase unless it specifies -IPC_NOWAIT. A read operation can similarly result in a sleep on a -queue waiting for @code{semval} to become 0. (Actually there are -two queues per semaphore array).@refill - -@noindent -A semaphore array is described by: -@example -struct semid_ds - struct ipc_perm sem_perm; - time_t sem_otime; /* last semop time */ - time_t sem_ctime; /* last change time */ - struct wait_queue *eventn; /* wait for a semval to increase */ - struct wait_queue *eventz; /* wait for a semval to become 0 */ - struct sem_undo *undo; /* undo entries */ - ushort sem_nsems; /* no. of semaphores in array */ -@end example - -@noindent -Each semaphore is described internally by : -@example -struct sem - short sempid; /* pid of last semop() */ - ushort semval; /* current value */ - ushort semncnt; /* num procs awaiting increase in semval */ - ushort semzcnt; /* num procs awaiting semval = 0 */ -@end example - -@menu -* semget:: -* semop:: -* semctl:: -* semlimits:: Limits imposed by this implementation. -@end menu - -@node semget, semop, Semaphores, Semaphores -@subsection semget - -@noindent -A semaphore array is allocated by a semget system call: - -@example -semid = semget (key_t key, int nsems, int semflg); -@end example - -@itemize @bullet -@item -@code{key} : an integer usually got from @code{ftok} or IPC_PRIVATE -@item -@code{nsems} : -@itemize @asis -@item -# of semaphores in array (0 <= nsems <= SEMMSL <= SEMMNS) -@item -0 => dont care can be used when not creating the resource. -If successful you always get access to the entire array anyway.@refill -@end itemize -@item -semflg : -@itemize @asis -@item -IPC_CREAT used to create a new resource -@item -IPC_EXCL used with IPC_CREAT to ensure failure if the resource exists. -@item -rwxrwxrwx access permissions. -@end itemize -@item -returns : semid on success. -1 on failure. -@end itemize - -An array of nsems semaphores is allocated if there is no resource -corresponding to the given key. The access permissions specified are -then copied into the @code{sem_perm} struct for the array along with the -user-id etc. The user must use the IPC_CREAT flag or key = IPC_PRIVATE -if a new resource is to be created.@refill - -@noindent -Errors:@* -@noindent -EINVAL : nsems not in above range (allocate).@* - nsems greater than number in array (procure).@* -@noindent -EEXIST : (allocate) IPC_CREAT | IPC_EXCL specified and resource exists.@* -@noindent -EIDRM : (procure) The resource was removed.@* -@noindent -ENOMEM : could not allocate space for semaphore array.@* -@noindent -ENOSPC : No arrays available (SEMMNI), too few semaphores available (SEMMNS).@* -@noindent -ENOENT : Resource does not exist and IPC_CREAT not specified.@* -@noindent -EACCES : (procure) do not have permission for specified access. - - -@node semop, semctl, semget, Semaphores -@subsection semop - -@noindent -Operations on semaphore arrays are performed by calling semop : - -@example -int semop (int semid, struct sembuf *sops, unsigned nsops); -@end example -@itemize @bullet -@item -semid : id obtained by a call to semget. -@item -sops : array of semaphore operations. -@item -nsops : number of operations in array (0 < nsops < SEMOPM). -@item -returns : semval for last operation. -1 on failure. -@end itemize - -@noindent -Operations are described by a structure sembuf: -@example -struct sembuf - ushort sem_num; /* semaphore index in array */ - short sem_op; /* semaphore operation */ - short sem_flg; /* operation flags */ -@end example - -The value @code{sem_op} is to be added (signed) to the current value semval -of the semaphore with index sem_num (0 .. nsems -1) in the set. -Flags recognized in sem_flg are IPC_NOWAIT and SEM_UNDO.@refill - -@noindent -Two kinds of operations can result in wait: -@enumerate -@item -If sem_op is 0 (read operation) and semval is non-zero, the process -sleeps on a queue waiting for semval to become zero or returns with -error EAGAIN if (IPC_NOWAIT | sem_flg) is true.@refill -@item -If (sem_op < 0) and (semval + sem_op < 0), the process either sleeps -on a queue waiting for semval to increase or returns with error EAGAIN if -(sem_flg & IPC_NOWAIT) is true.@refill -@end enumerate - -The array sops is first read in and preliminary checks performed on -the arguments. The operations are parsed to determine if any of -them needs write permissions or requests an undo operation.@refill - -The operations are then tried and the process sleeps if any operation -that does not specify IPC_NOWAIT cannot go through. If a process sleeps -it repeats these checks on waking up. If any operation that requests -IPC_NOWAIT, cannot go through at any stage, the call returns with errno -set to EAGAIN.@refill - -Finally, operations are committed when all go through without an intervening -sleep. Processes waiting on the zero_queue or increment_queue are awakened -if any of the semval's becomes zero or is incremented respectively.@refill - -@noindent -Errors:@* -@noindent -E2BIG : nsops > SEMOPM.@* -@noindent -EACCES : Do not have permission for requested (read/alter) access.@* -@noindent -EAGAIN : An operation with IPC_NOWAIT specified could not go through.@* -@noindent -EFAULT : The array sops is not accessible.@* -@noindent -EFBIG : An operation had semnum >= nsems.@* -@noindent -EIDRM : The resource was removed.@* -@noindent -EINTR : The process was interrupted on its way to a wait queue.@* -@noindent -EINVAL : nsops is 0, semid < 0 or unused.@* -@noindent -ENOMEM : SEM_UNDO requested. Could not allocate space for undo structure.@* -@noindent -ERANGE : sem_op + semval > SEMVMX for some operation. - - -@node semctl, semlimits, semop, Semaphores -@subsection semctl - -@example -int semctl (int semid, int semnum, int cmd, union semun arg); -@end example - -@itemize @bullet -@item -semid : id obtained by a call to semget. -@item -cmd : -@itemize @asis -@item -GETPID return pid for the process that executed the last semop. -@item -GETVAL return semval of semaphore with index semnum. -@item -GETNCNT return number of processes waiting for semval to increase. -@item -GETZCNT return number of processes waiting for semval to become 0 -@item -SETVAL set semval = arg.val. -@item -GETALL read all semval's into arg.array. -@item -SETALL set all semval's with values given in arg.array. -@end itemize -@item -returns : 0 on success or as given above. -1 on failure. -@end itemize - -The first 4 operate on the semaphore with index semnum in the set. -The last two operate on all semaphores in the set.@refill - -@code{arg} is a union : -@example -union semun - int val; value for SETVAL. - struct semid_ds *buf; buffer for IPC_STAT and IPC_SET. - ushort *array; array for GETALL and SETALL -@end example - -@itemize @bullet -@item -IPC_SET, SETVAL, SETALL : sem_ctime is updated. -@item -SETVAL, SETALL : Undo entries are cleared for altered semaphores in -all processes. Processes sleeping on the wait queues are -awakened if a semval becomes 0 or increases.@refill -@item -IPC_SET : sem_perm.uid, sem_perm.gid, sem_perm.mode are updated from -user supplied values.@refill -@end itemize - -@noindent -Errors: -@noindent -EACCES : do not have permission for specified access.@* -@noindent -EFAULT : arg is not accessible.@* -@noindent -EIDRM : The resource was removed.@* -@noindent -EINVAL : semid < 0 or semnum < 0 or semnum >= nsems.@* -@noindent -EPERM : IPC_RMID, IPC_SET ... not creator, owner or super-user.@* -@noindent -ERANGE : arg.array[i].semval > SEMVMX or < 0 for some i. - - - - -@node semlimits, Shared Memory, semctl, Semaphores -@subsection Limits on Semaphore Resources - -@noindent -Sizeof various structures: -@example -semid_ds 44 /* 1 per semaphore array .. dynamic */ -sem 8 /* 1 for each semaphore in system .. dynamic */ -sembuf 6 /* allocated by user */ -sem_undo 20 /* 1 for each undo request .. dynamic */ -@end example - -@noindent -Limits :@* -@itemize @bullet -@item -SEMVMX 32767 semaphore maximum value (short). -@item -SEMMNI number of semaphore identifiers (or arrays) system wide...policy. -@item -SEMMSL maximum number of semaphores per id. -1 semid_ds per array, 1 struct sem per semaphore -=> SEMMSL = (PAGE_SIZE - sizeof(semid_ds)) / sizeof(sem). -Implementation maximum SEMMSL = 500.@refill -@item -SEMMNS maximum number of semaphores system wide ... policy. -Setting SEMMNS >= SEMMSL*SEMMNI makes it irrelevent.@refill -@item -SEMOPM Maximum number of operations in one semop call...policy. -@end itemize - -@noindent -Unused or unimplemented:@* -@noindent -SEMAEM adjust on exit max value.@* -@noindent -SEMMNU number of undo structures system-wide.@* -@noindent -SEMUME maximum number of undo entries per process. - - - -@node Shared Memory, shmget, semlimits, Top -@section Shared Memory - -Shared memory is distinct from the sharing of read-only code pages or -the sharing of unaltered data pages that is available due to the -copy-on-write mechanism. The essential difference is that the -shared pages are dirty (in the case of Shared memory) and can be -made to appear at a convenient location in the process' address space.@refill - -@noindent -A shared segment is described by : -@example -struct shmid_ds - struct ipc_perm shm_perm; - int shm_segsz; /* size of segment (bytes) */ - time_t shm_atime; /* last attach time */ - time_t shm_dtime; /* last detach time */ - time_t shm_ctime; /* last change time */ - ulong *shm_pages; /* internal page table */ - ushort shm_cpid; /* pid, creator */ - ushort shm_lpid; /* pid, last operation */ - short shm_nattch; /* no. of current attaches */ -@end example - -A shmget allocates a shmid_ds and an internal page table. A shmat -maps the segment into the process' address space with pointers -into the internal page table and the actual pages are faulted in -as needed. The memory associated with the segment must be explicitly -destroyed by calling shmctl with IPC_RMID.@refill - -@menu -* shmget:: -* shmat:: -* shmdt:: -* shmctl:: -* shmlimits:: Limits imposed by this implementation. -@end menu - - -@node shmget, shmat, Shared Memory, Shared Memory -@subsection shmget - -@noindent -A shared memory segment is allocated by a shmget system call: - -@example -int shmget(key_t key, int size, int shmflg); -@end example - -@itemize @bullet -@item -key : an integer usually got from @code{ftok} or IPC_PRIVATE -@item -size : size of the segment in bytes (SHMMIN <= size <= SHMMAX). -@item -shmflg : -@itemize @asis -@item -IPC_CREAT used to create a new resource -@item -IPC_EXCL used with IPC_CREAT to ensure failure if the resource exists. -@item -rwxrwxrwx access permissions. -@end itemize -@item -returns : shmid on success. -1 on failure. -@end itemize - -A descriptor for a shared memory segment is allocated if there isn't one -corresponding to the given key. The access permissions specified are -then copied into the @code{shm_perm} struct for the segment along with the -user-id etc. The user must use the IPC_CREAT flag or key = IPC_PRIVATE -to allocate a new segment.@refill - -If the segment already exists, the access permissions are verified, -and a check is made to see that it is not marked for destruction.@refill - -@code{size} is effectively rounded up to a multiple of PAGE_SIZE as shared -memory is allocated in pages.@refill - -@noindent -Errors:@* -@noindent -EINVAL : (allocate) Size not in range specified above.@* - (procure) Size greater than size of segment.@* -@noindent -EEXIST : (allocate) IPC_CREAT | IPC_EXCL specified and resource exists.@* -@noindent -EIDRM : (procure) The resource is marked destroyed or was removed.@* -@noindent -ENOSPC : (allocate) All id's are taken (max of SHMMNI id's system-wide). -Allocating a segment of the requested size would exceed the -system wide limit on total shared memory (SHMALL).@refill -@* -@noindent -ENOENT : (procure) Resource does not exist and IPC_CREAT not specified.@* -@noindent -EACCES : (procure) Do not have permission for specified access.@* -@noindent -ENOMEM : (allocate) Could not allocate memory for shmid_ds or pg_table. - - - -@node shmat, shmdt, shmget, Shared Memory -@subsection shmat - -@noindent -Maps a shared segment into the process' address space. - -@example -char *virt_addr; -virt_addr = shmat (int shmid, char *shmaddr, int shmflg); -@end example - -@itemize @bullet -@item -shmid : id got from call to shmget. -@item -shmaddr : requested attach address.@* - If shmaddr is 0 the system finds an unmapped region.@* - If a non-zero value is indicated the value must be page - aligned or the user must specify the SHM_RND flag.@refill -@item -shmflg :@* - SHM_RDONLY : request read-only attach.@* - SHM_RND : attach address is rounded DOWN to a multiple of SHMLBA. -@item -returns: virtual address of attached segment. -1 on failure. -@end itemize - -When shmaddr is 0, the attach address is determined by finding an -unmapped region in the address range 1G to 1.5G, starting at 1.5G -and coming down from there. The algorithm is very simple so you -are encouraged to avoid non-specific attaches. - -@noindent -Algorithm: -@display -Determine attach address as described above. -Check region (shmaddr, shmaddr + size) is not mapped and allocate -page tables (undocumented SHM_REMAP flag!). -Map the region by setting up pointers into the internal page table. -Add a descriptor for the attach to the task struct for the process. -@code{shm_nattch}, @code{shm_lpid}, @code{shm_atime} are updated. -@end display - -@noindent -Notes:@* -The @code{brk} value is not altered. -The segment is automatically detached when the process exits. -The same segment may be attached as read-only or read-write and -more than once in the process' address space. -A shmat can succeed on a segment marked for destruction. -The request for a particular type of attach is made using the SHM_RDONLY flag. -There is no notion of a write-only attach. The requested attach -permissions must fall within those allowed by @code{shm_perm.mode}. - -@noindent -Errors:@* -@noindent -EACCES : Do not have permission for requested access.@* -@noindent -EINVAL : shmid < 0 or unused, shmaddr not aligned, attach at brk failed.@* -@noindent -EIDRM : resource was removed.@* -@noindent -ENOMEM : Could not allocate memory for descriptor or page tables. - - -@node shmdt, shmctl, shmat, Shared Memory -@subsection shmdt - -@example -int shmdt (char *shmaddr); -@end example - -@itemize @bullet -@item -shmaddr : attach address of segment (returned by shmat). -@item -returns : 0 on success. -1 on failure. -@end itemize - -An attached segment is detached and @code{shm_nattch} decremented. The -occupied region in user space is unmapped. The segment is destroyed -if it is marked for destruction and @code{shm_nattch} is 0. -@code{shm_lpid} and @code{shm_dtime} are updated.@refill - -@noindent -Errors:@* -@noindent -EINVAL : No shared memory segment attached at shmaddr. - - -@node shmctl, shmlimits, shmdt, Shared Memory -@subsection shmctl - -@noindent -Destroys allocated segments. Reads/Writes the control structures. - -@example -int shmctl (int shmid, int cmd, struct shmid_ds *buf); -@end example - -@itemize @bullet -@item -shmid : id got from call to shmget. -@item -cmd : IPC_STAT, IPC_SET, IPC_RMID (@xref{syscalls}). -@itemize @asis -@item -IPC_SET : Used to set the owner uid, gid, and shm_perms.mode field. -@item -IPC_RMID : The segment is marked destroyed. It is only destroyed -on the last detach.@refill -@item -IPC_STAT : The shmid_ds structure is copied into the user allocated buffer. -@end itemize -@item -buf : used to read (IPC_STAT) or write (IPC_SET) information. -@item -returns : 0 on success, -1 on failure. -@end itemize - -The user must execute an IPC_RMID shmctl call to free the memory -allocated by the shared segment. Otherwise all the pages faulted in -will continue to live in memory or swap.@refill - -@noindent -Errors:@* -@noindent -EACCES : Do not have permission for requested access.@* -@noindent -EFAULT : buf is not accessible.@* -@noindent -EINVAL : shmid < 0 or unused.@* -@noindent -EIDRM : identifier destroyed.@* -@noindent -EPERM : not creator, owner or super-user (IPC_SET, IPC_RMID). - - -@node shmlimits, Notes, shmctl, Shared Memory -@subsection Limits on Shared Memory Resources - -@noindent -Limits: -@itemize @bullet -@item -SHMMNI max num of shared segments system wide ... 4096. -@item -SHMMAX max shared memory segment size (bytes) ... 4M -@item -SHMMIN min shared memory segment size (bytes). -1 byte (though PAGE_SIZE is the effective minimum size).@refill -@item -SHMALL max shared mem system wide (in pages) ... policy. -@item -SHMLBA segment low boundary address multiple. -Must be page aligned. SHMLBA = PAGE_SIZE.@refill -@end itemize -@noindent -Unused or unimplemented:@* -SHMSEG : maximum number of shared segments per process. - - - -@node Notes, Top, shmlimits, Top -@section Miscellaneous Notes - -The system calls are mapped into one -- @code{sys_ipc}. This should be -transparent to the user.@refill - -@subsection Semaphore @code{undo} requests - -There is one sem_undo structure associated with a process for -each semaphore which was altered (with an undo request) by the process. -@code{sem_undo} structures are freed only when the process exits. - -One major cause for unhappiness with the undo mechanism is that -it does not fit in with the notion of having an atomic set of -operations on an array. The undo requests for an array and each -semaphore therein may have been accumulated over many @code{semop} -calls. Thus use the undo mechanism with private semaphores only.@refill - -Should the process sleep in @code{exit} or should all undo -operations be applied with the IPC_NOWAIT flag in effect? -Currently those undo operations which go through immediately are -applied and those that require a wait are ignored silently.@refill - -@subsection Shared memory, @code{malloc} and the @code{brk}. -Note that since this section was written the implementation was -changed so that non-specific attaches are done in the region -1G - 1.5G. However much of the following is still worth thinking -about so I left it in. - -On many systems, the shared memory is allocated in a special region -of the address space ... way up somewhere. As mentioned earlier, -this implementation attaches shared segments at the lowest possible -address. Thus if you plan to use @code{malloc}, it is wise to malloc a -large space and then proceed to attach the shared segments. This way -malloc sets the brk sufficiently above the region it will use.@refill - -Alternatively you can use @code{sbrk} to adjust the @code{brk} value -as you make shared memory attaches. The implementation is not very -smart about selecting attach addresses. Using the system default -addresses will result in fragmentation if detaches do not occur -in the reverse sequence as attaches.@refill - -Taking control of the matter is probably best. The rule applied -is that attaches are allowed in unmapped regions other than -in the text space (see ). Also remember that attach addresses -and segment sizes are multiples of PAGE_SIZE.@refill - -One more trap (I quote Bruno on this). If you use malloc() to get space -for your shared memory (ie. to fix the @code{brk}), you must ensure you -get an unmapped address range. This means you must mallocate more memory -than you had ever allocated before. Memory returned by malloc(), used, -then freed by free() and then again returned by malloc is no good. -Neither is calloced memory.@refill - -Note that a shared memory region remains a shared memory region until -you unmap it. Attaching a segment at the @code{brk} and calling malloc -after that will result in an overlap of what malloc thinks is its -space with what is really a shared memory region. For example in the case -of a read-only attach, you will not be able to write to the overlapped -portion.@refill - - -@subsection Fork, exec and exit - -On a fork, the child inherits attached shared memory segments but -not the semaphore undo information.@refill - -In the case of an exec, the attached shared segments are detached. -The sem undo information however remains intact.@refill - -Upon exit, all attached shared memory segments are detached. -The adjust values in the undo structures are added to the relevant semvals -if the operations are permitted. Disallowed operations are ignored.@refill - - -@subsection Other Features - -These features of the current implementation are -likely to be modified in the future. - -The SHM_LOCK and SHM_UNLOCK flag are available (super-user) for use with the -@code{shmctl} call to prevent swapping of a shared segment. The user -must fault in any pages that are required to be present after locking -is enabled. - -The IPC_INFO, MSG_STAT, MSG_INFO, SHM_STAT, SHM_INFO, SEM_STAT, SEMINFO -@code{ctl} calls are used by the @code{ipcs} program to provide information -on allocated resources. These can be modified as needed or moved to a proc -file system interface. - - -@sp 3 -Thanks to Ove Ewerlid, Bruno Haible, Ulrich Pegelow and Linus Torvalds -for ideas, tutorials, bug reports and fixes, and merriment. And more -thanks to Bruno. - - -@contents -@bye - -- cgit v1.2.3 From 37f243ed57e5a783c19c4784cf24dfed52b89e32 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 10 Nov 2010 11:48:30 +0100 Subject: swapon: better text for "discard", note about swapon in fstab.5 Suggested by Hugh Dickins. Thanks. Signed-off-by: Karel Zak --- mount/fstab.5 | 5 ++++- mount/swapon.8 | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/mount/fstab.5 b/mount/fstab.5 index 99557194..cd5cf558 100644 --- a/mount/fstab.5 +++ b/mount/fstab.5 @@ -176,8 +176,11 @@ This field describes the mount options associated with the filesystem. It is formatted as a comma separated list of options. It contains at least the type of mount plus any additional options appropriate to the filesystem -type. For documentation on the available options, see +type. For documentation on the available mount options, see .BR mount (8). +For documentation on the available swap options, see +.BR swapon (8). + Basic file system independent options are: .TP .B defaults diff --git a/mount/swapon.8 b/mount/swapon.8 index e35c6e5f..1fe62987 100644 --- a/mount/swapon.8 +++ b/mount/swapon.8 @@ -113,14 +113,14 @@ are made available, except for those with the ``noauto'' option. Devices that are already being used as swap are silently skipped. .TP .B "\-d, \-\-discard" -Swapping will discard clusters of swap pages in between freeing them -and re-writing to them, if the swap device supports that. +Discard freed swap pages before they are reused, if the swap +device supports the discard or trim operation. This may improve +performance on some Solid State Devices, but often it does not. The .I /etc/fstab mount option .BI discard may be also used to enable discard flag. - .TP .B "\-e, \-\-ifexists" Silently skip devices that do not exist. -- cgit v1.2.3 From a4a27b06e88cadbbd3bc5a14b50a9ff70646b7d7 Mon Sep 17 00:00:00 2001 From: Thorsten Glaser Date: Sun, 7 Nov 2010 14:00:04 +0000 Subject: hwclock: [m68k] unbreak FTBFS with recent (>= 2.4.18?) kernels The old KDGHWCLK ioctl was removed from the Linux kernel quite some time ago. The kd.c source file of hwclock contains fallback code to handle this, but the fallback code never could have compiled or was not fixed along other code changes. The Linux kernel nowadays igno- res the ioctl entirely so removing it unless provided by the kernel headers, to keep it working on very old kernels, seems the sensible thing to do, as the comments say m68k only and deprecated (which is correct AFAICT). According to pickaxe on gitweb, it was removed in 2002: http://git.kernel.org/?p=linux/kernel/git/torvalds/old-2.6-bkcvs.git;a=commit;h=a915e414af5fc541ff62ef0bfec847457ae650bc Addresses: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=578168 Signed-off-by: Thorsten Glaser Signed-off-by: Karel Zak --- AUTHORS | 1 + hwclock/kd.c | 43 ++++++++++++++++++------------------------- 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/AUTHORS b/AUTHORS index d6a6a62c..4284620a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -210,6 +210,7 @@ CONTRIBUTORS: Sven Jost Theodore Ts'o Thomas Fehr + Thorsten Glaser Tilman Schmidt Timo Juhani Lindfors Tom Prince diff --git a/hwclock/kd.c b/hwclock/kd.c index 3da87caf..66ff579b 100644 --- a/hwclock/kd.c +++ b/hwclock/kd.c @@ -2,14 +2,7 @@ #include "clock.h" -#ifndef __m68k__ - -struct clock_ops * -probe_for_kd_clock() { - return NULL; -} - -#else /* __m68k__ */ +#ifdef __m68k__ #include /* for close() */ #include /* for O_RDONLY */ @@ -19,26 +12,26 @@ probe_for_kd_clock() { #include "nls.h" #include "usleep.h" -static int con_fd = -1; /* opened by probe_for_kd_clock() */ - /* never closed */ -static char *con_fd_filename; /* usually "/dev/tty1" */ - /* Get defines for KDGHWCLK and KDSHWCLK (m68k) */ #include -#ifndef KDGHWCLK -#define KDGHWCLK 0x4B50 /* get hardware clock */ -#define KDSHWCLK 0x4B51 /* set hardware clock */ -struct hwclk_time { - unsigned sec; /* 0..59 */ - unsigned min; /* 0..59 */ - unsigned hour; /* 0..23 */ - unsigned day; /* 1..31 */ - unsigned mon; /* 0..11 */ - unsigned year; /* 70... */ - int wday; /* 0..6, 0 is Sunday, -1 means unknown/don't set */ -}; + +/* Even on m68k, if KDGHWCLK (antique) is not defined, don't build this */ + #endif +#if !defined(__m68k__) || !defined(KDGHWCLK) + +struct clock_ops * +probe_for_kd_clock() { + return NULL; +} + +#else /* __m68k__ && KDGHWCLK */ + +static int con_fd = -1; /* opened by probe_for_kd_clock() */ + /* never closed */ +static char *con_fd_filename; /* usually "/dev/tty1" */ + static int synchronize_to_clock_tick_kd(void) { /*---------------------------------------------------------------------------- @@ -183,4 +176,4 @@ probe_for_kd_clock() { } return ret; } -#endif /* __m68k__ */ +#endif /* __m68k__ && KDGHWCLK */ -- cgit v1.2.3 From e8ae49476e5391fc477adb75d891c6b43543ded8 Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Thu, 11 Nov 2010 10:34:52 -0300 Subject: libblkid: add blkid_probe_get_sectors() This function allows users to obtain the device's 512-byte sector count. Signed-off-by: Davidlohr Bueso Signed-off-by: Karel Zak --- shlibs/blkid/docs/libblkid-sections.txt | 1 + shlibs/blkid/src/blkid.h.in | 1 + shlibs/blkid/src/blkid.sym | 1 + shlibs/blkid/src/probe.c | 11 +++++++++++ 4 files changed, 14 insertions(+) diff --git a/shlibs/blkid/docs/libblkid-sections.txt b/shlibs/blkid/docs/libblkid-sections.txt index c8b0045d..47675f4a 100644 --- a/shlibs/blkid/docs/libblkid-sections.txt +++ b/shlibs/blkid/docs/libblkid-sections.txt @@ -42,6 +42,7 @@ blkid_new_probe blkid_new_probe_from_filename blkid_probe_get_devno blkid_probe_get_sectorsize +blkid_probe_get_sectors blkid_probe_get_size blkid_probe_set_device blkid_reset_probe diff --git a/shlibs/blkid/src/blkid.h.in b/shlibs/blkid/src/blkid.h.in index 7fa2fde6..46cbeb23 100644 --- a/shlibs/blkid/src/blkid.h.in +++ b/shlibs/blkid/src/blkid.h.in @@ -203,6 +203,7 @@ extern int blkid_probe_is_wholedisk(blkid_probe pr); extern blkid_loff_t blkid_probe_get_size(blkid_probe pr); extern blkid_loff_t blkid_probe_get_offset(blkid_probe pr); extern unsigned int blkid_probe_get_sectorsize(blkid_probe pr); +extern blkid_loff_t blkid_probe_get_sectors(blkid_probe pr); extern int blkid_probe_get_fd(blkid_probe pr); diff --git a/shlibs/blkid/src/blkid.sym b/shlibs/blkid/src/blkid.sym index 4085d2ce..f6e488a9 100644 --- a/shlibs/blkid/src/blkid.sym +++ b/shlibs/blkid/src/blkid.sym @@ -100,6 +100,7 @@ global: blkid_probe_get_devno; blkid_probe_get_partitions; blkid_probe_get_sectorsize; + blkid_probe_get_sectors; blkid_probe_get_size; blkid_probe_get_topology; blkid_probe_invert_partitions_filter; diff --git a/shlibs/blkid/src/probe.c b/shlibs/blkid/src/probe.c index a748f2e2..3698b99b 100644 --- a/shlibs/blkid/src/probe.c +++ b/shlibs/blkid/src/probe.c @@ -1187,6 +1187,17 @@ unsigned int blkid_probe_get_sectorsize(blkid_probe pr) return pr->blkssz; } +/** + * blkid_probe_get_sectors: + * @pr: probe + * + * Returns: 512-byte sector count or -1 in case of error. + */ +blkid_loff_t blkid_probe_get_sectors(blkid_probe pr) +{ + return pr ? pr->size >> 9 : -1; +} + /** * blkid_probe_numof_values: * @pr: probe -- cgit v1.2.3 From 97be4a37e327108e2d95ca832e71f6eda1e2d908 Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Mon, 15 Nov 2010 08:55:16 -0300 Subject: lib/tt: fix langinfo build break MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When HAVE_LANGINFO_H is not defined we break the compilation in tt.c: CC tt.o tt.c: In function â€tt_new_table’: tt.c:142: warning: implicit declaration of function â€nl_langinfo’ tt.c:142: error: â€CODESET’ undeclared (first use in this function) tt.c:142: error: (Each undeclared identifier is reported only once tt.c:142: error: for each function it appears in.) make: *** [tt.o] Error 1 Signed-off-by: Davidlohr Bueso --- lib/tt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tt.c b/lib/tt.c index 7d87bf54..d3436e10 100644 --- a/lib/tt.c +++ b/lib/tt.c @@ -138,7 +138,7 @@ struct tt *tt_new_table(int flags) INIT_LIST_HEAD(&tb->tb_lines); INIT_LIST_HEAD(&tb->tb_columns); -#ifdef HAVE_WIDECHAR +#if defined(HAVE_WIDECHAR) && defined(HAVE_LANGINFO_H) if (!(flags & TT_FL_ASCII) && !strcmp(nl_langinfo(CODESET), "UTF-8")) tb->symbols = &utf8_tt_symbols; else -- cgit v1.2.3 From dc61d398ba14a38f13aeab3be9e9e09f7f117179 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 15 Nov 2010 16:42:45 +0100 Subject: lib: add fallback for nl_langinfo() The fallback ignores locales and returns hardcoded static strings. It should be enough to include "nls.h" to work with nl_langinfo() on all systems. Signed-off-by: Karel Zak --- configure.ac | 7 +++- include/nls.h | 73 ++++++++++++++++++++++++++++++++++ lib/langinfo.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 lib/langinfo.c diff --git a/configure.ac b/configure.ac index 561424a6..ca3e4af5 100644 --- a/configure.ac +++ b/configure.ac @@ -110,7 +110,6 @@ AC_CHECK_HEADERS( [err.h \ errno.h \ getopt.h \ - langinfo.h \ linux/fd.h \ linux/tiocl.h \ linux/version.h \ @@ -146,10 +145,16 @@ AC_CHECK_HEADERS( sys/user.h \ sys/resource.h \ unistd.h ]) + AC_CHECK_HEADERS([linux/raw.h], [AM_CONDITIONAL([HAVE_RAW], [true])], [AM_CONDITIONAL([HAVE_RAW], [false])]) +AC_CHECK_HEADERS([langinfo.h], + [AM_CONDITIONAL([HAVE_LANGINFO], [true])], + [AM_CONDITIONAL([HAVE_LANGINFO], [false])]) + + AC_CHECK_DECLS([_NL_TIME_WEEK_1STDAY],[],[],[[#include ]]) AC_CHECK_DECL([llseek], diff --git a/include/nls.h b/include/nls.h index dd0440c9..00f2e37a 100644 --- a/include/nls.h +++ b/include/nls.h @@ -31,4 +31,77 @@ int main(int argc, char *argv[]); # define N_(Text) (Text) #endif +#ifdef HAVE_LANGINFO_H +# include +#else + +typedef int nl_item; +extern char *langinfo_fallback(nl_item item); + +# define nl_langinfo langinfo_fallback + +enum { + CODESET = 1, + RADIXCHAR, + THOUSEP, + D_T_FMT, + D_FMT, + T_FMT, + T_FMT_AMPM, + AM_STR, + PM_STR, + + DAY_1, + DAY_2, + DAY_3, + DAY_4, + DAY_5, + DAY_6, + DAY_7, + + ABDAY_1, + ABDAY_2, + ABDAY_3, + ABDAY_4, + ABDAY_5, + ABDAY_6, + ABDAY_7, + + MON_1, + MON_2, + MON_3, + MON_4, + MON_5, + MON_6, + MON_7, + MON_8, + MON_9, + MON_10, + MON_11, + MON_12, + + ABMON_1, + ABMON_2, + ABMON_3, + ABMON_4, + ABMON_5, + ABMON_6, + ABMON_7, + ABMON_8, + ABMON_9, + ABMON_10, + ABMON_11, + ABMON_12, + + ERA_D_FMT, + ERA_D_T_FMT, + ERA_T_FMT, + ALT_DIGITS, + CRNCYSTR, + YESEXPR, + NOEXPR +}; + +#endif /* !HAVE_LANGINFO_H */ + #endif /* UTIL_LINUX_NLS_H */ diff --git a/lib/langinfo.c b/lib/langinfo.c new file mode 100644 index 00000000..deeab9b1 --- /dev/null +++ b/lib/langinfo.c @@ -0,0 +1,121 @@ +/* + * This is callback solution for systems without nl_langinfo(), this function + * returns hardcoded and on locale setting independed value. + * + * See langinfo.h man page for more details. + * + * Copyright (C) 2010 Karel Zak + */ +#include "nls.h" + +char *langinfo_fallback(nl_item item) +{ + switch (item) { + case CODESET: + return "ISO-8859-1"; + case THOUSEP: + return ","; + case D_T_FMT: + case ERA_D_T_FMT: + return "%a %b %e %H:%M:%S %Y"; + case D_FMT: + case ERA_D_FMT: + return "%m/%d/%y"; + case T_FMT: + case ERA_T_FMT: + return "%H:%M:%S"; + case T_FMT_AMPM: + return "%I:%M:%S %p"; + case AM_STR: + return "AM"; + case PM_STR: + return "PM"; + case DAY_1: + return "Sunday"; + case DAY_2: + return "Monday"; + case DAY_3: + return "Tuesday"; + case DAY_4: + return "Wednesday"; + case DAY_5: + return "Thursday"; + case DAY_6: + return "Friday"; + case DAY_7: + return "Saturday"; + case ABDAY_1: + return "Sun"; + case ABDAY_2: + return "Mon"; + case ABDAY_3: + return "Tue"; + case ABDAY_4: + return "Wed"; + case ABDAY_5: + return "Thu"; + case ABDAY_6: + return "Fri"; + case ABDAY_7: + return "Sat"; + case MON_1: + return "January"; + case MON_2: + return "February"; + case MON_3: + return "March"; + case MON_4: + return "April"; + case MON_5: + return "May"; + case MON_6: + return "June"; + case MON_7: + return "July"; + case MON_8: + return "August"; + case MON_9: + return "September"; + case MON_10: + return "October"; + case MON_11: + return "November"; + case MON_12: + return "December"; + case ABMON_1: + return "Jan"; + case ABMON_2: + return "Feb"; + case ABMON_3: + return "Mar"; + case ABMON_4: + return "Apr"; + case ABMON_5: + return "May"; + case ABMON_6: + return "Jun"; + case ABMON_7: + return "Jul"; + case ABMON_8: + return "Aug"; + case ABMON_9: + return "Sep"; + case ABMON_10: + return "Oct"; + case ABMON_11: + return "Nov"; + case ABMON_12: + return "Dec"; + case ALT_DIGITS: + return "\0\0\0\0\0\0\0\0\0\0"; + case CRNCYSTR: + return "-"; + case YESEXPR: + return "^[yY]"; + case NOEXPR: + return "^[nN]"; + default: + return ""; + } +} + -- cgit v1.2.3 From f7a29259ee46b1065ca3ba36f921fecfcbb6fdc6 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 15 Nov 2010 16:47:13 +0100 Subject: findmnt: follow HAVE_LANGINFO Signed-off-by: Karel Zak --- lib/tt.c | 5 +---- misc-utils/Makefile.am | 3 +++ misc-utils/findmnt.c | 3 --- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/lib/tt.c b/lib/tt.c index d3436e10..a4aabfe0 100644 --- a/lib/tt.c +++ b/lib/tt.c @@ -15,9 +15,6 @@ #include #include #include -#ifdef HAVE_LANGINFO_H -#include -#endif #ifdef HAVE_SYS_IOCTL_H #include #endif @@ -138,7 +135,7 @@ struct tt *tt_new_table(int flags) INIT_LIST_HEAD(&tb->tb_lines); INIT_LIST_HEAD(&tb->tb_columns); -#if defined(HAVE_WIDECHAR) && defined(HAVE_LANGINFO_H) +#if defined(HAVE_WIDECHAR) if (!(flags & TT_FL_ASCII) && !strcmp(nl_langinfo(CODESET), "UTF-8")) tb->symbols = &utf8_tt_symbols; else diff --git a/misc-utils/Makefile.am b/misc-utils/Makefile.am index 6a16f999..794b8818 100644 --- a/misc-utils/Makefile.am +++ b/misc-utils/Makefile.am @@ -60,6 +60,9 @@ dist_man_MANS += findmnt.8 findmnt_LDADD = $(ul_libmount_la) findmnt_CFLAGS = $(AM_CFLAGS) -I$(ul_libmount_incdir) findmnt_SOURCES = findmnt.c $(top_srcdir)/lib/tt.c +if !HAVE_LANGINFO +findmnt_SOURCES += $(top_srcdir)/lib/langinfo.c +endif endif cal_SOURCES = cal.c $(top_srcdir)/lib/mbsalign.c diff --git a/misc-utils/findmnt.c b/misc-utils/findmnt.c index b1fb90a4..0e3cc376 100644 --- a/misc-utils/findmnt.c +++ b/misc-utils/findmnt.c @@ -26,9 +26,6 @@ #include #include #include -#ifdef HAVE_LANGINFO_H -#include -#endif #ifdef HAVE_SYS_IOCTL_H #include #endif -- cgit v1.2.3 From 2a6fd10e02ca8929e70f8dbf95f04630698f9499 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 15 Nov 2010 16:48:03 +0100 Subject: cal: follow HAVE_LANGINFO Signed-off-by: Karel Zak --- misc-utils/Makefile.am | 3 +++ misc-utils/cal.c | 23 +++-------------------- 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/misc-utils/Makefile.am b/misc-utils/Makefile.am index 794b8818..aed8bac8 100644 --- a/misc-utils/Makefile.am +++ b/misc-utils/Makefile.am @@ -66,6 +66,9 @@ endif endif cal_SOURCES = cal.c $(top_srcdir)/lib/mbsalign.c +if !HAVE_LANGINFO +cal_SOURCES += $(top_srcdir)/lib/langinfo.c +endif if HAVE_TINFO cal_LDADD = -ltinfo @NCURSES_LIBS@ else diff --git a/misc-utils/cal.c b/misc-utils/cal.c index 4d46c1b1..896c4533 100644 --- a/misc-utils/cal.c +++ b/misc-utils/cal.c @@ -141,10 +141,6 @@ const char *Senter="", *Sexit="";/* enter and exit standout mode */ int Slen; /* strlen of Senter+Sexit */ char *Hrow; /* pointer to highlighted row in month */ -#ifdef HAVE_LANGINFO_H -# include -#endif - #include "widechar.h" /* allow compile-time define to over-ride default */ @@ -409,12 +405,6 @@ void headers_init(void) strcpy(day_headings,""); strcpy(j_day_headings,""); -#ifdef HAVE_LANGINFO_H -# define weekday(wd) nl_langinfo(ABDAY_1+wd) -#else -# define weekday(wd) _time_info->abbrev_wkday[wd] -#endif - for(i = 0 ; i < 7 ; i++ ) { ssize_t space_left; wd = (i + weekstart) % 7; @@ -424,25 +414,18 @@ void headers_init(void) space_left = sizeof(day_headings) - (cur_dh - day_headings); if(space_left <= 2) break; - cur_dh += center_str(weekday(wd), cur_dh, space_left, 2); + cur_dh += center_str(nl_langinfo(ABDAY_1+wd), cur_dh, space_left, 2); if (i) strcat(cur_j_dh++, " "); space_left = sizeof(j_day_headings) - (cur_j_dh - j_day_headings); if(space_left <= 3) break; - cur_j_dh += center_str(weekday(wd), cur_j_dh, space_left, 3); + cur_j_dh += center_str(nl_langinfo(ABDAY_1+wd), cur_j_dh, space_left, 3); } -#undef weekday - - for (i = 0; i < 12; i++) { -#ifdef HAVE_LANGINFO_H + for (i = 0; i < 12; i++) full_month[i] = nl_langinfo(MON_1+i); -#else - full_month[i] = _time_info->full_month[i]; -#endif - } } void -- cgit v1.2.3 From efcf9a9d1e24789d83976e07c581b0be2f54340a Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 15 Nov 2010 16:48:27 +0100 Subject: agetty: use nl_langinfo() Signed-off-by: Karel Zak --- login-utils/Makefile.am | 4 ++++ login-utils/agetty.c | 12 +++--------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/login-utils/Makefile.am b/login-utils/Makefile.am index 9ebd0b7c..c5e3d52f 100644 --- a/login-utils/Makefile.am +++ b/login-utils/Makefile.am @@ -11,6 +11,10 @@ EXTRA_DIST = README.getty README.modems-with-agetty README.poeigl if BUILD_AGETTY sbin_PROGRAMS += agetty dist_man_MANS += agetty.8 +agetty_SOURCES = agetty.c +if !HAVE_LANGINFO +agetty_SOURCES += $(top_srcdir)/lib/langinfo.c +endif endif if BUILD_INIT diff --git a/login-utils/agetty.c b/login-utils/agetty.c index 9d463ce4..f048c3e4 100644 --- a/login-utils/agetty.c +++ b/login-utils/agetty.c @@ -910,12 +910,6 @@ do_prompt(op, tp) case 'd': case 't': { - /* TODO: use nl_langinfo() */ - char *weekday[] = { "Sun", "Mon", "Tue", "Wed", "Thu", - "Fri", "Sat" }; - char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", - "Jun", "Jul", "Aug", "Sep", "Oct", - "Nov", "Dec" }; time_t now; struct tm *tm; @@ -924,14 +918,14 @@ do_prompt(op, tp) if (c == 'd') (void) printf ("%s %s %d %d", - weekday[tm->tm_wday], month[tm->tm_mon], - tm->tm_mday, + nl_langinfo(ABDAY_1 + tm->tm_wday), + nl_langinfo(ABMON_1 + tm->tm_mon), + tm->tm_mday, tm->tm_year < 70 ? tm->tm_year + 2000 : tm->tm_year + 1900); else (void) printf ("%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); - break; } -- cgit v1.2.3 From d50da32777d88d0c1f25e3a131409302bef846ff Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 16 Nov 2010 10:17:02 +0100 Subject: mount: update relatime description in mount.8 Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=653705 Signed-off-by: Karel Zak --- mount/mount.8 | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/mount/mount.8 b/mount/mount.8 index a6566b00..8b09de86 100644 --- a/mount/mount.8 +++ b/mount/mount.8 @@ -907,6 +907,15 @@ time is only updated if the previous access time was earlier than the current modify or change time. (Similar to noatime, but doesn't break mutt or other applications that need to know if a file has been read since the last time it was modified.) + +Since Linux 2.6.30, the kernel defaults to the behavior provided by this +option (unless +.B noatime +was specified), and the +.B strictatime +option is required to obtain traditional semantics. In addition, since Linux +2.6.30, the file's last access time is always updated if it is more than 1 +day old. .TP .B norelatime Do not use -- cgit v1.2.3 From 81a12d11efc8d0db248f3bbdb21acd58a0651262 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Fri, 19 Nov 2010 13:37:25 +0100 Subject: mount: ignore *context= options on remount Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=563267 Signed-off-by: Karel Zak --- mount/mount.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/mount/mount.c b/mount/mount.c index 1c8a55fd..c0023f39 100644 --- a/mount/mount.c +++ b/mount/mount.c @@ -378,6 +378,56 @@ append_context(const char *optname, char *optdata, char **extra_opts) freecon(raw); return 0; } + +/* returns newly allocated string without *context= options */ +static char *remove_context_options(char *opts) +{ + char *begin = NULL, *end = NULL, *p; + int open_quote = 0, changed = 0; + + if (!opts) + return NULL; + + opts = xstrdup(opts); + + for (p = opts; p && *p; p++) { + if (!begin) + begin = p; /* begin of the option item */ + if (*p == '"') + open_quote ^= 1; /* reverse the status */ + if (open_quote) + continue; /* still in quoted block */ + if (*p == ',') + end = p; /* terminate the option item */ + else if (*(p + 1) == '\0') + end = p + 1; /* end of optstr */ + if (!begin || !end) + continue; + + if (strncmp(begin, "context=", 8) == 0 || + strncmp(begin, "fscontext=", 10) == 0 || + strncmp(begin, "defcontext=", 11) == 0 || + strncmp(begin, "rootcontext=", 12) == 0) { + size_t sz; + + if ((begin == opts || *(begin - 1) == ',') && *end == ',') + end++; + sz = strlen(end); + + memmove(begin, end, sz + 1); + if (!*begin && *(begin - 1) == ',') + *(begin - 1) = '\0'; + + p = begin; + changed = 1; + } + } + + if (changed && verbose) + printf (_("mount: SELinux *context= options are ignore on remount.\n")); + + return opts; +} #endif /* @@ -1382,6 +1432,7 @@ try_mount_one (const char *spec0, const char *node0, const char *types0, parse_opts (opts, &flags, &extra_opts); extra_opts1 = extra_opts; + mount_opts = extra_opts; /* quietly succeed for fstab entries that don't get mounted automatically */ if (mount_all && (flags & MS_NOAUTO)) @@ -1397,8 +1448,6 @@ try_mount_one (const char *spec0, const char *node0, const char *types0, "%s is already mounted on %s\n"), spec, node); - mount_opts = extra_opts; - if (opt_speed) cdrom_setspeed(spec); @@ -1419,12 +1468,17 @@ try_mount_one (const char *spec0, const char *node0, const char *types0, if (flags & (MS_BIND | MS_MOVE | MS_PROPAGATION)) types = "none"; +#ifdef HAVE_LIBSELINUX + if ((flags & MS_REMOUNT) && mount_opts) + mount_opts = remove_context_options(mount_opts); +#endif + /* * Call mount.TYPE for types that require a separate mount program. * For the moment these types are ncpfs and smbfs. Maybe also vxfs. * All such special things must occur isolated in the types string. */ - if (check_special_mountprog(spec, node, types, flags, extra_opts, &status)) { + if (check_special_mountprog(spec, node, types, flags, mount_opts, &status)) { res = status; goto out; } @@ -1718,6 +1772,8 @@ try_mount_one (const char *spec0, const char *node0, const char *types0, } #endif + if (extra_opts1 != mount_opts) + my_free(mount_opts); my_free(extra_opts1); my_free(spec1); my_free(node1); -- cgit v1.2.3 From cf59b09c1e7c520b96295058c10acea1dbeee671 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 23 Nov 2010 19:42:33 +0100 Subject: mount: mark die() as nonreturn Signed-off-by: Karel Zak --- mount/sundries.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mount/sundries.c b/mount/sundries.c index 98f46949..4cf30899 100644 --- a/mount/sundries.c +++ b/mount/sundries.c @@ -115,7 +115,7 @@ error (const char *fmt, ...) { } /* Fatal error. Print message and exit. */ -void + __attribute__ ((noreturn)) void die(int err, const char *fmt, ...) { va_list args; -- cgit v1.2.3 From e8fc977aba09ddbd89b25276fd777c3f0eef9299 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 23 Nov 2010 19:49:58 +0100 Subject: libblkid: cache is incorrectly revalidated for example: # echo "password" | cryptsetup luksFormat /dev/loop7 # blkid /dev/loop7 /dev/loop7: UUID="09240a80-1cf1-456d-9a6e-a35b39dc1f2b" TYPE="crypto_LUKS" # pvcreate -ff /dev/loop7 # blkid /dev/loop7 # the second blkid call has to return info about LVM. Reported-by: Milan Broz Signed-off-by: Karel Zak --- shlibs/blkid/src/blkidP.h | 2 +- shlibs/blkid/src/probe.c | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/shlibs/blkid/src/blkidP.h b/shlibs/blkid/src/blkidP.h index 6ac8910c..956a84e2 100644 --- a/shlibs/blkid/src/blkidP.h +++ b/shlibs/blkid/src/blkidP.h @@ -437,7 +437,7 @@ extern size_t blkid_rtrim_whitespace(unsigned char *str); ((bmp)[ blkid_bmp_idx_byte(item) ] |= blkid_bmp_idx_bit(item)) #define blkid_bmp_unset_item(bmp, item) \ - ((bmp)[ bmp_idx_byte(item) ] &= ~bmp_idx_bit(item)) + ((bmp)[ blkid_bmp_idx_byte(item) ] &= ~blkid_bmp_idx_bit(item)) #define blkid_bmp_get_item(bmp, item) \ ((bmp)[ blkid_bmp_idx_byte(item) ] & blkid_bmp_idx_bit(item)) diff --git a/shlibs/blkid/src/probe.c b/shlibs/blkid/src/probe.c index 3698b99b..33e2fe13 100644 --- a/shlibs/blkid/src/probe.c +++ b/shlibs/blkid/src/probe.c @@ -431,14 +431,13 @@ int __blkid_probe_invert_filter(blkid_probe pr, int chain) struct blkid_chain *chn; unsigned long *fltr; - fltr = blkid_probe_get_filter(pr, chain, FALSE); - if (!fltr) - return -1; - chn = &pr->chains[chain]; + if (!chn->driver->has_fltr || !chn->fltr) + return -1; + for (i = 0; i < blkid_bmp_nwords(chn->driver->nidinfos); i++) - fltr[i] = ~fltr[i]; + chn->fltr[i] = ~chn->fltr[i]; DBG(DEBUG_LOWPROBE, printf("probing filter inverted\n")); /* blkid_probe_dump_filter(pr, chain); */ -- cgit v1.2.3 From 8abcf2900297c6d53ead867c42f7c1688e8d52ca Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Tue, 16 Nov 2010 10:47:35 -0300 Subject: lib: [strutils] general purpose string handling functions This patch replaces a few functions used throughout the source: * Renames getnum (from schedutils) to strtol_or_err * Moves strtosize (from lib/strtosize.c) * Moves xstrncpy (from include/xstrncpy.h) * Adds strnlen, strnchr and strndup if not available (remove it from libmount utils) A few Makefile.am files were modified to compile accordingly along with trivial renaming in schedutils source code. Signed-off-by: Davidlohr Bueso --- disk-utils/mkswap.c | 2 +- disk-utils/swaplabel.c | 2 +- fdisk/cfdisk.c | 2 +- include/Makefile.am | 5 +- include/strtosize.h | 8 -- include/strutils.h | 26 +++++++ include/xstrncpy.h | 8 -- lib/Makefile.am | 3 +- lib/strtosize.c | 148 ------------------------------------ lib/strutils.c | 186 ++++++++++++++++++++++++++++++++++++++++++++++ login-utils/agetty.c | 2 +- login-utils/checktty.c | 2 +- login-utils/chfn.c | 2 +- login-utils/login.c | 2 +- login-utils/shutdown.c | 2 +- login-utils/simpleinit.c | 2 +- login-utils/vipw.c | 2 +- login-utils/wall.c | 2 +- misc-utils/Makefile.am | 4 +- misc-utils/blkid.c | 2 +- misc-utils/wipefs.c | 2 +- mount/Makefile.am | 6 +- mount/lomount.c | 4 +- mount/mount.c | 2 +- mount/umount.c | 2 +- schedutils/Makefile.am | 2 +- schedutils/chrt.c | 6 +- schedutils/ionice.c | 12 +-- schedutils/schedutils.c | 34 --------- schedutils/schedutils.h | 7 -- schedutils/taskset.c | 4 +- shlibs/mount/src/mountP.h | 9 --- shlibs/mount/src/utils.c | 39 ---------- sys-utils/Makefile.am | 2 +- sys-utils/fallocate.c | 2 +- text-utils/more.c | 2 +- 36 files changed, 252 insertions(+), 295 deletions(-) delete mode 100644 include/strtosize.h create mode 100644 include/strutils.h delete mode 100644 include/xstrncpy.h delete mode 100644 lib/strtosize.c create mode 100644 lib/strutils.c delete mode 100644 schedutils/schedutils.c delete mode 100644 schedutils/schedutils.h diff --git a/disk-utils/mkswap.c b/disk-utils/mkswap.c index 246b8dd7..3d14a42e 100644 --- a/disk-utils/mkswap.c +++ b/disk-utils/mkswap.c @@ -48,7 +48,7 @@ #include "linux_version.h" #include "swapheader.h" -#include "xstrncpy.h" +#include "strutils.h" #include "nls.h" #include "blkdev.h" #include "pathnames.h" diff --git a/disk-utils/swaplabel.c b/disk-utils/swaplabel.c index 63419722..9dc20b49 100644 --- a/disk-utils/swaplabel.c +++ b/disk-utils/swaplabel.c @@ -33,7 +33,7 @@ #include "c.h" #include "writeall.h" #include "swapheader.h" -#include "xstrncpy.h" +#include "strutils.h" #include "nls.h" #define SWAP_UUID_OFFSET (offsetof(struct swap_header_v1_2, uuid)) diff --git a/fdisk/cfdisk.c b/fdisk/cfdisk.c index 149a6166..1e078a9f 100644 --- a/fdisk/cfdisk.c +++ b/fdisk/cfdisk.c @@ -99,7 +99,7 @@ #include "nls.h" #include "blkdev.h" -#include "xstrncpy.h" +#include "strutils.h" #include "common.h" #include "gpt.h" #include "mbsalign.h" diff --git a/include/Makefile.am b/include/Makefile.am index 3b93acd0..c7b3c20d 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -20,11 +20,10 @@ dist_noinst_HEADERS = \ nls.h \ pathnames.h \ setproctitle.h \ - strtosize.h \ + strutils.h \ swapheader.h \ tt.h \ usleep.h \ wholedisk.h \ widechar.h \ - writeall.h \ - xstrncpy.h + writeall.h diff --git a/include/strtosize.h b/include/strtosize.h deleted file mode 100644 index c789df93..00000000 --- a/include/strtosize.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef UTIL_LINUX_STRTOSIZE -#define UTIL_LINUX_STRTOSIZE - -#include - -extern int strtosize(const char *str, uintmax_t *res); - -#endif /* UTIL_LINUX_STRING_TO_NUMBE */ diff --git a/include/strutils.h b/include/strutils.h new file mode 100644 index 00000000..e24496d3 --- /dev/null +++ b/include/strutils.h @@ -0,0 +1,26 @@ +#ifndef UTIL_LINUX_STRUTILS +#define UTIL_LINUX_STRUTILS + +#include +#include + +extern int strtosize(const char *str, uintmax_t *res); +extern long strtol_or_err(const char *str, const char *errmesg); + +#ifndef HAVE_STRNLEN +extern size_t strnlen(const char *s, size_t maxlen); +#endif +#ifndef HAVE_STRNDUP +extern char *strndup(const char *s, size_t n); +#endif +#ifndef HAVE_STRNCHR +extern char *strnchr(const char *s, size_t maxlen, int c); +#endif + +/* caller guarantees n > 0 */ +static inline void xstrncpy(char *dest, const char *src, size_t n) +{ + strncpy(dest, src, n-1); + dest[n-1] = 0; +} +#endif diff --git a/include/xstrncpy.h b/include/xstrncpy.h deleted file mode 100644 index 7ed4109d..00000000 --- a/include/xstrncpy.h +++ /dev/null @@ -1,8 +0,0 @@ -/* NUL-terminated version of strncpy() */ -#include - -/* caller guarantees n > 0 */ -static inline void xstrncpy(char *dest, const char *src, size_t n) { - strncpy(dest, src, n-1); - dest[n-1] = 0; -} diff --git a/lib/Makefile.am b/lib/Makefile.am index 45d319d3..9a3bf35b 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -3,7 +3,7 @@ include $(top_srcdir)/config/include-Makefile.am AM_CPPFLAGS += -DTEST_PROGRAM noinst_PROGRAMS = test_blkdev test_ismounted test_wholedisk test_mangle \ - test_strtosize test_tt test_canonicalize + test_tt test_canonicalize if LINUX if HAVE_CPU_SET_T noinst_PROGRAMS += test_cpuset @@ -14,7 +14,6 @@ test_blkdev_SOURCES = blkdev.c test_ismounted_SOURCES = ismounted.c test_wholedisk_SOURCES = wholedisk.c test_mangle_SOURCES = mangle.c -test_strtosize_SOURCES = strtosize.c if LINUX test_cpuset_SOURCES = cpuset.c endif diff --git a/lib/strtosize.c b/lib/strtosize.c deleted file mode 100644 index 068c5429..00000000 --- a/lib/strtosize.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * strtosize() - convert string to size (uintmax_t). - * - * Supported suffixes: - * - * XiB or X for 2^N - * where X = {K,M,G,T,P,E,Y,Z} - * or X = {k,m,g,t,p,e} (undocumented for backward compatibility only) - * for example: - * 10KiB = 10240 - * 10K = 10240 - * - * XB for 10^N - * where X = {K,M,G,T,P,E,Y,Z} - * for example: - * 10KB = 10000 - * - * Note that the function does not accept numbers with '-' (negative sign) - * prefix. - * - * Returns 0 on success, -1 in case of error, -2 in case of overflow. - * - * Copyright (C) 2010 Karel Zak - */ -#include -#include -#include -#include - -static int do_scale_by_power (uintmax_t *x, int base, int power) -{ - while (power--) { - if (UINTMAX_MAX / base < *x) - return -2; - *x *= base; - } - return 0; -} - -int strtosize(const char *str, uintmax_t *res) -{ - char *p; - uintmax_t x; - int base = 1024, rc = 0; - - *res = 0; - - if (!str || !*str) - goto err; - - /* Only positive numbers are acceptable - * - * Note that this check is not perfect, it would be better to - * use lconv->negative_sign. But coreutils use the same solution, - * so it's probably good enough... - */ - p = (char *) str; - while (isspace((unsigned char) *p)) - p++; - if (*p == '-') - goto err; - p = NULL; - - errno = 0; - x = strtoumax(str, &p, 0); - - if (p == str || - (errno != 0 && (x == UINTMAX_MAX || x == 0))) - goto err; - - if (!p || !*p) - goto done; /* without suffix */ - - /* - * Check size suffixes - */ - if (*(p + 1) == 'i' && *(p + 2) == 'B' && !*(p + 3)) - base = 1024; /* XiB, 2^N */ - else if (*(p + 1) == 'B' && !*(p + 2)) - base = 1000; /* XB, 10^N */ - else if (*(p + 1)) - goto err; /* unexpected suffix */ - - switch(*p) { - case 'K': - case 'k': - rc = do_scale_by_power(&x, base, 1); - break; - case 'M': - case 'm': - rc = do_scale_by_power(&x, base, 2); - break; - case 'G': - case 'g': - rc = do_scale_by_power(&x, base, 3); - break; - case 'T': - case 't': - rc = do_scale_by_power(&x, base, 4); - break; - case 'P': - case 'p': - rc = do_scale_by_power(&x, base, 5); - break; - case 'E': - case 'e': - rc = do_scale_by_power(&x, base, 6); - break; - case 'Z': - rc = do_scale_by_power(&x, base, 7); - break; - case 'Y': - rc = do_scale_by_power(&x, base, 8); - break; - default: - goto err; - } - -done: - *res = x; - return rc; -err: - return -1; -} - -#ifdef TEST_PROGRAM - -#include -#include -#include - -int main(int argc, char *argv[]) -{ - uintmax_t size = 0; - - if (argc < 2) { - fprintf(stderr, "usage: %s [suffix]\n", argv[0]); - exit(EXIT_FAILURE); - } - - if (strtosize(argv[1], &size)) - errx(EXIT_FAILURE, "invalid size '%s' value", argv[1]); - - printf("%25s : %20ju\n", argv[1], size); - return EXIT_FAILURE; -} -#endif /* TEST_PROGRAM */ - diff --git a/lib/strutils.c b/lib/strutils.c new file mode 100644 index 00000000..f394800d --- /dev/null +++ b/lib/strutils.c @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2010 Karel Zak + * Copyright (C) 2010 Davidlohr Bueso + */ + +#include +#include +#include +#include +#include + +static int do_scale_by_power (uintmax_t *x, int base, int power) +{ + while (power--) { + if (UINTMAX_MAX / base < *x) + return -2; + *x *= base; + } + return 0; +} + +/* + * strtosize() - convert string to size (uintmax_t). + * + * Supported suffixes: + * + * XiB or X for 2^N + * where X = {K,M,G,T,P,E,Y,Z} + * or X = {k,m,g,t,p,e} (undocumented for backward compatibility only) + * for example: + * 10KiB = 10240 + * 10K = 10240 + * + * XB for 10^N + * where X = {K,M,G,T,P,E,Y,Z} + * for example: + * 10KB = 10000 + * + * Note that the function does not accept numbers with '-' (negative sign) + * prefix. + */ +int strtosize(const char *str, uintmax_t *res) +{ + char *p; + uintmax_t x; + int base = 1024, rc = 0; + + *res = 0; + + if (!str || !*str) + goto err; + + /* Only positive numbers are acceptable + * + * Note that this check is not perfect, it would be better to + * use lconv->negative_sign. But coreutils use the same solution, + * so it's probably good enough... + */ + p = (char *) str; + while (isspace((unsigned char) *p)) + p++; + if (*p == '-') + goto err; + p = NULL; + + errno = 0; + x = strtoumax(str, &p, 0); + + if (p == str || + (errno != 0 && (x == UINTMAX_MAX || x == 0))) + goto err; + + if (!p || !*p) + goto done; /* without suffix */ + + /* + * Check size suffixes + */ + if (*(p + 1) == 'i' && *(p + 2) == 'B' && !*(p + 3)) + base = 1024; /* XiB, 2^N */ + else if (*(p + 1) == 'B' && !*(p + 2)) + base = 1000; /* XB, 10^N */ + else if (*(p + 1)) + goto err; /* unexpected suffix */ + + switch(*p) { + case 'K': + case 'k': + rc = do_scale_by_power(&x, base, 1); + break; + case 'M': + case 'm': + rc = do_scale_by_power(&x, base, 2); + break; + case 'G': + case 'g': + rc = do_scale_by_power(&x, base, 3); + break; + case 'T': + case 't': + rc = do_scale_by_power(&x, base, 4); + break; + case 'P': + case 'p': + rc = do_scale_by_power(&x, base, 5); + break; + case 'E': + case 'e': + rc = do_scale_by_power(&x, base, 6); + break; + case 'Z': + rc = do_scale_by_power(&x, base, 7); + break; + case 'Y': + rc = do_scale_by_power(&x, base, 8); + break; + default: + goto err; + } + +done: + *res = x; + return rc; +err: + return -1; +} + +#ifndef HAVE_STRNLEN +size_t strnlen(const char *s, size_t maxlen) +{ + int i; + + for (i = 0; i < maxlen; i++) { + if (s[i] == '\0') + return i + 1; + } + return maxlen; +} +#endif + +#ifndef HAVE_STRNCHR +char *strnchr(const char *s, size_t maxlen, int c) +{ + for (; maxlen-- && *s != '\0'; ++s) + if (*s == (char)c) + return (char *)s; + return NULL; +} +#endif + +#ifndef HAVE_STRNDUP +char *strndup(const char *s, size_t n) +{ + size_t len = strnlen(s, n); + char *new = (char *) malloc((len + 1) * sizeof(char)); + if (!new) + return NULL; + new[len] = '\0'; + return (char *) memcpy(new, s, len); +} +#endif + +/* + * same as strtol(3) but exit on failure instead of returning crap + */ +long strtol_or_err(const char *str, const char *errmesg) +{ + long num; + char *end = NULL; + + if (str == NULL || *str == '\0') + goto err; + errno = 0; + num = strtol(str, &end, 10); + + if (errno || (end && *end)) + goto err; + + return num; +err: + if (errno) + err(EXIT_FAILURE, "%s: '%s'", errmesg, str); + else + errx(EXIT_FAILURE, "%s: '%s'", errmesg, str); + return 0; +} diff --git a/login-utils/agetty.c b/login-utils/agetty.c index f048c3e4..b1cfa5a5 100644 --- a/login-utils/agetty.c +++ b/login-utils/agetty.c @@ -32,7 +32,7 @@ #include #include -#include "xstrncpy.h" +#include "strutils.h" #include "nls.h" #include "pathnames.h" diff --git a/login-utils/checktty.c b/login-utils/checktty.c index c28ee833..92bebfb7 100644 --- a/login-utils/checktty.c +++ b/login-utils/checktty.c @@ -31,7 +31,7 @@ #include "pathnames.h" #include "login.h" -#include "xstrncpy.h" +#include "strutils.h" #ifndef TTY_MAJOR #define TTY_MAJOR 4 diff --git a/login-utils/chfn.c b/login-utils/chfn.c index 691c4f6f..ef0a746d 100644 --- a/login-utils/chfn.c +++ b/login-utils/chfn.c @@ -36,7 +36,7 @@ #include "my_crypt.h" #include "islocal.h" #include "setpwnam.h" -#include "xstrncpy.h" +#include "strutils.h" #include "nls.h" #include "env.h" diff --git a/login-utils/login.c b/login-utils/login.c index 1550388c..68eb84bc 100644 --- a/login-utils/login.c +++ b/login-utils/login.c @@ -113,7 +113,7 @@ #include "pathnames.h" #include "my_crypt.h" #include "login.h" -#include "xstrncpy.h" +#include "strutils.h" #include "nls.h" diff --git a/login-utils/shutdown.c b/login-utils/shutdown.c index 0078df2d..172113c7 100644 --- a/login-utils/shutdown.c +++ b/login-utils/shutdown.c @@ -74,7 +74,7 @@ #include #include "linux_reboot.h" #include "pathnames.h" -#include "xstrncpy.h" +#include "strutils.h" #include "nls.h" #include "usleep.h" diff --git a/login-utils/simpleinit.c b/login-utils/simpleinit.c index 8cff848c..9277a3cc 100644 --- a/login-utils/simpleinit.c +++ b/login-utils/simpleinit.c @@ -45,7 +45,7 @@ #include "my_crypt.h" #include "pathnames.h" #include "linux_reboot.h" -#include "xstrncpy.h" +#include "strutils.h" #include "nls.h" #include "simpleinit.h" diff --git a/login-utils/vipw.c b/login-utils/vipw.c index b3972f3b..e7247e42 100644 --- a/login-utils/vipw.c +++ b/login-utils/vipw.c @@ -64,7 +64,7 @@ static char version_string[] = "vipw 1.4"; #include #include "setpwnam.h" -#include "xstrncpy.h" +#include "strutils.h" #include "nls.h" #ifdef HAVE_LIBSELINUX diff --git a/login-utils/wall.c b/login-utils/wall.c index 7b5f6718..38c54426 100644 --- a/login-utils/wall.c +++ b/login-utils/wall.c @@ -58,7 +58,7 @@ #include #include "nls.h" -#include "xstrncpy.h" +#include "strutils.h" #include "ttymsg.h" #include "pathnames.h" #include "carefulputc.h" diff --git a/misc-utils/Makefile.am b/misc-utils/Makefile.am index aed8bac8..76b69fa4 100644 --- a/misc-utils/Makefile.am +++ b/misc-utils/Makefile.am @@ -37,12 +37,12 @@ if BUILD_LIBBLKID sbin_PROGRAMS += blkid findfs wipefs dist_man_MANS += blkid.8 findfs.8 wipefs.8 blkid_SOURCES = blkid.c $(top_srcdir)/lib/ismounted.c \ - $(top_srcdir)/lib/strtosize.c + $(top_srcdir)/lib/strutils.c blkid_LDADD = $(ul_libblkid_la) blkid_CFLAGS = $(AM_CFLAGS) -I$(ul_libblkid_incdir) findfs_LDADD = $(ul_libblkid_la) findfs_CFLAGS = $(AM_CFLAGS) -I$(ul_libblkid_incdir) -wipefs_SOURCES = wipefs.c $(top_srcdir)/lib/strtosize.c +wipefs_SOURCES = wipefs.c $(top_srcdir)/lib/strutils.c wipefs_LDADD = $(ul_libblkid_la) wipefs_CFLAGS = $(AM_CFLAGS) -I$(ul_libblkid_incdir) if HAVE_STATIC_BLKID diff --git a/misc-utils/blkid.c b/misc-utils/blkid.c index f94df06a..2f7860fd 100644 --- a/misc-utils/blkid.c +++ b/misc-utils/blkid.c @@ -41,7 +41,7 @@ extern int optind; #include #include "ismounted.h" -#include "strtosize.h" +#include "strutils.h" const char *progname = "blkid"; diff --git a/misc-utils/wipefs.c b/misc-utils/wipefs.c index dbfabc4a..2f223f0c 100644 --- a/misc-utils/wipefs.c +++ b/misc-utils/wipefs.c @@ -35,7 +35,7 @@ #include "nls.h" #include "xalloc.h" -#include "strtosize.h" +#include "strutils.h" struct wipe_desc { loff_t offset; /* magic string offset */ diff --git a/mount/Makefile.am b/mount/Makefile.am index 235cceb0..36b06e32 100644 --- a/mount/Makefile.am +++ b/mount/Makefile.am @@ -28,12 +28,12 @@ cflags_common = $(AM_CFLAGS) ldflags_static = -all-static mount_SOURCES = mount.c $(srcs_mount) $(top_srcdir)/lib/setproctitle.c \ - $(top_srcdir)/lib/strtosize.c + $(top_srcdir)/lib/strutils.c mount_CFLAGS = $(SUID_CFLAGS) $(cflags_common) mount_LDFLAGS = $(SUID_LDFLAGS) $(AM_LDFLAGS) mount_LDADD = $(ldadd_common) -umount_SOURCES = umount.c $(srcs_mount) $(top_srcdir)/lib/strtosize.c +umount_SOURCES = umount.c $(srcs_mount) $(top_srcdir)/lib/strutils.c umount_CFLAGS = $(SUID_CFLAGS) $(cflags_common) umount_LDFLAGS = $(SUID_LDFLAGS) $(AM_LDFLAGS) umount_LDADD = $(ldadd_common) @@ -45,7 +45,7 @@ swapon_CFLAGS = $(cflags_common) swapon_LDADD = $(ldadd_common) losetup_SOURCES = lomount.c $(srcs_common) loop.h lomount.h \ - $(top_srcdir)/lib/strtosize.c + $(top_srcdir)/lib/strutils.c losetup_CPPFLAGS = -DMAIN $(AM_CPPFLAGS) mount_static_LDADD = diff --git a/mount/lomount.c b/mount/lomount.c index 03aae4b2..d6556fc7 100644 --- a/mount/lomount.c +++ b/mount/lomount.c @@ -18,7 +18,7 @@ #include "loop.h" #include "lomount.h" -#include "xstrncpy.h" +#include "strutils.h" #include "nls.h" #include "sundries.h" #include "xmalloc.h" @@ -886,7 +886,7 @@ find_unused_loop_device (void) { #include #include -#include "strtosize.h" +#include "strutils.h" static void usage(FILE *f) { diff --git a/mount/mount.c b/mount/mount.c index c0023f39..9faa6a5b 100644 --- a/mount/mount.c +++ b/mount/mount.c @@ -41,7 +41,7 @@ #include "env.h" #include "nls.h" #include "blkdev.h" -#include "strtosize.h" +#include "strutils.h" #define DO_PS_FIDDLING diff --git a/mount/umount.c b/mount/umount.c index b5ff8a17..6e24779b 100644 --- a/mount/umount.c +++ b/mount/umount.c @@ -20,7 +20,7 @@ #include "fstab.h" #include "env.h" #include "nls.h" -#include "strtosize.h" +#include "strutils.h" #if defined(MNT_FORCE) /* Interesting ... it seems libc knows about MNT_FORCE and presumably diff --git a/schedutils/Makefile.am b/schedutils/Makefile.am index c83e5eaf..dc331753 100644 --- a/schedutils/Makefile.am +++ b/schedutils/Makefile.am @@ -2,7 +2,7 @@ include $(top_srcdir)/config/include-Makefile.am if BUILD_SCHEDUTILS -srcs_common = schedutils.c schedutils.h +srcs_common = $(top_srcdir)/lib/strutils.c usrbin_exec_PROGRAMS = chrt dist_man_MANS = chrt.1 diff --git a/schedutils/chrt.c b/schedutils/chrt.c index 811eb200..bd7070cc 100644 --- a/schedutils/chrt.c +++ b/schedutils/chrt.c @@ -32,7 +32,7 @@ #include "c.h" #include "nls.h" -#include "schedutils.h" +#include "strutils.h" /* the SCHED_BATCH is supported since Linux 2.6.16 * -- temporary workaround for people with old glibc headers @@ -240,7 +240,7 @@ int main(int argc, char *argv[]) break; case 'p': errno = 0; - pid = getnum(argv[argc - 1], _("failed to parse pid")); + pid = strtol_or_err(argv[argc - 1], _("failed to parse pid")); break; case 'r': policy = SCHED_RR; @@ -268,7 +268,7 @@ int main(int argc, char *argv[]) } errno = 0; - priority = getnum(argv[optind], _("failed to parse priority")); + priority = strtol_or_err(argv[optind], _("failed to parse priority")); #ifdef SCHED_RESET_ON_FORK /* sanity check */ diff --git a/schedutils/ionice.c b/schedutils/ionice.c index 34132f07..78c9f0d3 100644 --- a/schedutils/ionice.c +++ b/schedutils/ionice.c @@ -18,7 +18,7 @@ #include "nls.h" -#include "schedutils.h" +#include "strutils.h" static int tolerant; @@ -105,15 +105,15 @@ int main(int argc, char *argv[]) while ((c = getopt(argc, argv, "+n:c:p:th")) != EOF) { switch (c) { case 'n': - ioprio = getnum(optarg, _("failed to parse class data")); + ioprio = strtol_or_err(optarg, _("failed to parse class data")); set |= 1; break; case 'c': - ioclass = getnum(optarg, _("failed to parse class")); + ioclass = strtol_or_err(optarg, _("failed to parse class")); set |= 2; break; case 'p': - pid = getnum(optarg, _("failed to parse pid")); + pid = strtol_or_err(optarg, _("failed to parse pid")); break; case 't': tolerant = 1; @@ -147,7 +147,7 @@ int main(int argc, char *argv[]) ioprio_print(pid); for(; argv[optind]; ++optind) { - pid = getnum(argv[optind], _("failed to parse pid")); + pid = strtol_or_err(argv[optind], _("failed to parse pid")); ioprio_print(pid); } } else { @@ -156,7 +156,7 @@ int main(int argc, char *argv[]) for(; argv[optind]; ++optind) { - pid = getnum(argv[optind], _("failed to parse pid")); + pid = strtol_or_err(argv[optind], _("failed to parse pid")); ioprio_setpid(pid, ioprio, ioclass); } } diff --git a/schedutils/schedutils.c b/schedutils/schedutils.c deleted file mode 100644 index 9d6051ba..00000000 --- a/schedutils/schedutils.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2010 Karel Zak - * - * Released under the terms of the GNU General Public License version 2 - * - */ -#include -#include -#include -#include - -#include "nls.h" - -long getnum(const char *str, const char *errmesg) -{ - long num; - char *end = NULL; - - if (str == NULL || *str == '\0') - goto err; - errno = 0; - num = strtol(str, &end, 10); - - if (errno || (end && *end)) - goto err; - - return num; -err: - if (errno) - err(EXIT_FAILURE, "%s: '%s'", errmesg, str); - else - errx(EXIT_FAILURE, "%s: '%s'", errmesg, str); - return 0; -} diff --git a/schedutils/schedutils.h b/schedutils/schedutils.h deleted file mode 100644 index 80e4f7bf..00000000 --- a/schedutils/schedutils.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef UTIL_LINUX_SCHED_UTILS -#define UTIL_LINUX_SCHED_UTILS - -extern long getnum(const char *str, const char *errmesg); - -#endif - diff --git a/schedutils/taskset.c b/schedutils/taskset.c index 201fc158..5a7557c3 100644 --- a/schedutils/taskset.c +++ b/schedutils/taskset.c @@ -32,7 +32,7 @@ #include "cpuset.h" #include "nls.h" -#include "schedutils.h" +#include "strutils.h" static void __attribute__((__noreturn__)) usage(FILE *out) { @@ -89,7 +89,7 @@ int main(int argc, char *argv[]) while ((opt = getopt_long(argc, argv, "+pchV", longopts, NULL)) != -1) { switch (opt) { case 'p': - pid = getnum(argv[argc - 1], _("failed to parse pid")); + pid = strtol_or_err(argv[argc - 1], _("failed to parse pid")); break; case 'c': c_opt = 1; diff --git a/shlibs/mount/src/mountP.h b/shlibs/mount/src/mountP.h index 6145b730..4a99bb4e 100644 --- a/shlibs/mount/src/mountP.h +++ b/shlibs/mount/src/mountP.h @@ -60,15 +60,6 @@ extern int mnt_run_test(struct mtest *tests, int argc, char *argv[]); /* utils.c */ extern char *mnt_getenv_safe(const char *arg); -#ifndef HAVE_STRNLEN -extern size_t strnlen(const char *s, size_t maxlen); -#endif -#ifndef HAVE_STRNDUP -extern char *strndup(const char *s, size_t n); -#endif -#ifndef HAVE_STRNCHR -extern char *strnchr(const char *s, size_t maxlen, int c); -#endif extern char *mnt_get_username(const uid_t uid); /* diff --git a/shlibs/mount/src/utils.c b/shlibs/mount/src/utils.c index 6133cdd7..a1ab50c0 100644 --- a/shlibs/mount/src/utils.c +++ b/shlibs/mount/src/utils.c @@ -51,45 +51,6 @@ char *mnt_getenv_safe(const char *arg) #endif } -/* TODO: move strn<...> functions to top-level lib/strn.c */ -#ifndef HAVE_STRNLEN -size_t strnlen(const char *s, size_t maxlen) -{ - int i; - - for (i = 0; i < maxlen; i++) { - if (s[i] == '\0') - return i + 1; - } - return maxlen; -} -#endif - -#ifndef HAVE_STRNCHR -char *strnchr(const char *s, size_t maxlen, int c) -{ - for (; maxlen-- && *s != '\0'; ++s) - if (*s == (char)c) - return (char *)s; - return NULL; -} -#endif - -#ifndef HAVE_STRNDUP -char *strndup(const char *s, size_t n) -{ - size_t len = strnlen (s, n); - char *new = (char *) malloc (len + 1); - - if (new == NULL) - return NULL; - - new[len] = '\0'; - return (char *) memcpy (new, s, len); -} -#endif - - /** * mnt_fstype_is_pseudofs: * @type: filesystem name diff --git a/sys-utils/Makefile.am b/sys-utils/Makefile.am index d2b85685..a45978e3 100644 --- a/sys-utils/Makefile.am +++ b/sys-utils/Makefile.am @@ -31,7 +31,7 @@ tunelp_SOURCES = tunelp.c lp.h if BUILD_FALLOCATE usrbin_exec_PROGRAMS += fallocate -fallocate_SOURCES = fallocate.c $(top_srcdir)/lib/strtosize.c +fallocate_SOURCES = fallocate.c $(top_srcdir)/lib/strutils.c dist_man_MANS += fallocate.1 endif diff --git a/sys-utils/fallocate.c b/sys-utils/fallocate.c index fd4d2a9a..9598cf10 100644 --- a/sys-utils/fallocate.c +++ b/sys-utils/fallocate.c @@ -44,7 +44,7 @@ #endif #include "nls.h" -#include "strtosize.h" +#include "strutils.h" static void __attribute__((__noreturn__)) usage(FILE *out) diff --git a/text-utils/more.c b/text-utils/more.c index 37520598..49df52e2 100644 --- a/text-utils/more.c +++ b/text-utils/more.c @@ -56,7 +56,7 @@ #include #include #include -#include "xstrncpy.h" +#include "strutils.h" #include "nls.h" #include "xalloc.h" -- cgit v1.2.3 From 779d6a1bfbb84a8a458eaac03a254e017c07e7cb Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 23 Nov 2010 21:10:48 +0100 Subject: docs: update TODO file Signed-off-by: Karel Zak --- TODO | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/TODO b/TODO index e827ac30..87a4a488 100644 --- a/TODO +++ b/TODO @@ -14,7 +14,7 @@ libblkid blkid(8) ------- - - add something like "blkid --list-all" to list all supported filesystems/raids + - add something like "blkid --list-known" to list all supported filesystems/raids - add a new option (-r) that allows to print removable block devices that are missing in /proc/partitions, see blkid_probe_all_removable(). @@ -56,7 +56,7 @@ fdisk(s) * fdisk/* refactoring - * add GPT support + * add GPT support (probably implement libfdisk) partx ----- @@ -144,9 +144,6 @@ misc try to mount all unmounted entries } while (not all mounted && at least one new was successfully mounted) - * agetty: use nl_langinfo() for days and months rather than hardcoded - English names. - * rewrite ipcs to use /proc/sys/kernel rather than unreliable syscalls (there are problems with 32bit userspace on 64bit kernel) -- cgit v1.2.3 From b79bd89b05ca3472b11394278b5af716f9914772 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 23 Nov 2010 21:14:48 +0100 Subject: libblkid: remove unused variable Signed-off-by: Karel Zak --- shlibs/blkid/src/probe.c | 1 - 1 file changed, 1 deletion(-) diff --git a/shlibs/blkid/src/probe.c b/shlibs/blkid/src/probe.c index 33e2fe13..0ef6f295 100644 --- a/shlibs/blkid/src/probe.c +++ b/shlibs/blkid/src/probe.c @@ -429,7 +429,6 @@ int __blkid_probe_invert_filter(blkid_probe pr, int chain) { int i; struct blkid_chain *chn; - unsigned long *fltr; chn = &pr->chains[chain]; -- cgit v1.2.3 From 8c9e72ce2b3dc8cbc9df446b8915ea936cb702b3 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Thu, 18 Nov 2010 21:03:02 +0100 Subject: lib: [ismounted] don't wast time with mtab is /proc/mounts used Signed-off-by: Karel Zak --- lib/ismounted.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/ismounted.c b/lib/ismounted.c index 592df308..f19d67b1 100644 --- a/lib/ismounted.c +++ b/lib/ismounted.c @@ -171,6 +171,10 @@ static int check_mntent(const char *file, int *mount_flags, mtpt, mtlen); if (retval == 0 && (*mount_flags != 0)) return 0; + if (access("/proc/mounts", R_OK) == 0) { + *mount_flags = 0; + return retval; + } #endif /* __linux__ */ #if defined(MOUNTED) || defined(_PATH_MOUNTED) #ifndef MOUNTED -- cgit v1.2.3 From 3e451589d5eaecfa8ddff46877f94ad79bc010f0 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Thu, 18 Nov 2010 21:04:13 +0100 Subject: lib: [tt] add TT_FL_RIGHT, add columns list parser Signed-off-by: Karel Zak --- include/tt.h | 8 +++++-- lib/tt.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 65 insertions(+), 11 deletions(-) diff --git a/include/tt.h b/include/tt.h index bf24d550..e6a63ed3 100644 --- a/include/tt.h +++ b/include/tt.h @@ -12,11 +12,12 @@ #include "list.h" enum { - TT_FL_TRUNCATE = (1 << 1), + TT_FL_TRUNC = (1 << 1), TT_FL_TREE = (1 << 2), TT_FL_RAW = (1 << 3), TT_FL_ASCII = (1 << 4), - TT_FL_NOHEADINGS = (1 << 5) + TT_FL_NOHEADINGS = (1 << 5), + TT_FL_RIGHT = (1 << 6), }; struct tt { @@ -68,4 +69,7 @@ extern struct tt_line *tt_add_line(struct tt *tb, struct tt_line *parent); extern int tt_line_set_data(struct tt_line *ln, int colnum, const char *data); +extern int tt_parse_columns_list(const char *list, int cols[], int *ncols, + int (name2id)(const char *, size_t)); + #endif /* UTIL_LINUX_TT_H */ diff --git a/lib/tt.c b/lib/tt.c index a4aabfe0..f371a93a 100644 --- a/lib/tt.c +++ b/lib/tt.c @@ -394,12 +394,16 @@ static void recount_widths(struct tt *tb, char *buf, size_t bufsz) struct tt_column *cl = list_entry(p, struct tt_column, cl_columns); - cl->width_min = mbs_width(cl->name); + if (cl->name) + cl->width_min = mbs_width(cl->name); if (cl->width < cl->width_min) cl->width = cl->width_min; + else if (cl->width_hint >= 1 && + cl->width < (int) cl->width_hint && cl->width_min < (int) cl->width_hint) + cl->width = (int) cl->width_hint; width += cl->width + (is_last_column(tb, cl) ? 0 : 1); @@ -412,7 +416,8 @@ static void recount_widths(struct tt *tb, char *buf, size_t bufsz) struct tt_column *cl = list_entry( tb->tb_columns.prev, struct tt_column, cl_columns); - cl->width += tb->termwidth - width; + if (!(cl->flags & TT_FL_RIGHT)) + cl->width += tb->termwidth - width; goto leave; } @@ -434,7 +439,7 @@ static void recount_widths(struct tt *tb, char *buf, size_t bufsz) continue; /* never truncate columns with absolute sizes */ if (cl->flags & TT_FL_TREE) continue; /* never truncate the tree */ - if (trunc_only && !(cl->flags & TT_FL_TRUNCATE)) + if (trunc_only && !(cl->flags & TT_FL_TRUNC)) continue; if (cl->width == cl->width_min) continue; @@ -458,7 +463,7 @@ leave: struct tt_column *cl = list_entry(p, struct tt_column, cl_columns); - fprintf(stderr, "width: %s=%d [%d]\n", + fprintf(stderr, "width: %s=%d [hint=%d]\n", cl->name, cl->width, cl->width_hint > 1 ? (int) cl->width_hint : (int) (cl->width_hint * tb->termwidth)); @@ -498,20 +503,28 @@ static void print_data(struct tt *tb, struct tt_column *cl, char *data) width = len; /* truncate data */ - if (len > width && (cl->flags & TT_FL_TRUNCATE)) { + if (len > width && (cl->flags & TT_FL_TRUNC)) { len = mbs_truncate(data, width); if (!data || len == (size_t) -1) { len = 0; data = NULL; } } - if (data) - fputs(data, stdout); + if (data) { + if (!(tb->flags & TT_FL_RAW) && (cl->flags & TT_FL_RIGHT)) { + int xw = cl->width; + fprintf(stdout, "%*s", xw, data); + if (len < xw) + len = xw; + } + else + fputs(data, stdout); + } for (i = len; i < width; i++) fputc(' ', stdout); /* padding */ if (!is_last_column(tb, cl)) { - if (len > width && !(cl->flags & TT_FL_TRUNCATE)) { + if (len > width && !(cl->flags & TT_FL_TRUNC)) { fputc('\n', stdout); for (i = 0; i <= cl->seqnum; i++) { struct tt_column *x = tt_get_column(tb, i); @@ -633,6 +646,43 @@ int tt_print_table(struct tt *tb) return 0; } +int tt_parse_columns_list(const char *list, int cols[], int *ncols, + int (name2id)(const char *, size_t)) +{ + const char *begin = NULL, *p; + + if (!list || !*list || !cols || !ncols || !name2id) + return -1; + + *ncols = 0; + + for (p = list; p && *p; p++) { + const char *end = NULL; + int id; + + if (!begin) + begin = p; /* begin of the column name */ + if (*p == ',') + end = p; /* terminate the name */ + if (*(p + 1) == '\0') + end = p + 1; /* end of string */ + if (!begin || !end) + continue; + if (end <= begin) + return -1; + + id = name2id(begin, end - begin); + if (id == -1) + return -1; + cols[ *ncols ] = id; + (*ncols)++; + begin = NULL; + if (end && !*end) + break; + } + return 0; +} + #ifdef TEST_PROGRAM #include #include @@ -666,7 +716,7 @@ int main(int argc, char *argv[]) err(EXIT_FAILURE, "table initialization failed"); tt_define_column(tb, "NAME", 0.3, notree ? 0 : TT_FL_TREE); - tt_define_column(tb, "FOO", 0.3, TT_FL_TRUNCATE); + tt_define_column(tb, "FOO", 0.3, TT_FL_TRUNC); tt_define_column(tb, "BAR", 0.3, 0); tt_define_column(tb, "PATH", 0.3, 0); -- cgit v1.2.3 From 9ead000613ea527f047597d2978ca605f1314418 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Thu, 18 Nov 2010 21:06:27 +0100 Subject: findmnt: apply new changes from tt.c Signed-off-by: Karel Zak --- misc-utils/findmnt.c | 58 +++++++++++++++------------------------------------- 1 file changed, 16 insertions(+), 42 deletions(-) diff --git a/misc-utils/findmnt.c b/misc-utils/findmnt.c index 0e3cc376..9d3547b1 100644 --- a/misc-utils/findmnt.c +++ b/misc-utils/findmnt.c @@ -190,46 +190,6 @@ static int column_name_to_id(const char *name, size_t namesz) return -1; } -/* - * parses list of columns from @str and add IDs to columns[] - */ -static int set_columns(const char *str) -{ - const char *begin = NULL, *p; - - ncolumns = 0; - - if (!str || !*str) - return -1; - - ncolumns = 0; - - for (p = str; p && *p; p++) { - const char *end = NULL; - int id; - - if (!begin) - begin = p; /* begin of the column name */ - if (*p == ',') - end = p; /* terminate the name */ - if (*(p + 1) == '\0') - end = p + 1; /* end of string */ - if (!begin || !end) - continue; - if (end <= begin) - return -1; - - id = column_name_to_id(begin, end - begin); - if (id == -1) - return -1; - columns[ ncolumns++ ] = id; - begin = NULL; - if (end && !*end) - break; - } - return 0; -} - /* Returns LABEL or UUID */ static const char *get_tag(mnt_fs *fs, const char *tagname) { @@ -446,6 +406,8 @@ again: static int __attribute__((__noreturn__)) usage(FILE *out) { + int i; + fprintf(out, _( "\nUsage:\n" " %1$s [options]\n" @@ -478,6 +440,17 @@ static int __attribute__((__noreturn__)) usage(FILE *out) " -S, --source device, LABEL= or UUID=device\n" " -T, --target mountpoint\n\n")); + + fprintf(out, _("\nAvailable columns:\n")); + + for (i = 0; i < __NCOLUMNS; i++) { + + fprintf(out, " %-12s", infos[i].name); + if (i && !((i+1) % 3)) + fputc('\n', out); + } + fputc('\n', out); + fprintf(out, _("\nFor more information see findmnt(1).\n")); exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); @@ -577,7 +550,8 @@ int main(int argc, char *argv[]) set_all_columns_truncate(FALSE); break; case 'o': - if (set_columns(optarg)) + if (tt_parse_columns_list(optarg, columns, &ncolumns, + column_name_to_id)) exit(EXIT_FAILURE); break; case 'O': @@ -695,7 +669,7 @@ int main(int argc, char *argv[]) } for (i = 0; i < ncolumns; i++) { - int fl = get_column_truncate(i) ? TT_FL_TRUNCATE : 0; + int fl = get_column_truncate(i) ? TT_FL_TRUNC : 0; if (get_column_id(i) == COL_TARGET && (tt_flags & TT_FL_TREE)) fl |= TT_FL_TREE; -- cgit v1.2.3 From ecc264bc39537486109c7bb80c937b5931326200 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 24 Nov 2010 16:39:15 +0100 Subject: lib: [xalloc] add xstrdup() Signed-off-by: Karel Zak --- include/xalloc.h | 9 +++++++++ misc-utils/wipefs.c | 9 --------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/xalloc.h b/include/xalloc.h index 2a8c78bc..ff5432e5 100644 --- a/include/xalloc.h +++ b/include/xalloc.h @@ -43,4 +43,13 @@ void *xcalloc(const size_t nelems, const size_t size) return ret; } +static inline char *xstrdup(const char *str) +{ + char *ret = strdup(str); + + if (!ret && str) + err(EXIT_FAILURE, "cannot duplicate string"); + return ret; +} + #endif diff --git a/misc-utils/wipefs.c b/misc-utils/wipefs.c index 2f223f0c..d3033446 100644 --- a/misc-utils/wipefs.c +++ b/misc-utils/wipefs.c @@ -136,15 +136,6 @@ add_offset(struct wipe_desc *wp0, loff_t offset, int zap) return wp; } -static inline char * -xstrdup(const char *s) -{ - char *x = strdup(s); - if (!x) - err(EXIT_FAILURE, _("strdup failed")); - return x; -} - static struct wipe_desc * get_offset_from_probe(struct wipe_desc *wp, blkid_probe pr, int zap) { -- cgit v1.2.3 From ce877f2d161b80119fd6bf6ccd2c7013252156d7 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 24 Nov 2010 16:41:20 +0100 Subject: lib: [strutils] move strmode() from namei.c to strutils.c Signed-off-by: Karel Zak --- include/strutils.h | 4 ++++ lib/strutils.c | 40 ++++++++++++++++++++++++++++++++++++++++ misc-utils/Makefile.am | 2 ++ misc-utils/namei.c | 37 +------------------------------------ 4 files changed, 47 insertions(+), 36 deletions(-) diff --git a/include/strutils.h b/include/strutils.h index e24496d3..31cf8060 100644 --- a/include/strutils.h +++ b/include/strutils.h @@ -3,6 +3,7 @@ #include #include +#include extern int strtosize(const char *str, uintmax_t *res); extern long strtol_or_err(const char *str, const char *errmesg); @@ -23,4 +24,7 @@ static inline void xstrncpy(char *dest, const char *src, size_t n) strncpy(dest, src, n-1); dest[n-1] = 0; } + +extern void strmode(mode_t mode, char *str); + #endif diff --git a/lib/strutils.c b/lib/strutils.c index f394800d..dcae9f2d 100644 --- a/lib/strutils.c +++ b/lib/strutils.c @@ -8,6 +8,7 @@ #include #include #include +#include static int do_scale_by_power (uintmax_t *x, int base, int power) { @@ -184,3 +185,42 @@ err: errx(EXIT_FAILURE, "%s: '%s'", errmesg, str); return 0; } + +/* + * Converts stat->st_mode to ls(1)-like mode string. The size of "str" must + * be 10 bytes. + */ +void strmode(mode_t mode, char *str) +{ + if (S_ISDIR(mode)) + str[0] = 'd'; + else if (S_ISLNK(mode)) + str[0] = 'l'; + else if (S_ISCHR(mode)) + str[0] = 'c'; + else if (S_ISBLK(mode)) + str[0] = 'b'; + else if (S_ISSOCK(mode)) + str[0] = 's'; + else if (S_ISFIFO(mode)) + str[0] = 'p'; + else if (S_ISREG(mode)) + str[0] = '-'; + + str[1] = mode & S_IRUSR ? 'r' : '-'; + str[2] = mode & S_IWUSR ? 'w' : '-'; + str[3] = (mode & S_ISUID + ? (mode & S_IXUSR ? 's' : 'S') + : (mode & S_IXUSR ? 'x' : '-')); + str[4] = mode & S_IRGRP ? 'r' : '-'; + str[5] = mode & S_IWGRP ? 'w' : '-'; + str[6] = (mode & S_ISGID + ? (mode & S_IXGRP ? 's' : 'S') + : (mode & S_IXGRP ? 'x' : '-')); + str[7] = mode & S_IROTH ? 'r' : '-'; + str[8] = mode & S_IWOTH ? 'w' : '-'; + str[9] = (mode & S_ISVTX + ? (mode & S_IXOTH ? 't' : 'T') + : (mode & S_IXOTH ? 'x' : '-')); + str[10] = '\0'; +} diff --git a/misc-utils/Makefile.am b/misc-utils/Makefile.am index 76b69fa4..c88b7c85 100644 --- a/misc-utils/Makefile.am +++ b/misc-utils/Makefile.am @@ -20,6 +20,8 @@ CLEANFILES = chkdupexe dist_man_MANS = cal.1 chkdupexe.1 ddate.1 logger.1 look.1 mcookie.1 \ namei.1 script.1 whereis.1 scriptreplay.1 +namei_SOURCES = namei.c $(top_srcdir)/lib/strutils.c + if BUILD_LIBUUID usrbin_exec_PROGRAMS += uuidgen dist_man_MANS += uuidgen.1 diff --git a/misc-utils/namei.c b/misc-utils/namei.c index 0342a08c..e75a165a 100644 --- a/misc-utils/namei.c +++ b/misc-utils/namei.c @@ -38,6 +38,7 @@ #include "xalloc.h" #include "nls.h" #include "widechar.h" +#include "strutils.h" #ifndef MAXSYMLINKS #define MAXSYMLINKS 256 @@ -362,42 +363,6 @@ follow_symlinks(struct namei *nm) return 0; } -static void -strmode(mode_t mode, char *str) -{ - if (S_ISDIR(mode)) - str[0] = 'd'; - else if (S_ISLNK(mode)) - str[0] = 'l'; - else if (S_ISCHR(mode)) - str[0] = 'c'; - else if (S_ISBLK(mode)) - str[0] = 'b'; - else if (S_ISSOCK(mode)) - str[0] = 's'; - else if (S_ISFIFO(mode)) - str[0] = 'p'; - else if (S_ISREG(mode)) - str[0] = '-'; - - str[1] = mode & S_IRUSR ? 'r' : '-'; - str[2] = mode & S_IWUSR ? 'w' : '-'; - str[3] = (mode & S_ISUID - ? (mode & S_IXUSR ? 's' : 'S') - : (mode & S_IXUSR ? 'x' : '-')); - str[4] = mode & S_IRGRP ? 'r' : '-'; - str[5] = mode & S_IWGRP ? 'w' : '-'; - str[6] = (mode & S_ISGID - ? (mode & S_IXGRP ? 's' : 'S') - : (mode & S_IXGRP ? 'x' : '-')); - str[7] = mode & S_IROTH ? 'r' : '-'; - str[8] = mode & S_IWOTH ? 'w' : '-'; - str[9] = (mode & S_ISVTX - ? (mode & S_IXOTH ? 't' : 'T') - : (mode & S_IXOTH ? 'x' : '-')); - str[10] = '\0'; -} - static int print_namei(struct namei *nm, char *path) { -- cgit v1.2.3 From 2a4c734bee6d52c26b7bfa5312c02f4b22b22645 Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Wed, 24 Nov 2010 17:06:39 +0100 Subject: lsblk: add new utility Signed-off-by: Milan Broz Signed-off-by: Karel Zak --- misc-utils/.gitignore | 1 + misc-utils/Makefile.am | 11 +- misc-utils/lsblk.8 | 66 +++ misc-utils/lsblk.c | 1062 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1138 insertions(+), 2 deletions(-) create mode 100644 misc-utils/lsblk.8 create mode 100644 misc-utils/lsblk.c diff --git a/misc-utils/.gitignore b/misc-utils/.gitignore index a39caaf3..d13bdf53 100644 --- a/misc-utils/.gitignore +++ b/misc-utils/.gitignore @@ -18,3 +18,4 @@ findfs blkid wipefs findmnt +lsblk diff --git a/misc-utils/Makefile.am b/misc-utils/Makefile.am index c88b7c85..b60ab0ed 100644 --- a/misc-utils/Makefile.am +++ b/misc-utils/Makefile.am @@ -6,11 +6,16 @@ bin_PROGRAMS = sbin_PROGRAMS = usrsbin_exec_PROGRAMS = -usrbin_exec_PROGRAMS = cal ddate logger look mcookie \ +usrbin_exec_PROGRAMS = cal ddate logger look lsblk mcookie \ namei script whereis scriptreplay EXTRA_DIST += README.cal README.ddate README.namei README.namei2 mcookie_SOURCES = mcookie.c $(top_srcdir)/lib/md5.c +lsblk_SOURCES = lsblk.c \ + $(top_srcdir)/lib/canonicalize.c \ + $(top_srcdir)/lib/ismounted.c \ + $(top_srcdir)/lib/tt.c \ + $(top_srcdir)/lib/strutils.c script_LDADD = usrbin_exec_SCRIPTS = chkdupexe @@ -18,7 +23,7 @@ usrbin_exec_SCRIPTS = chkdupexe CLEANFILES = chkdupexe dist_man_MANS = cal.1 chkdupexe.1 ddate.1 logger.1 look.1 mcookie.1 \ - namei.1 script.1 whereis.1 scriptreplay.1 + lsblk.1 namei.1 script.1 whereis.1 scriptreplay.1 namei_SOURCES = namei.c $(top_srcdir)/lib/strutils.c @@ -47,6 +52,8 @@ findfs_CFLAGS = $(AM_CFLAGS) -I$(ul_libblkid_incdir) wipefs_SOURCES = wipefs.c $(top_srcdir)/lib/strutils.c wipefs_LDADD = $(ul_libblkid_la) wipefs_CFLAGS = $(AM_CFLAGS) -I$(ul_libblkid_incdir) +lsblk_LDADD = $(ul_libblkid_la) +lsblk_CFLAGS = $(AM_CFLAGS) -I$(ul_libblkid_incdir) if HAVE_STATIC_BLKID sbin_PROGRAMS += blkid.static blkid_static_SOURCES = $(blkid_SOURCES) diff --git a/misc-utils/lsblk.8 b/misc-utils/lsblk.8 new file mode 100644 index 00000000..cc326063 --- /dev/null +++ b/misc-utils/lsblk.8 @@ -0,0 +1,66 @@ +.\" -*- nroff -*- +.TH LSBLK 8 "Apr 2010" "Version 1.0" +.SH NAME +lsblk \- list block devices +.SH SYNOPSIS +.B lsblk +.RB [ options ] +.sp +.B lsblk +.RB [ options ] +.IR device... +.SH DESCRIPTION +.B lsblk +will list information about all or selected block devices. The +.B lsblk +command reads +.I sysfs +filesystem to gather information. +.PP +The command prints all block devices (except RAM disks) in the tree-like format +by default. See +.B "lsblk --help" +to get list of all available columns. +.SH OPTIONS +.IP "\fB\-a, \-\-all\fP" +List all block devices. +.IP "\fB\-b, \-\-bytes\fP" +Print the SIZE column in bytes rather than in human readable format. +.IP "\fB\-e, \-\-exclude \fIlist\fP +Exclude devices by comma delimited list of major device numbers. Note that RAM +disks (major=1) are excluded by default. +.IP "\fB\-f, \-\-fs\fP +Output info about filesystems. This option is equivalent to -o NAME,FSTYPE,LABEL,MOUNTPOINT. +The authoritative information about filesystems and raids are provided by +.BR blkid (8) +command. +.IP "\fB\-h, \-\-help\fP" +Print help and exit. +.IP "\fB\-i, \-\-ascii\fP" +Use ascii characters for tree formatting. +.IP "\fB\-m, \-\-perms\fP +Output info about device owner, group and mode. This option is equivalent to -o NAME,SIZE,OWNER,GROUP,MODE. +.IP "\fB\-l, \-\-list\fP" +Use the list output format. +.IP "\fB\-n, \-\-noheadings\fP" +Do not print a header line. +.IP "\fB\-o, \-\-output \fIlist\fP" +Define output columns. Use +.B "--help" +to get list of all supported columns. +.IP "\fB\-r, \-\-raw\fP" +Use raw output format. +.IP "\fB\-t, \-\-topology\fP" +Output info about block device topology. This option is equivalent to -o NAME,ALIGNMENT,MIN-IO,OPT-IO,PHY-SEC,LOG-SEC,ROTA,SCHED. +.SH AUTHORS +.nf +Milan Broz +Karel Zak +.fi +.SH SEE ALSO +.BR findmnt (8), +.BR blkid (8), +.BR ls (1) +.SH AVAILABILITY +The lsblk command is part of the util-linux-ng package and is available from +ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/. diff --git a/misc-utils/lsblk.c b/misc-utils/lsblk.c new file mode 100644 index 00000000..f863e1c6 --- /dev/null +++ b/misc-utils/lsblk.c @@ -0,0 +1,1062 @@ +/* + * lsblk(1) - list block devices + * + * Copyright (C) 2010 Red Hat, Inc. All rights reserved. + * Written by Milan Broz + * Karel Zak + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "pathnames.h" +#include "blkdev.h" +#include "canonicalize.h" +#include "ismounted.h" +#include "nls.h" +#include "tt.h" +#include "xalloc.h" +#include "strutils.h" + +/* column IDs */ +enum { + COL_NAME = 0, + COL_KNAME, + COL_MAJMIN, + COL_FSTYPE, + COL_TARGET, + COL_LABEL, + COL_UUID, + COL_RO, + COL_RA, + COL_MODEL, + COL_SIZE, + COL_OWNER, + COL_GROUP, + COL_MODE, + COL_ALIOFF, + COL_MINIO, + COL_OPTIO, + COL_PHYSEC, + COL_LOGSEC, + COL_ROTA, + COL_SCHED, + + __NCOLUMNS +}; + +/* column names */ +struct colinfo { + const char *name; /* header */ + double whint; /* width hint (N < 1 is in percent of termwidth) */ + int flags; /* TT_FL_* */ + const char *help; +}; + +/* columns descriptions */ +static struct colinfo infos[__NCOLUMNS] = { + [COL_NAME] = { "NAME", 0.25, TT_FL_TREE, N_("device name") }, + [COL_KNAME] = { "KNAME", 0.3, 0, N_("internel kernel device name") }, + [COL_MAJMIN] = { "MAJ:MIN", 6, 0, N_("major:minor device number") }, + [COL_FSTYPE] = { "FSTYPE", 0.1, TT_FL_TRUNC, N_("filesystem type") }, + [COL_TARGET] = { "MOUNTPOINT", 0.10, TT_FL_TRUNC, N_("where the device is mounted") }, + [COL_LABEL] = { "LABEL", 0.1, 0, N_("filesystem LABEL") }, + [COL_UUID] = { "UUID", 36, 0, N_("filesystem UUID") }, + [COL_RO] = { "RO", 1, TT_FL_RIGHT, N_("read-only device") }, + [COL_RA] = { "RA", 1, TT_FL_RIGHT, N_("removable device") }, + [COL_ROTA] = { "ROTA", 1, TT_FL_RIGHT, N_("rotational device") }, + [COL_MODEL] = { "MODEL", 0.1, TT_FL_TRUNC, N_("device identifier") }, + [COL_SIZE] = { "SIZE", 6, TT_FL_RIGHT, N_("size of the device") }, + [COL_OWNER] = { "OWNER", 0.1, TT_FL_TRUNC, N_("user name"), }, + [COL_GROUP] = { "GROUP", 0.1, TT_FL_TRUNC, N_("group name") }, + [COL_MODE] = { "MODE", 10, 0, N_("device node permissions") }, + [COL_ALIOFF] = { "ALIGNMENT", 6, TT_FL_RIGHT, N_("alignment offset") }, + [COL_MINIO] = { "MIN-IO", 6, TT_FL_RIGHT, N_("minimum I/O size") }, + [COL_OPTIO] = { "OPT-IO", 6, TT_FL_RIGHT, N_("optimal I/O size") }, + [COL_PHYSEC] = { "PHY-SEC", 7, TT_FL_RIGHT, N_("physical sector size") }, + [COL_LOGSEC] = { "LOG-SEC", 7, TT_FL_RIGHT, N_("logical sector size") }, + [COL_SCHED] = { "SCHED", 0.1, 0, N_("I/O scheduler name") } + +}; + +struct lsblk { + struct tt *tt; /* output table */ + int all_devices:1; /* print all devices */ + int bytes:1; /* print SIZE in bytes */ +}; + +struct lsblk *lsblk; /* global handler */ +int columns[__NCOLUMNS];/* enabled columns */ +int ncolumns; /* number of enabled columns */ + +unsigned int excludes[256]; +int nexcludes; + +struct blkdev_cxt { + struct blkdev_cxt *parent; + + struct tt_line *tt_line; + struct stat st; + + char *name; /* kernel name in /sys/block */ + char *dm_name; /* DM name (dm/block) */ + + char *filename; /* path to device node */ + int sysfs_fd; /* O_RDONLY file desciptor to /sys/block/ */ + + int partition; /* is partition? TRUE/FALSE */ + + int probed; /* already probed */ + char *fstype; /* detected fs, NULL or "?" if cannot detect */ + char *uuid; /* UUID of device / filesystem */ + char *label; /* FS label */ + + int nholders; /* # of devices mapped directly to this device + * /sys/block/.../holders + number of partition */ + int nslaves; /* # of devices this device maps to */ + int maj, min; /* devno */ + + uint64_t size; /* device size */ +}; + +static int is_maj_excluded(int maj) +{ + int i; + + assert(ARRAY_SIZE(excludes) > nexcludes); + + for (i = 0; i < nexcludes; i++) + if (excludes[i] == maj) + return 1; + return 0; +} + + +/* array with IDs of enabled columns */ +static int get_column_id(int num) +{ + assert(ARRAY_SIZE(columns) == __NCOLUMNS); + assert(num < ncolumns); + assert(columns[num] < __NCOLUMNS); + return columns[num]; +} + +static struct colinfo *get_column_info(int num) +{ + return &infos[ get_column_id(num) ]; +} + + +static int column_name_to_id(const char *name, size_t namesz) +{ + int i; + + for (i = 0; i < __NCOLUMNS; i++) { + const char *cn = infos[i].name; + + if (!strncasecmp(name, cn, namesz) && !*(cn + namesz)) + return i; + } + warnx(_("unknown column: %s"), name); + return -1; +} + +static void reset_blkdev_cxt(struct blkdev_cxt *cxt) +{ + if (!cxt) + return; + free(cxt->name); + free(cxt->dm_name); + free(cxt->filename); + free(cxt->fstype); + free(cxt->uuid); + free(cxt->label); + + if (cxt->sysfs_fd >= 0) + close(cxt->sysfs_fd); + + memset(cxt, 0, sizeof(*cxt)); +} + +static int is_dm(const char *name) +{ + return strncmp(name, "dm-", 3) ? 0 : 1; +} + +static struct dirent *xreaddir(DIR *dp) +{ + struct dirent *d; + + assert(dp); + + while ((d = readdir(dp))) { + if (!strcmp(d->d_name, ".") || + !strcmp(d->d_name, "..")) + continue; + + /* blacklist here? */ + break; + } + return d; +} + +/* + * returns exponent (2^x=n) in range KiB..PiB + */ +static int get_exp(uint64_t n) +{ + int shft; + + for (shft = 10; shft <= 60; shft += 10) { + if (n < (1ULL << shft)) + break; + } + return shft - 10; +} + +static char *size_to_human_string(uint64_t bytes) +{ + char buf[32]; + int dec, frac, exp; + const char *letters = "BKMGTP"; + char c; + + exp = get_exp(bytes); + c = *(letters + (exp ? exp / 10 : 0)); + dec = exp ? bytes / (1ULL << exp) : bytes; + frac = exp ? bytes % (1ULL << exp) : 0; + + if (frac) { + /* round */ + frac = (frac / (1ULL << (exp - 10)) + 50) / 100; + if (frac == 10) + dec++, frac = 0; + } + + if (frac) { + struct lconv const *l = localeconv(); + char *dp = l ? l->decimal_point : NULL; + + if (!dp || !*dp) + dp = "."; + snprintf(buf, sizeof(buf), "%d%s%d%c", dec, dp, frac, c); + } else + snprintf(buf, sizeof(buf), "%d%c", dec, c); + + return xstrdup(buf); +} + + +static int is_partition_dirent(DIR *dir, struct dirent *d, const char *parent_name) +{ + char path[256]; + + assert(dir); + assert(d); + +#ifdef _DIRENT_HAVE_D_TYPE + if (d->d_type != DT_DIR) + return 0; +#endif + if (strncmp(parent_name, d->d_name, strlen(parent_name))) + return 0; + + /* Cannot use /partition file, not supported on old sysfs */ + snprintf(path, sizeof(path), "%s/start", d->d_name); + + return faccessat(dirfd(dir), path, R_OK, 0) == 0; +} + +static char *get_device_path(struct blkdev_cxt *cxt) +{ + char path[PATH_MAX]; + + assert(cxt); + assert(cxt->name); + + if (is_dm(cxt->name)) + return canonicalize_dm_name(cxt->name); + + snprintf(path, sizeof(path), "/dev/%s", cxt->name); + return xstrdup(path); +} + +static char *get_sysfs_path(struct blkdev_cxt *cxt) +{ + char path[PATH_MAX]; + + assert(cxt); + assert(cxt->name); + + if (cxt->partition && cxt->parent) + snprintf(path, sizeof(path), _PATH_SYS_BLOCK "/%s/%s", + cxt->parent->name, cxt->name); + else + snprintf(path, sizeof(path), _PATH_SYS_BLOCK "/%s", cxt->name); + + return xstrdup(path); +} + +static int sysfs_open(struct blkdev_cxt *cxt, const char *attr) +{ + int fd; + + assert(cxt); + assert(cxt->sysfs_fd >= 0); + + fd = openat(cxt->sysfs_fd, attr, O_RDONLY); + if (fd == -1 && errno == ENOENT && !strncmp(attr, "queue/", 6) && cxt->parent) { + fd = openat(cxt->parent->sysfs_fd, attr, O_RDONLY); + } + return fd; +} + +static FILE *sysfs_fopen(struct blkdev_cxt *cxt, const char *attr) +{ + int fd = sysfs_open(cxt, attr); + + return fd < 0 ? NULL : fdopen(fd, "r"); +} + +static DIR *sysfs_opendir(struct blkdev_cxt *cxt, const char *attr) +{ + DIR *dir; + int fd; + + if (attr) + fd = sysfs_open(cxt, attr); + else { + /* request to open root of device in sysfs (/sys/block/) + * -- we cannot use cxt->sysfs_fd directly, because closedir() + * will close this our persistent file descriptor. + */ + assert(cxt); + assert(cxt->sysfs_fd >= 0); + + fd = dup(cxt->sysfs_fd); + } + + if (fd < 0) + return NULL; + dir = fdopendir(fd); + if (!dir) { + close(fd); + return NULL; + } + if (!attr) + rewinddir(dir); + return dir; +} + +static __attribute__ ((format (scanf, 3, 4))) +int sysfs_scanf(struct blkdev_cxt *cxt, const char *attr, const char *fmt, ...) +{ + FILE *f = sysfs_fopen(cxt, attr); + va_list ap; + int rc; + + if (!f) + return -EINVAL; + va_start(ap, fmt); + rc = vfscanf(f, fmt, ap); + va_end(ap); + + fclose(f); + return rc; +} + +static uint64_t sysfs_read_u64(struct blkdev_cxt *cxt, const char *attr) +{ + uint64_t x; + return sysfs_scanf(cxt, attr, "%"SCNu64, &x) == 1 ? x : 0; +} + +static char *sysfs_strdup(struct blkdev_cxt *cxt, const char *attr) +{ + char buf[1024]; + return sysfs_scanf(cxt, attr, "%1024[^\n]", buf) == 1 ? + xstrdup(buf) : NULL; +} + +static int sysfs_count_dirents(struct blkdev_cxt *cxt, const char *attr) +{ + DIR *dir; + int r = 0; + + if (!(dir = sysfs_opendir(cxt, attr))) + return 0; + + while (xreaddir(dir)) r++; + + closedir(dir); + return r; +} + +static int sysfs_count_partitions(struct blkdev_cxt *cxt) +{ + DIR *dir; + struct dirent *d; + int r = 0; + + if (!(dir = sysfs_opendir(cxt, NULL))) + return 0; + + while ((d = xreaddir(dir))) { + if (is_partition_dirent(dir, d, cxt->name)) + r++; + } + + closedir(dir); + return r; +} + +static char *get_device_mountpoint(struct blkdev_cxt *cxt) +{ + int fl = 0; + char mnt[PATH_MAX]; + + *mnt = '\0'; + + /* + * TODO: use libmount and parse /proc/mountinfo only once + */ + if (check_mount_point(cxt->filename, &fl, mnt, sizeof(mnt)) == 0 && + (fl & MF_MOUNTED)) { + if (fl & MF_SWAP) + strcpy(mnt, "[SWAP]"); + } + return strlen(mnt) ? xstrdup(mnt) : NULL; +} + +/* TODO: read info from udev db (if possible) for non-root users + */ +static void probe_device(struct blkdev_cxt *cxt) +{ + char *path = NULL; + blkid_probe pr = NULL; + + if (cxt->probed) + return; + cxt->probed = 1; + + if (!cxt->size) + return; + + pr = blkid_new_probe_from_filename(cxt->filename); + if (!pr) + return; + + /* TODO: we have to enable partitions probing to avoid conflicts + * between raids and PT -- see blkid(8) code for more details + */ + blkid_probe_enable_superblocks(pr, 1); + blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_LABEL | + BLKID_SUBLKS_UUID | + BLKID_SUBLKS_TYPE); + if (!blkid_do_safeprobe(pr)) { + const char *data = NULL; + + if (!blkid_probe_lookup_value(pr, "TYPE", &data, NULL)) + cxt->fstype = xstrdup(data); + if (!blkid_probe_lookup_value(pr, "UUID", &data, NULL)) + cxt->uuid = xstrdup(data); + if (!blkid_probe_lookup_value(pr, "LABEL", &data, NULL)) + cxt->label = xstrdup(data); + } + + free(path); + blkid_free_probe(pr); + return; +} + +static int is_readonly_device(struct blkdev_cxt *cxt) +{ + int fd, ro = 0; + + if (sysfs_scanf(cxt, "ro", "%d", &ro) == 0) + return ro; + + /* fallback if "ro" attribute does not exist */ + fd = open(cxt->filename, O_RDONLY); + if (fd != -1) { + ioctl(fd, BLKROGET, &ro); + close(fd); + } + return ro; +} + +static char *get_scheduler(struct blkdev_cxt *cxt) +{ + char *str = sysfs_strdup(cxt, "queue/scheduler"); + char *p, *res = NULL; + + if (!str) + return NULL; + p = strchr(str, '['); + if (p) { + res = p + 1; + p = strchr(res, ']'); + if (p) { + *p = '\0'; + res = xstrdup(res); + } else + res = NULL; + } + free(str); + return res; +} + +static void set_tt_data(struct blkdev_cxt *cxt, int col, int id, struct tt_line *ln) +{ + char buf[1024]; + char *p; + + if (!cxt->st.st_rdev && (id == COL_OWNER || id == COL_GROUP || + id == COL_MODE)) + stat(cxt->filename, &cxt->st); + + switch(id) { + case COL_NAME: + if (cxt->dm_name) { + snprintf(buf, sizeof(buf), "%s (%s)", + cxt->dm_name, cxt->name); + tt_line_set_data(ln, col, xstrdup(buf)); + break; + } + case COL_KNAME: + tt_line_set_data(ln, col, xstrdup(cxt->name)); + break; + case COL_OWNER: + { + struct passwd *pw = getpwuid(cxt->st.st_uid); + if (pw) + tt_line_set_data(ln, col, xstrdup(pw->pw_name)); + break; + } + case COL_GROUP: + { + struct group *gr = getgrgid(cxt->st.st_gid); + if (gr) + tt_line_set_data(ln, col, xstrdup(gr->gr_name)); + break; + } + case COL_MODE: + { + char md[11]; + strmode(cxt->st.st_mode, md); + tt_line_set_data(ln, col, xstrdup(md)); + break; + } + case COL_MAJMIN: + if (lsblk->tt->flags & TT_FL_RAW) + snprintf(buf, sizeof(buf), "%u:%u", cxt->maj, cxt->min); + else + snprintf(buf, sizeof(buf), "%3u:%-3u", cxt->maj, cxt->min); + tt_line_set_data(ln, col, xstrdup(buf)); + break; + case COL_FSTYPE: + probe_device(cxt); + if (cxt->fstype) + tt_line_set_data(ln, col, xstrdup(cxt->fstype)); + break; + case COL_TARGET: + if (!cxt->nholders) { + p = get_device_mountpoint(cxt); + if (p) + tt_line_set_data(ln, col, p); + } + break; + case COL_LABEL: + probe_device(cxt); + if (cxt->label) + tt_line_set_data(ln, col, xstrdup(cxt->label)); + break; + case COL_UUID: + probe_device(cxt); + if (cxt->uuid) + tt_line_set_data(ln, col, xstrdup(cxt->uuid)); + break; + case COL_RO: + tt_line_set_data(ln, col, is_readonly_device(cxt) ? + xstrdup("1") : xstrdup("0")); + break; + case COL_RA: + p = sysfs_strdup(cxt, "removable"); + if (!p && cxt->parent) + p = sysfs_strdup(cxt->parent, "removable"); + if (p) + tt_line_set_data(ln, col, p); + break; + case COL_ROTA: + p = sysfs_strdup(cxt, "queue/rotational"); + if (p) + tt_line_set_data(ln, col, p); + break; + case COL_MODEL: + if (!cxt->partition && cxt->nslaves == 0) { + p = sysfs_strdup(cxt, "device/model"); + if (p) + tt_line_set_data(ln, col, p); + } + break; + case COL_SIZE: + if (cxt->size) { + if (lsblk->bytes) { + if (asprintf(&p, "%jd", cxt->size) < 0) + p = NULL; + } else + p = size_to_human_string(cxt->size); + if (p) + tt_line_set_data(ln, col, p); + } + break; + case COL_ALIOFF: + p = sysfs_strdup(cxt, "alignment_offset"); + if (p) + tt_line_set_data(ln, col, p); + break; + case COL_MINIO: + p = sysfs_strdup(cxt, "queue/minimum_io_size"); + if (p) + tt_line_set_data(ln, col, p); + break; + case COL_OPTIO: + p = sysfs_strdup(cxt, "queue/optimal_io_size"); + if (p) + tt_line_set_data(ln, col, p); + break; + case COL_PHYSEC: + p = sysfs_strdup(cxt, "queue/physical_block_size"); + if (p) + tt_line_set_data(ln, col, p); + break; + case COL_LOGSEC: + p = sysfs_strdup(cxt, "queue/logical_block_size"); + if (p) + tt_line_set_data(ln, col, p); + break; + case COL_SCHED: + p = get_scheduler(cxt); + if (p) + tt_line_set_data(ln, col, p); + break; + }; +} + +static void print_device(struct blkdev_cxt *cxt, struct tt_line *tt_parent) +{ + int i; + + cxt->tt_line = tt_add_line(lsblk->tt, tt_parent); + + for (i = 0; i < ncolumns; i++) + set_tt_data(cxt, i, get_column_id(i), cxt->tt_line); +} + +static int set_cxt(struct blkdev_cxt *cxt, + struct blkdev_cxt *parent, + const char *name, + int partition) +{ + char *p; + + cxt->parent = parent; + cxt->name = xstrdup(name); + cxt->partition = partition; + + cxt->filename = get_device_path(cxt); + + /* open /sys/block/ */ + p = get_sysfs_path(cxt); + cxt->sysfs_fd = open(p, O_RDONLY); + if (cxt->sysfs_fd < 0) + err(EXIT_FAILURE, _("%s: open failed"), p); + free(p); + + if (sysfs_scanf(cxt, "dev", "%u:%u", &cxt->maj, &cxt->min) != 2) + return -1; + + cxt->size = sysfs_read_u64(cxt, "size") << 9; + + /* Ignore devices of zero size */ + if (!lsblk->all_devices && cxt->size == 0) + return -1; + + if (is_dm(name)) + cxt->dm_name = sysfs_strdup(cxt, "dm/name"); + + cxt->nholders = sysfs_count_dirents(cxt, "holders") + + sysfs_count_partitions(cxt); + cxt->nslaves = sysfs_count_dirents(cxt, "slaves"); + + return 0; +} + +/* + * List devices (holders) mapped to device + */ +static int list_holders(struct blkdev_cxt *cxt) +{ + DIR *dir; + struct dirent *d; + struct blkdev_cxt holder = {}; + + assert(cxt); + assert(cxt->sysfs_fd >= 0); + + if (!cxt->nholders) + return 0; + + /* Partitions */ + dir = sysfs_opendir(cxt, NULL); + if (!dir) + err(EXIT_FAILURE, _("failed to open device directory in sysfs")); + + while ((d = xreaddir(dir))) { + if (!is_partition_dirent(dir, d, cxt->name)) + continue; + + set_cxt(&holder, cxt, d->d_name, 1); + print_device(&holder, cxt->tt_line); + list_holders(&holder); + reset_blkdev_cxt(&holder); + } + closedir(dir); + + /* Holders */ + dir = sysfs_opendir(cxt, "holders"); + if (!dir) + return 0; + + while ((d = xreaddir(dir))) { + set_cxt(&holder, cxt, d->d_name, 0); + print_device(&holder, cxt->tt_line); + list_holders(&holder); + reset_blkdev_cxt(&holder); + } + closedir(dir); + + return 0; +} + +/* Iterate top-level devices in sysfs */ +static int iterate_block_devices(void) +{ + DIR *dir; + struct dirent *d; + struct blkdev_cxt cxt = {}; + + if (!(dir = opendir(_PATH_SYS_BLOCK))) + return EXIT_FAILURE; + + while ((d = xreaddir(dir))) { + + if (set_cxt(&cxt, NULL, d->d_name, 0)) + goto next; + + /* Skip devices in the middle of dependence tree */ + if (cxt.nslaves > 0) + goto next; + + if (!lsblk->all_devices && is_maj_excluded(cxt.maj)) + goto next; + + print_device(&cxt, NULL); + list_holders(&cxt); + next: + reset_blkdev_cxt(&cxt); + } + + closedir(dir); + + return EXIT_SUCCESS; +} + +static int process_one_device(char *devname) +{ + struct blkdev_cxt parent = {}, cxt = {}; + struct stat st; + char buf[PATH_MAX]; + dev_t disk = 0; + + if (stat(devname, &st) || !S_ISBLK(st.st_mode)) { + warnx(_("%s: not a block device"), devname); + return EXIT_FAILURE; + } + if (blkid_devno_to_wholedisk(st.st_rdev, buf, sizeof(buf), &disk)) { + warn(_("%s: failed to get whole-list devno"), devname); + return EXIT_FAILURE; + } + if (st.st_rdev == disk) + /* + * unpartitioned device + */ + set_cxt(&cxt, NULL, buf, 0); + else { + /* + * Parititioned, read sysfs name of the device + */ + size_t len; + char path[PATH_MAX], *diskname, *name; + + snprintf(path, sizeof(path), "/sys/dev/block/%d:%d", + major(st.st_rdev), minor(st.st_rdev)); + diskname = xstrdup(buf); + + len = readlink(path, buf, sizeof(buf)); + if (len < 0) { + warn(_("%s: failed to read link"), path); + return EXIT_FAILURE; + } + buf[len] = '\0'; + + /* sysfs device name */ + name = strrchr(buf, '/') + 1; + + set_cxt(&parent, NULL, diskname, 0); + set_cxt(&cxt, &parent, name, 1); + + free(diskname); + } + + print_device(&cxt, NULL); + list_holders(&cxt); + reset_blkdev_cxt(&cxt); + + if (st.st_rdev != disk) + reset_blkdev_cxt(&parent); + + return EXIT_SUCCESS; +} + +static void parse_excludes(const char *str) +{ + nexcludes = 0; + + while (str && *str) { + char *end = NULL; + unsigned int n; + + errno = 0; + n = strtoul(str, &end, 10); + + if (end == str || (errno != 0 && (n == ULONG_MAX || n == 0))) + err(EXIT_FAILURE, _("failed to parse list '%s'"), str); + excludes[nexcludes++] = n; + + if (nexcludes == ARRAY_SIZE(excludes)) + errx(EXIT_FAILURE, _("the list of excluded devices is " + "too large (limit is %d devices)"), + (int)ARRAY_SIZE(excludes)); + str = end && *end ? end + 1 : NULL; + } +} + +static int __attribute__((__noreturn__)) help(FILE *out) +{ + int i; + + fprintf(out, _( + "\nUsage:\n" + " %s [options] [ ...]\n"), program_invocation_short_name); + + fprintf(out, _( + "\nOptions:\n" + " -a, --all print all devices\n" + " -b, --bytes print SIZE in bytes rather than in human readable format\n" + " -e, --exclude exclude devices by major number (default: RAM disks)\n" + " -f, --fs output info about filesystems\n" + " -h, --help usage information (this)\n" + " -i, --ascii use ascii characters only\n" + " -m, --perms output info about permissions\n" + " -l, --list use list format ouput\n" + " -n, --noheadings don't print headings\n" + " -o, --output output columns\n" + " -r, --raw use raw format output\n" + " -t, --topology output info about topology\n")); + + fprintf(out, _("\nAvailable columns:\n")); + + for (i = 0; i < __NCOLUMNS; i++) + fprintf(out, " %10s %s\n", infos[i].name, gettext(infos[i].help)); + + fprintf(out, _("\nFor more information see lsblk(1).\n")); + + exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); +} + +static int __attribute__((__noreturn__)) +errx_mutually_exclusive(const char *opts) +{ + errx(EXIT_FAILURE, "%s %s", opts, _("options are mutually exclusive")); +} + +int main(int argc, char *argv[]) +{ + struct lsblk _ls; + int tt_flags = TT_FL_TREE; + int i, c, status = EXIT_FAILURE; + + struct option longopts[] = { + { "all", 0, 0, 'a' }, + { "help", 0, 0, 'h' }, + { "output", 1, 0, 'o' }, + { "perms", 0, 0, 'm' }, + { "noheadings", 0, 0, 'n' }, + { "list", 0, 0, 'l' }, + { "ascii", 0, 0, 'i' }, + { "raw", 0, 0, 'r' }, + { "fs", 0, 0, 'f' }, + { "exclude", 1, 0, 'e' }, + { "topology", 0, 0, 't' }, + { NULL, 0, 0, 0 }, + }; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + lsblk = &_ls; + memset(lsblk, 0, sizeof(*lsblk)); + + while((c = getopt_long(argc, argv, "abe:fhlnmo:irt", longopts, NULL)) != -1) { + switch(c) { + case 'a': + lsblk->all_devices = 1; + break; + case 'b': + lsblk->bytes = 1; + break; + case 'e': + parse_excludes(optarg); + break; + case 'h': + help(stdout); + break; + case 'l': + if (tt_flags & TT_FL_RAW) + errx_mutually_exclusive("--{raw,list}"); + + tt_flags &= ~TT_FL_TREE; /* disable the default */ + break; + case 'n': + tt_flags |= TT_FL_NOHEADINGS; + break; + case 'o': + if (tt_parse_columns_list(optarg, columns, &ncolumns, + column_name_to_id)) + return EXIT_FAILURE; + break; + case 'i': + tt_flags = TT_FL_ASCII; + break; + case 'r': + tt_flags &= ~TT_FL_TREE; /* disable the default */ + tt_flags |= TT_FL_RAW; /* enable raw */ + break; + case 'f': + columns[ncolumns++] = COL_NAME; + columns[ncolumns++] = COL_FSTYPE; + columns[ncolumns++] = COL_LABEL; + columns[ncolumns++] = COL_TARGET; + break; + case 'm': + columns[ncolumns++] = COL_NAME; + columns[ncolumns++] = COL_SIZE; + columns[ncolumns++] = COL_OWNER; + columns[ncolumns++] = COL_GROUP; + columns[ncolumns++] = COL_MODE; + break; + case 't': + columns[ncolumns++] = COL_NAME; + columns[ncolumns++] = COL_ALIOFF; + columns[ncolumns++] = COL_MINIO; + columns[ncolumns++] = COL_OPTIO; + columns[ncolumns++] = COL_PHYSEC; + columns[ncolumns++] = COL_LOGSEC; + columns[ncolumns++] = COL_ROTA; + columns[ncolumns++] = COL_SCHED; + break; + default: + help(stderr); + } + } + + if (!ncolumns) { + columns[ncolumns++] = COL_NAME; + columns[ncolumns++] = COL_MAJMIN; + columns[ncolumns++] = COL_RA; + columns[ncolumns++] = COL_SIZE; + columns[ncolumns++] = COL_RO; + columns[ncolumns++] = COL_TARGET; + } + + if (nexcludes && lsblk->all_devices) + errx_mutually_exclusive("--{all,exclude}"); + else if (!nexcludes) + excludes[nexcludes++] = 1; /* default: ignore RAM disks */ + /* + * initialize output columns + */ + if (!(lsblk->tt = tt_new_table(tt_flags))) + errx(EXIT_FAILURE, _("failed to initialize output table")); + + for (i = 0; i < ncolumns; i++) { + struct colinfo *ci = get_column_info(i); + int fl = ci->flags; + + if (!(tt_flags & TT_FL_TREE) && get_column_id(i) == COL_NAME) + fl &= ~TT_FL_TREE; + + if (!tt_define_column(lsblk->tt, ci->name, ci->whint, fl)) { + warn(_("failed to initialize output column")); + goto leave; + } + } + + if (optind == argc) + status = iterate_block_devices(); + else while (optind < argc) + status = process_one_device(argv[optind++]); + + tt_print_table(lsblk->tt); + +leave: + tt_free_table(lsblk->tt); + return status; +} -- cgit v1.2.3 From f77fa578e3e14bbc22cc987640cfb2c8e254477f Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 24 Nov 2010 18:16:44 +0100 Subject: build-sys: fix lsblk building Signed-off-by: Karel Zak --- misc-utils/Makefile.am | 19 ++++++++++++------- misc-utils/lsblk.c | 4 ++-- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/misc-utils/Makefile.am b/misc-utils/Makefile.am index b60ab0ed..8b1dbbe2 100644 --- a/misc-utils/Makefile.am +++ b/misc-utils/Makefile.am @@ -6,16 +6,11 @@ bin_PROGRAMS = sbin_PROGRAMS = usrsbin_exec_PROGRAMS = -usrbin_exec_PROGRAMS = cal ddate logger look lsblk mcookie \ +usrbin_exec_PROGRAMS = cal ddate logger look mcookie \ namei script whereis scriptreplay EXTRA_DIST += README.cal README.ddate README.namei README.namei2 mcookie_SOURCES = mcookie.c $(top_srcdir)/lib/md5.c -lsblk_SOURCES = lsblk.c \ - $(top_srcdir)/lib/canonicalize.c \ - $(top_srcdir)/lib/ismounted.c \ - $(top_srcdir)/lib/tt.c \ - $(top_srcdir)/lib/strutils.c script_LDADD = usrbin_exec_SCRIPTS = chkdupexe @@ -23,7 +18,7 @@ usrbin_exec_SCRIPTS = chkdupexe CLEANFILES = chkdupexe dist_man_MANS = cal.1 chkdupexe.1 ddate.1 logger.1 look.1 mcookie.1 \ - lsblk.1 namei.1 script.1 whereis.1 scriptreplay.1 + namei.1 script.1 whereis.1 scriptreplay.1 namei_SOURCES = namei.c $(top_srcdir)/lib/strutils.c @@ -47,11 +42,21 @@ blkid_SOURCES = blkid.c $(top_srcdir)/lib/ismounted.c \ $(top_srcdir)/lib/strutils.c blkid_LDADD = $(ul_libblkid_la) blkid_CFLAGS = $(AM_CFLAGS) -I$(ul_libblkid_incdir) + findfs_LDADD = $(ul_libblkid_la) findfs_CFLAGS = $(AM_CFLAGS) -I$(ul_libblkid_incdir) + wipefs_SOURCES = wipefs.c $(top_srcdir)/lib/strutils.c wipefs_LDADD = $(ul_libblkid_la) wipefs_CFLAGS = $(AM_CFLAGS) -I$(ul_libblkid_incdir) + +bin_PROGRAMS += lsblk +dist_man_MANS += lsblk.8 +lsblk_SOURCES = lsblk.c \ + $(top_srcdir)/lib/canonicalize.c \ + $(top_srcdir)/lib/ismounted.c \ + $(top_srcdir)/lib/tt.c \ + $(top_srcdir)/lib/strutils.c lsblk_LDADD = $(ul_libblkid_la) lsblk_CFLAGS = $(AM_CFLAGS) -I$(ul_libblkid_incdir) if HAVE_STATIC_BLKID diff --git a/misc-utils/lsblk.c b/misc-utils/lsblk.c index f863e1c6..6c5a205d 100644 --- a/misc-utils/lsblk.c +++ b/misc-utils/lsblk.c @@ -1,5 +1,5 @@ /* - * lsblk(1) - list block devices + * lsblk(8) - list block devices * * Copyright (C) 2010 Red Hat, Inc. All rights reserved. * Written by Milan Broz @@ -915,7 +915,7 @@ static int __attribute__((__noreturn__)) help(FILE *out) for (i = 0; i < __NCOLUMNS; i++) fprintf(out, " %10s %s\n", infos[i].name, gettext(infos[i].help)); - fprintf(out, _("\nFor more information see lsblk(1).\n")); + fprintf(out, _("\nFor more information see lsblk(8).\n")); exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); } -- cgit v1.2.3 From 042154d764e9dcff1e17b06f09ada0e2c2074f95 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 24 Nov 2010 23:16:01 +0100 Subject: fallocate: fix typo Signed-off-by: Karel Zak --- sys-utils/fallocate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys-utils/fallocate.c b/sys-utils/fallocate.c index 9598cf10..e9d7c079 100644 --- a/sys-utils/fallocate.c +++ b/sys-utils/fallocate.c @@ -87,7 +87,7 @@ int main(int argc, char **argv) { "help", 0, 0, 'h' }, { "keep-size", 0, 0, 'n' }, { "offset", 1, 0, 'o' }, - { "lenght", 1, 0, 'l' }, + { "length", 1, 0, 'l' }, { NULL, 0, 0, 0 } }; -- cgit v1.2.3 From 6d830ab64173d7228d96290b96f1d71ee8cdd187 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Fri, 26 Nov 2010 13:40:51 +0100 Subject: libblkid: 256MiB is min size of btrfs Signed-off-by: Karel Zak --- shlibs/blkid/src/superblocks/btrfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/shlibs/blkid/src/superblocks/btrfs.c b/shlibs/blkid/src/superblocks/btrfs.c index a2019597..51bbadc7 100644 --- a/shlibs/blkid/src/superblocks/btrfs.c +++ b/shlibs/blkid/src/superblocks/btrfs.c @@ -83,6 +83,7 @@ const struct blkid_idinfo btrfs_idinfo = .name = "btrfs", .usage = BLKID_USAGE_FILESYSTEM, .probefunc = probe_btrfs, + .minsz = 256 * 1024 * 1024, .magics = { { .magic = "_BHRfS_M", .len = 8, .kboff = 64, .sboff = 0x40 }, -- cgit v1.2.3 From d9e2d0dd144c2c06bff590c35400965016e55b7c Mon Sep 17 00:00:00 2001 From: Lukas Czerner Date: Thu, 25 Nov 2010 00:05:37 +0100 Subject: fstrim: add new command fstrim is used on a mounted filesystem to discard (or "trim") blocks which are not in use by the filesystem. This is useful for solid-state drives (SSDs) and thinly-provisioned storage Signed-off-by: Lukas Czerner Signed-off-by: Karel Zak --- sys-utils/.gitignore | 1 + sys-utils/Makefile.am | 6 +- sys-utils/fstrim.8 | 84 +++++++++++++++++++++++++++ sys-utils/fstrim.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 242 insertions(+), 3 deletions(-) create mode 100644 sys-utils/fstrim.8 create mode 100644 sys-utils/fstrim.c diff --git a/sys-utils/.gitignore b/sys-utils/.gitignore index 7af5ffbf..b8af98f1 100644 --- a/sys-utils/.gitignore +++ b/sys-utils/.gitignore @@ -5,6 +5,7 @@ dmesg fallocate flock fsfreeze +fstrim i386.8 ia64.8 ipcmk diff --git a/sys-utils/Makefile.am b/sys-utils/Makefile.am index a45978e3..3bcae52c 100644 --- a/sys-utils/Makefile.am +++ b/sys-utils/Makefile.am @@ -10,12 +10,12 @@ dist_man_MANS = flock.1 ipcrm.1 ipcs.1 ipcmk.1 renice.1 setsid.1 \ if LINUX bin_PROGRAMS += dmesg -sbin_PROGRAMS += ctrlaltdel fsfreeze +sbin_PROGRAMS += ctrlaltdel fsfreeze fstrim usrbin_exec_PROGRAMS += cytune setarch usrsbin_exec_PROGRAMS += ldattach tunelp rtcwake dist_man_MANS += dmesg.1 ctrlaltdel.8 cytune.8 setarch.8 \ - ldattach.8 tunelp.8 rtcwake.8 fsfreeze.8 + ldattach.8 tunelp.8 rtcwake.8 fsfreeze.8 fstrim.8 if HAVE_CPU_SET_T usrbin_exec_PROGRAMS += lscpu @@ -27,7 +27,7 @@ endif cytune_SOURCES = cytune.c cyclades.h tunelp_SOURCES = tunelp.c lp.h - +fstrim_SOURCES = fstrim.c $(top_srcdir)/lib/strutils.c if BUILD_FALLOCATE usrbin_exec_PROGRAMS += fallocate diff --git a/sys-utils/fstrim.8 b/sys-utils/fstrim.8 new file mode 100644 index 00000000..ae6ff8a1 --- /dev/null +++ b/sys-utils/fstrim.8 @@ -0,0 +1,84 @@ +.\" -*- nroff -*- +.TH FSTRIM 8 "Nov 2010" +.SH NAME +fstrim \- discard unused blocks on a mounted filesystem +.SH SYNOPSIS +.B fstrim +.RB [ \-o +.IR offset ] +.RB [ \-l +.IR length ] +.RB [ \-m +.IR minimum-extent ] +.RB [ \-v ] +.I mountpoint + +.SH DESCRIPTION +.B fstrim +is used on a mounted filesystem to discard (or "trim") blocks which are not in +use by the filesystem. This is useful for solid-state drives (SSDs) and +thinly-provisioned storage. +.PP +By default, +.B fstrim +will discard all unused blocks in the filesystem. Options may be used to +modify this behavior based on range or size, as explained below. +.PP +The +.I mountpoint +argument is the pathname of the directory where the filesystem +is mounted. + +.SH OPTIONS +The \fIoffset\fR, \fIlength\fR, and \fIminimum-free-extent\fR arguments may be +followed by binary (2^N) suffixes KiB, MiB, GiB, TiB, PiB and EiB (the "iB" is +optional, e.g. "K" has the same meaning as "KiB") or decimal (10^N) suffixes +KB, MB, GB, PB and EB. +.IP "\fB\-h, \-\-help\fP" +Print help and exit. +.IP "\fB\-o, \-\-offset\fP \fIoffset\fP" +Byte offset in filesystem from which to begin searching for free blocks +to discard. Default value is zero, starting at the beginning of the +filesystem. +.IP "\fB\-l, \-\-length\fP \fIlength\fP" +Number of bytes after starting point to search for free blocks to discard. +If the specified value extends past the end of the filesystem, +.B fstrim +will stop at the filesystem size boundary. Default value extends to the end +of the filesystem. +.IP "\fB\-m, \-\-minimum\fP \fIminimum-free-extent\fP" +Minimum contiguous free range to discard, in bytes. (This value is internally +rounded up to a multiple of the filesystem block size). Free ranges smaller +than this will be ignored. By increasing this value, the fstrim operation +will complete more quickly for filesystems with badly fragmented freespace, +although not all blocks will be discarded. Default value is zero, discard +every free block. +.IP "\fB\-v, \-\-verbose\fP" +Verbose execution. When specified +.B fstrim +will output the number of bytes passed from the filesystem +down the block stack to the device for potential discard. This number is a +maximum discard amount from the storage device's perspective, because +.I FITRIM +ioctl called repeated will keep sending the same sectors for discard repeatedly. + +.B fstrim +will report the same potential discard bytes each time, but only sectors which +had been written to between the discards would actually be discarded by the +storage device. Further, the kernel block layer reserves the right to adjust +the discard ranges to fit raid stripe geometry, non-trim capable devices in a +LVM setup, etc. These reductions would not be reflected in fstrim_range.len +(the +.B --length +option). + +.SH AUTHOR +.nf +Lukas Czerner +Karel Zak +.fi +.SH SEE ALSO +.BR mount (8) +.SH AVAILABILITY +The fstrim command is part of the util-linux-ng package and is available from +ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/. diff --git a/sys-utils/fstrim.c b/sys-utils/fstrim.c new file mode 100644 index 00000000..fd83d311 --- /dev/null +++ b/sys-utils/fstrim.c @@ -0,0 +1,154 @@ +/* + * fstrim.c -- discard the part (or whole) of mounted filesystem. + * + * Copyright (C) 2010 Red Hat, Inc. All rights reserved. + * Written by Lukas Czerner + * Karel Zak + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * This program uses FITRIM ioctl to discard parts or the whole filesystem + * online (mounted). You can specify range (start and length) to be + * discarded, or simply discard while filesystem. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "nls.h" +#include "strutils.h" + +#ifndef FITRIM +struct fstrim_range { + uint64_t start; + uint64_t len; + uint64_t minlen; +}; +#define FITRIM _IOWR('X', 121, struct fstrim_range) +#endif + +static void __attribute__((__noreturn__)) usage(FILE *out) +{ + fprintf(out, _("Usage: %s [options] \n\nOptions:\n"), + program_invocation_short_name); + + fprintf(out, _( + " -h, --help this help\n" + " -o, --offset offset in bytes to discard from\n" + " -l, --length length of bytes to discard from the offset\n" + " -m, --minimum minimum extent length to discard\n" + " -v, --verbose print number of discarded bytes\n")); + + fprintf(out, _("\nFor more information see fstrim(1).\n")); + + exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); +} + +int main(int argc, char **argv) +{ + char *path; + int c, fd, verbose = 0; + struct fstrim_range range; + struct stat sb; + + struct option longopts[] = { + { "help", 0, 0, 'h' }, + { "offset", 1, 0, 'o' }, + { "length", 1, 0, 'l' }, + { "minimum", 1, 0, 'm' }, + { "verbose", 0, 0, 'v' }, + { NULL, 0, 0, 0 } + }; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + memset(&range, 0, sizeof(range)); + range.len = ULLONG_MAX; + + while ((c = getopt_long(argc, argv, "ho:l:m:v", longopts, NULL)) != -1) { + switch(c) { + case 'h': + usage(stdout); + break; + case 'l': + if (strtosize(optarg, &range.len)) + errx(EXIT_FAILURE, + _("failed to parse length: %s"), optarg); + break; + case 'o': + if (strtosize(optarg, &range.start)) + errx(EXIT_FAILURE, + _("failed to parse offset: %s"), optarg); + break; + case 'm': + if (strtosize(optarg, &range.minlen)) + errx(EXIT_FAILURE, + _("failed to parse minimal extend length: %s"), + optarg); + break; + case 'v': + verbose = 1; + break; + default: + usage(stderr); + break; + } + } + + if (optind == argc) + errx(EXIT_FAILURE, _("no mountpoint specified.")); + + path = argv[optind++]; + + if (optind != argc) { + warnx(_("unexpected number of arguments")); + usage(stderr); + } + + if (stat(path, &sb) == -1) + err(EXIT_FAILURE, _("%s: stat failed"), path); + if (!S_ISDIR(sb.st_mode)) + errx(EXIT_FAILURE, _("%s: not a directory"), path); + + fd = open(path, O_RDONLY); + if (fd < 0) + err(EXIT_FAILURE, _("%s: open failed"), path); + + if (ioctl(fd, FITRIM, &range)) { + int errsv = errno; + close(fd); + error(EXIT_FAILURE, errsv, _("%s: FITRIM ioctl failed"), path); + } + if (verbose) + printf(_("%s: %" PRIu64 " bytes was trimmed\n"), + path, range.len); + close(fd); + return EXIT_SUCCESS; +} -- cgit v1.2.3 From fcf67294309030651848d6d58226010ca21177b7 Mon Sep 17 00:00:00 2001 From: Marek Otahal Date: Fri, 26 Nov 2010 16:47:38 +0100 Subject: rtcwake: add 'show' mode for rtc alarm The 'show' mode prints information on current alarm setting. [kzak@redhat.com: - code clean up - don't setup alarm on 'disable' mode] Signed-off-by: Marek Otahal Signed-off-by: Karel Zak --- sys-utils/rtcwake.8 | 4 ++ sys-utils/rtcwake.c | 110 ++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 94 insertions(+), 20 deletions(-) diff --git a/sys-utils/rtcwake.8 b/sys-utils/rtcwake.8 index ee7af3a0..60f958a7 100644 --- a/sys-utils/rtcwake.8 +++ b/sys-utils/rtcwake.8 @@ -117,6 +117,10 @@ useful for debugging. .TP .B disable Disable previously set alarm. +.TP +.B show +Print alarm information in format: "alarm: off|on