diff options
Diffstat (limited to 'misc-utils')
| -rw-r--r-- | misc-utils/Makemodule.am | 19 | ||||
| -rw-r--r-- | misc-utils/blkid.c | 21 | ||||
| -rw-r--r-- | misc-utils/cal.1 | 22 | ||||
| -rw-r--r-- | misc-utils/cal.c | 666 | ||||
| -rw-r--r-- | misc-utils/findmnt.8 | 2 | ||||
| -rw-r--r-- | misc-utils/findmnt.c | 154 | ||||
| -rw-r--r-- | misc-utils/getopt.1 | 58 | ||||
| -rw-r--r-- | misc-utils/logger.1 | 61 | ||||
| -rw-r--r-- | misc-utils/logger.c | 96 | ||||
| -rw-r--r-- | misc-utils/look.1 | 2 | ||||
| -rw-r--r-- | misc-utils/lsblk.8 | 4 | ||||
| -rw-r--r-- | misc-utils/lsblk.c | 32 | ||||
| -rw-r--r-- | misc-utils/lslocks.8 | 2 | ||||
| -rw-r--r-- | misc-utils/lslocks.c | 4 | ||||
| -rw-r--r-- | misc-utils/mcookie.1 | 4 | ||||
| -rw-r--r-- | misc-utils/mcookie.c | 10 | ||||
| -rw-r--r-- | misc-utils/namei.1 | 4 | ||||
| -rw-r--r-- | misc-utils/sd-daemon.c | 100 | ||||
| -rw-r--r-- | misc-utils/sd-daemon.h | 14 | ||||
| -rw-r--r-- | misc-utils/uuidd.c | 81 | ||||
| -rw-r--r-- | misc-utils/wipefs.8 | 19 | ||||
| -rw-r--r-- | misc-utils/wipefs.c | 136 |
22 files changed, 840 insertions, 671 deletions
diff --git a/misc-utils/Makemodule.am b/misc-utils/Makemodule.am index a615047f8..686fb1574 100644 --- a/misc-utils/Makemodule.am +++ b/misc-utils/Makemodule.am @@ -10,19 +10,11 @@ if !HAVE_LANGINFO cal_SOURCES += lib/langinfo.c endif -cal_LDADD = $(LDADD) - -if HAVE_TINFO -cal_LDADD += -ltinfo @NCURSES_LIBS@ -else -if HAVE_NCURSES -cal_LDADD += @NCURSES_LIBS@ -else +cal_CFLAGS = $(AM_CFLAGS) $(NCURSES_CFLAGS) +cal_LDADD = $(LDADD) libcommon.la $(NCURSES_LIBS) $(TINFO_LIBS) if HAVE_TERMCAP cal_LDADD += -ltermcap endif -endif # !HAVE_NCURSES -endif # !HAVE_TINFO usrbin_exec_PROGRAMS += logger @@ -76,8 +68,9 @@ endif if BUILD_UUIDD usrsbin_exec_PROGRAMS += uuidd dist_man_MANS += misc-utils/uuidd.8 -uuidd_LDADD = $(LDADD) libuuid.la -uuidd_CFLAGS = $(AM_CFLAGS) -I$(ul_libuuid_incdir) +uuidd_LDADD = $(LDADD) libuuid.la libcommon.la +uuidd_CFLAGS = $(DAEMON_CFLAGS) $(AM_CFLAGS) -I$(ul_libuuid_incdir) +uuidd_LDFLAGS = $(DAEMON_LDFLAGS) $(AM_LDFLAGS) uuidd_SOURCES = misc-utils/uuidd.c if USE_SOCKET_ACTIVATION uuidd_SOURCES += misc-utils/sd-daemon.c misc-utils/sd-daemon.h @@ -153,7 +146,7 @@ endif usrbin_exec_PROGRAMS += getopt dist_man_MANS += misc-utils/getopt.1 getopt_SOURCES = misc-utils/getopt.c -getoptexampledir = $(datadir)/getopt/ +getoptexampledir = $(docdir)/getopt/ dist_getoptexample_SCRIPTS = \ misc-utils/getopt-parse.bash \ misc-utils/getopt-parse.tcsh diff --git a/misc-utils/blkid.c b/misc-utils/blkid.c index 00b4f1c9d..b3eade56b 100644 --- a/misc-utils/blkid.c +++ b/misc-utils/blkid.c @@ -51,8 +51,6 @@ extern int optind; #include "ttyutils.h" #include "xalloc.h" -const char *progname = "blkid"; - int raw_chars; static void print_version(FILE *out) @@ -98,7 +96,7 @@ static void usage(int error) " -O <offset> probe at the given offset\n" " -u <list> filter by \"usage\" (e.g. -u filesystem,raid)\n" " -n <list> filter by filesystem type (e.g. -n vfat,ext3)\n" - "\n", progname); + "\n", program_invocation_short_name); exit(error); } @@ -106,8 +104,10 @@ static void usage(int error) /* * This function does "safe" printing. It will convert non-printable * ASCII characters using '^' and M- notation. + * + * If 'esc' is defined then escape all chars from esc by \. */ -static void safe_print(const char *cp, int len) +static void safe_print(const char *cp, int len, const char *esc) { unsigned char ch; @@ -124,7 +124,9 @@ static void safe_print(const char *cp, int len) if ((ch < 32) || (ch == 0x7f)) { fputc('^', stdout); ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */ - } + + } else if (esc && strchr(esc, ch)) + fputc('\\', stdout); } fputc(ch, stdout); } @@ -255,6 +257,9 @@ static void print_udev_format(const char *name, const char *value) blkid_encode_string(value, enc, sizeof(enc)); printf("ID_FS_%s_ENC=%s\n", name, enc); + } else if (!strcmp(name, "PTUUID")) { + printf("ID_PART_TABLE_UUID=%s\n", value); + } else if (!strcmp(name, "PTTYPE")) { printf("ID_PART_TABLE_TYPE=%s\n", value); @@ -301,7 +306,7 @@ static void print_value(int output, int num, const char *devname, printf("DEVNAME=%s\n", devname); fputs(name, stdout); fputs("=", stdout); - safe_print(value, valsz); + safe_print(value, valsz, NULL); fputs("\n", stdout); } else { @@ -309,7 +314,7 @@ static void print_value(int output, int num, const char *devname, printf("%s: ", devname); fputs(name, stdout); fputs("=\"", stdout); - safe_print(value, valsz); + safe_print(value, valsz, "\""); fputs("\" ", stdout); } } @@ -594,7 +599,7 @@ static int list_to_usage(const char *list, int *flag) return mask; err: *flag = 0; - fprintf(stderr, "unknown kerword in -u <list> argument: '%s'\n", + fprintf(stderr, "unknown keyword in -u <list> argument: '%s'\n", word ? word : list); exit(BLKID_EXIT_OTHER); } diff --git a/misc-utils/cal.1 b/misc-utils/cal.1 index 4d9b3d165..7e8e6baf1 100644 --- a/misc-utils/cal.1 +++ b/misc-utils/cal.1 @@ -51,7 +51,7 @@ Display single month output. (This is the default.) .TP \fB\-3\fR, \fB\-\-three\fR -Display prev/current/next month output. +Display three months spanning the date. .TP \fB\-s\fR, \fB\-\-sunday\fR Display Sunday as the first day of the week. @@ -63,15 +63,29 @@ Display Monday as the first day of the week. Display Julian dates (days one-based, numbered from January 1). .TP \fB\-y\fR, \fB\-\-year\fR -Display a calendar for the current year. +Display a calendar for the whole year. +.TP +\fB\-\-color\fR [\fIwhen\fR] +Colorize output. The +.I when +can be +.IR never , +.IR auto , +or +.IR always . +Never will turn off colorizing in all situations. Auto is default, and +it will make colorizing to be in use if output is done to terminal. +Always will allow colors to be outputed when +.B cal +outputs to pipe, or is called from a script. .TP \fB\-V\fR, \fB\-\-version\fR Display version information and exit. .TP \fB\-h\fR, \fB\-\-help\fR -Display help screen and exit. +Display help text and exit. .SH PARAMETERS -A single parameter specifies the year (1 - 9999) to be displayed; note the +A single parameter specifies the year to be displayed; note the year must be fully specified: .B "cal 89" will not display a calendar for 1989. diff --git a/misc-utils/cal.c b/misc-utils/cal.c index 1eeeea8a0..f91bc8ebe 100644 --- a/misc-utils/cal.c +++ b/misc-utils/cal.c @@ -68,127 +68,152 @@ #include "c.h" #include "closestream.h" +#include "colors.h" #include "nls.h" #include "mbsalign.h" #include "strutils.h" #if defined(HAVE_LIBNCURSES) || defined(HAVE_LIBNCURSESW) - -#ifdef HAVE_NCURSES_H -#include <ncurses.h> -#elif defined(HAVE_NCURSES_NCURSES_H) -#include <ncurses/ncurses.h> -#endif - -#include <term.h> /* include after <curses.h> */ - -static void -my_setupterm(const char *term, int fildes, int *errret) { - setupterm((char*)term, fildes, errret); +# ifdef HAVE_NCURSES_H +# include <ncurses.h> +# elif defined(HAVE_NCURSES_NCURSES_H) +# include <ncurses/ncurses.h> +# endif +# include <term.h> + +static void my_setupterm(const char *term, int fildes, int *errret) +{ + setupterm((char *)term, fildes, errret); } -static void -my_putstring(char *s) { - putp(s); +static void my_putstring(char *s) +{ + putp(s); } -static const char * -my_tgetstr(char *s __attribute__ ((__unused__)), char *ss) { - const char* ret = tigetstr(ss); - if (!ret || ret==(char*)-1) - return ""; - else +static const char *my_tgetstr(char *s __attribute__((__unused__)), char *ss) +{ + const char *ret = tigetstr(ss); + if (!ret || ret == (char *)-1) + return ""; + return ret; } #elif defined(HAVE_LIBTERMCAP) +# include <termcap.h> -#include <termcap.h> +static char termbuffer[4096]; +static char tcbuffer[4096]; +static char *strbuf = termbuffer; -char termbuffer[4096]; -char tcbuffer[4096]; -char *strbuf = termbuffer; - -static void -my_setupterm(const char *term, int fildes, int *errret) { - *errret = tgetent(tcbuffer, term); +static void my_setupterm(const char *term, int fildes __attribute__((__unused__)), int *errret) +{ + *errret = tgetent(tcbuffer, term); } -static void -my_putstring(char *s) { - tputs (s, 1, putchar); +static void my_putstring(char *s) +{ + tputs(s, 1, putchar); } -static const char * -my_tgetstr(char *s, char *ss __attribute__ ((__unused__))) { - const char* ret = tgetstr(s, &strbuf); - if (!ret) - return ""; - else +static const char *my_tgetstr(char *s, char *ss __attribute__((__unused__))) +{ + const char *ret = tgetstr(s, &strbuf); + if (!ret) + return ""; + return ret; } -#else /* ! (HAVE_LIBTERMCAP || HAVE_LIBNCURSES || HAVE_LIBNCURSESW) */ +#else /* ! (HAVE_LIBTERMCAP || HAVE_LIBNCURSES || HAVE_LIBNCURSESW) */ -static void -my_putstring(char *s) { - fputs(s, stdout); +static void my_putstring(char *s) +{ + fputs(s, stdout); } -#endif +#endif /* end of LIBTERMCAP / NCURSES */ +#if defined(HAVE_LIBNCURSES) || defined(HAVE_LIBNCURSESW) || defined(HAVE_LIBTERMCAP) +static const char *term=""; +static int Slen; /* strlen of Senter+Sexit */ +#endif -const char *term=""; -const char *Senter="", *Sexit="";/* enter and exit standout mode */ -int Slen; /* strlen of Senter+Sexit */ -char *Hrow; /* pointer to highlighted row in month */ +static const char *Senter="", *Sexit="";/* enter and exit standout mode */ +static char *Hrow; /* pointer to highlighted row in month */ #include "widechar.h" /* allow compile-time define to over-ride default */ #ifndef NUM_MONTHS -#define NUM_MONTHS 1 +# define NUM_MONTHS 1 #endif #if ( NUM_MONTHS != 1 && NUM_MONTHS !=3 ) -#error NUM_MONTHS must be 1 or 3 +# error NUM_MONTHS must be 1 or 3 #endif -#define THURSDAY 4 /* for reformation */ -#define SATURDAY 6 /* 1 Jan 1 was a Saturday */ +enum { + SUNDAY = 0, + MONDAY, + TUESDAY, + WEDNESDAY, + THURSDAY, + FRIDAY, + SATURDAY, + DAYS_IN_WEEK, + NONEDAY +}; +#define FIRST_WEEKDAY SATURDAY /* Jan 1st, 1 was a Saturday */ +#define REFORMATION_YEAR 1752 /* Signed-off-by: Lord Chesterfield */ +#define REFORMATION_MONTH 9 /* September */ #define FIRST_MISSING_DAY 639799 /* 3 Sep 1752 */ #define NUMBER_MISSING_DAYS 11 /* 11 day correction */ +#define DAYS_IN_YEAR 365 /* the common case, leap years are calculated */ +#define MONTHS_IN_YEAR 12 +#define DAYS_IN_MONTH 31 #define MAXDAYS 42 /* slots in a month array */ #define SPACE -1 /* used in day array */ -static int days_in_month[2][13] = { +#define SMALLEST_YEAR 1 + +#define DAY_LEN 3 /* 3 spaces per day */ +#define WEEK_LEN (DAYS_IN_WEEK * DAY_LEN) +#define HEAD_SEP 2 +#define MONTH_COLS 3 /* month columns in year view */ + +#define J_DAY_LEN 4 /* 4 spaces per day */ +#define J_WEEK_LEN (DAYS_IN_WEEK * J_DAY_LEN) +#define J_HEAD_SEP 2 +#define J_MONTH_COLS 2 + +#define TODAY_FLAG 0x400 /* flag day for highlighting */ + +#define FMT_ST_LINES 9 +#define FMT_ST_CHARS 300 /* 90 suffices in most locales */ +struct fmt_st +{ + char s[FMT_ST_LINES][FMT_ST_CHARS]; +}; + +static const int days_in_month[2][13] = { {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, }; -#define SEP1752_OFS 4 /* sep1752[4] is a Sunday */ - -/* 1 Sep 1752 is represented by sep1752[6] and j_sep1752[6] */ -int sep1752[MAXDAYS+6] = { - SPACE, SPACE, SPACE, SPACE, +/* September 1752 is special, and has static assignments for both date + * and Julian representations. */ +static const int d_sep1752[MAXDAYS / 2] = { SPACE, SPACE, 1, 2, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, - SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, - SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, - SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, - SPACE, SPACE -}, j_sep1752[MAXDAYS+6] = { - SPACE, SPACE, SPACE, SPACE, + 24, 25, 26, 27, 28, 29, 30 +}, j_sep1752[MAXDAYS / 2] = { SPACE, SPACE, 245, 246, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - 268, 269, 270, 271, 272, 273, 274, - SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, - SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, - SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, - SPACE, SPACE + 268, 269, 270, 271, 272, 273, 274 }, empty[MAXDAYS] = { SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, @@ -198,71 +223,44 @@ int sep1752[MAXDAYS+6] = { SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE }; -#define DAY_LEN 3 /* 3 spaces per day */ -#define J_DAY_LEN 4 /* 4 spaces per day */ -#define WEEK_LEN 21 /* 7 days * 3 characters */ -#define J_WEEK_LEN 28 /* 7 days * 4 characters */ -#define HEAD_SEP 2 /* spaces between day headings */ -#define J_HEAD_SEP 2 /* utf-8 can have up to 6 bytes per char; and an extra byte for ending \0 */ -char day_headings[WEEK_LEN*6+1]; -/* weekstart = 1 => " M Tu W Th F S S " */ -char j_day_headings[J_WEEK_LEN*6+1]; +static char day_headings[J_WEEK_LEN * 6 + 1]; /* weekstart = 1 => " M Tu W Th F S S " */ -const char *full_month[12]; - -/* leap year -- account for gregorian reformation in 1752 */ -#define leap_year(yr) \ - ((yr) <= 1752 ? !((yr) % 4) : \ - (!((yr) % 4) && ((yr) % 100)) || !((yr) % 400)) - -/* number of centuries since 1700, not inclusive */ -#define centuries_since_1700(yr) \ - ((yr) > 1700 ? (yr) / 100 - 17 : 0) - -/* number of centuries since 1700 whose modulo of 400 is 0 */ -#define quad_centuries_since_1700(yr) \ - ((yr) > 1600 ? ((yr) - 1600) / 400 : 0) - -/* number of leap years between year 1 and this year, not inclusive */ -#define leap_years_since_year_1(yr) \ - ((yr) / 4 - centuries_since_1700(yr) + quad_centuries_since_1700(yr)) +static const char *full_month[MONTHS_IN_YEAR]; /* 0 => sunday, 1 => monday */ -int weekstart=0; -int julian; - -#define TODAY_FLAG 0x400 /* flag day for highlighting */ - -#define FMT_ST_LINES 8 -#define FMT_ST_CHARS 300 /* 90 suffices in most locales */ -struct fmt_st -{ - char s[FMT_ST_LINES][FMT_ST_CHARS]; -}; - -char * ascii_day(char *, int); -int center_str(const char* src, char* dest, size_t dest_size, size_t width); -void center(const char *, size_t, int); -void day_array(int, int, int, int *); -int day_in_week(int, int, int); -int day_in_year(int, int, int); -void yearly(int, int); -void j_yearly(int, int); -void do_monthly(int, int, int, struct fmt_st*); -void monthly(int, int, int); -void monthly3(int, int, int); -void trim_trailing_spaces(char *); +static int weekstart = SUNDAY; +static int julian; + +/* function prototypes */ +static int leap_year(long year); +static char * ascii_day(char *, int); +static int center_str(const char* src, char* dest, size_t dest_size, size_t width); +static void center(const char *, size_t, int); +static void day_array(int, int, long, int *); +static int day_in_week(int, int, long); +static int day_in_year(int, int, long); +static void yearly(int, long, int); +static int do_monthly(int, int, long, struct fmt_st*, int); +static void monthly(int, int, long); +static int two_header_lines(int month, long year); +static void monthly3(int, int, long); static void __attribute__ ((__noreturn__)) usage(FILE * out); -void headers_init(void); +static void headers_init(int); -int -main(int argc, char **argv) { +int main(int argc, char **argv) +{ struct tm *local_time; time_t now; - int ch, day, month, year, yflag; + int ch, day = 0, month = 0, yflag = 0; + long year; int num_months = NUM_MONTHS; + int colormode = UL_COLORMODE_AUTO; + + enum { + OPT_COLOR = CHAR_MAX + 1 + }; static const struct option longopts[] = { {"one", no_argument, NULL, '1'}, @@ -271,6 +269,7 @@ main(int argc, char **argv) { {"monday", no_argument, NULL, 'm'}, {"julian", no_argument, NULL, 'j'}, {"year", no_argument, NULL, 'y'}, + {"color", optional_argument, NULL, OPT_COLOR}, {"version", no_argument, NULL, 'V'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0} @@ -284,7 +283,7 @@ main(int argc, char **argv) { #if defined(HAVE_LIBNCURSES) || defined(HAVE_LIBNCURSESW) || defined(HAVE_LIBTERMCAP) if ((term = getenv("TERM"))) { int ret; - my_setupterm(term, 1, &ret); + my_setupterm(term, STDOUT_FILENO, &ret); if (ret > 0) { Senter = my_tgetstr("so","smso"); Sexit = my_tgetstr("se","rmso"); @@ -324,11 +323,10 @@ main(int argc, char **argv) { wfd = val.word; wfd = day_in_week(wfd % 100, (wfd / 100) % 100, wfd / (100 * 100)); - weekstart = (wfd + *nl_langinfo(_NL_TIME_FIRST_WEEKDAY) - 1) % 7; + weekstart = (wfd + *nl_langinfo(_NL_TIME_FIRST_WEEKDAY) - 1) % DAYS_IN_WEEK; } #endif - yflag = 0; while ((ch = getopt_long(argc, argv, "13mjsyVh", longopts, NULL)) != -1) switch(ch) { case '1': @@ -338,10 +336,10 @@ main(int argc, char **argv) { num_months = 3; break; case 's': - weekstart = 0; /* default */ + weekstart = SUNDAY; /* default */ break; case 'm': - weekstart = 1; + weekstart = MONDAY; break; case 'j': julian = 1; @@ -349,6 +347,11 @@ main(int argc, char **argv) { case 'y': yflag = 1; break; + case OPT_COLOR: + if (optarg) + colormode = colormode_or_err(optarg, + _("unsupported color mode")); + break; case 'V': printf(UTIL_LINUX_VERSION); return EXIT_SUCCESS; @@ -364,28 +367,27 @@ main(int argc, char **argv) { time(&now); local_time = localtime(&now); - day = month = year = 0; switch(argc) { case 3: day = strtos32_or_err(*argv++, _("illegal day value")); - if (day < 1 || 31 < day) - errx(EXIT_FAILURE, _("illegal day value: use 1-%d"), 31); + if (day < 1 || DAYS_IN_MONTH < day) + errx(EXIT_FAILURE, _("illegal day value: use 1-%d"), DAYS_IN_MONTH); /* FALLTHROUGH */ case 2: month = strtos32_or_err(*argv++, _("illegal month value: use 1-12")); - if (month < 1 || 12 < month) + if (month < 1 || MONTHS_IN_YEAR < month) errx(EXIT_FAILURE, _("illegal month value: use 1-12")); /* FALLTHROUGH */ case 1: - year = strtos32_or_err(*argv++, _("illegal year value: use 1-9999")); - if (year < 1 || 9999 < year) - errx(EXIT_FAILURE, _("illegal year value: use 1-9999")); + year = strtol_or_err(*argv++, _("illegal year value")); + if (year < SMALLEST_YEAR) + errx(EXIT_FAILURE, _("illegal year value: use positive integer")); if (day) { int dm = days_in_month[leap_year(year)][month]; if (day > dm) errx(EXIT_FAILURE, _("illegal day value: use 1-%d"), dm); day = day_in_year(day, month, year); - } else if ((local_time->tm_year + 1900) == year) { + } else if ((long) (local_time->tm_year + 1900) == year) { day = local_time->tm_yday + 1; } if (!month) @@ -399,15 +401,13 @@ main(int argc, char **argv) { default: usage(stderr); } - headers_init(); + headers_init(julian); - if (!isatty(1)) - day = 0; /* don't highlight */ + if (!colors_init(colormode)) + day = 0; - if (yflag && julian) - j_yearly(day, year); - else if (yflag) - yearly(day, year); + if (yflag) + yearly(day, year, julian); else if (num_months == 1) monthly(day, month, year); else if (num_months == 3) @@ -416,128 +416,157 @@ main(int argc, char **argv) { return EXIT_SUCCESS; } -void headers_init(void) +/* leap year -- account for gregorian reformation in 1752 */ +static int leap_year(long year) { - int i, wd; - char *cur_dh = day_headings, *cur_j_dh = j_day_headings; + if (year <= REFORMATION_YEAR) + return !(year % 4); + else + return ( !(year % 4) && (year % 100) ) || !(year % 400); +} - strcpy(day_headings, ""); - strcpy(j_day_headings, ""); +static void headers_init(int julian) +{ + size_t i, wd, spaces = julian ? J_DAY_LEN - 1 : DAY_LEN - 1; + char *cur_dh = day_headings; - for (i = 0; i < 7; i++) { - ssize_t space_left; - wd = (i + weekstart) % 7; + for (i = 0; i < DAYS_IN_WEEK; i++) { + size_t space_left; + wd = (i + weekstart) % DAYS_IN_WEEK; if (i) strcat(cur_dh++, " "); - space_left = - sizeof(day_headings) - (cur_dh - day_headings); - if (space_left <= 2) - break; - cur_dh += - center_str(nl_langinfo(ABDAY_1 + wd), cur_dh, - space_left, 2); + space_left = sizeof(day_headings) - (cur_dh - day_headings); - if (i) - strcat(cur_j_dh++, " "); - space_left = - sizeof(j_day_headings) - (cur_j_dh - j_day_headings); - if (space_left <= 3) + if (space_left <= spaces) break; - cur_j_dh += - center_str(nl_langinfo(ABDAY_1 + wd), cur_j_dh, - space_left, 3); + cur_dh += center_str(nl_langinfo(ABDAY_1 + wd), cur_dh, + space_left, spaces); } - for (i = 0; i < 12; i++) + for (i = 0; i < MONTHS_IN_YEAR; i++) full_month[i] = nl_langinfo(MON_1 + i); } -void -do_monthly(int day, int month, int year, struct fmt_st *out) { +static int do_monthly(int day, int month, long year, + struct fmt_st *out, int header_hint) +{ int col, row, days[MAXDAYS]; char *p, lineout[FMT_ST_CHARS]; - int width = (julian ? J_WEEK_LEN : WEEK_LEN) - 1; + size_t width = (julian ? J_WEEK_LEN : WEEK_LEN) - 1; + int pos = 0; day_array(day, month, year, days); - /* - * %s is the month name, %d the year number. - * you can change the order and/or add something here; eg for - * Basque the translation should be: "%2$dko %1$s", and - * the Vietnamese should be "%s na(m %d", etc. - */ - snprintf(lineout, sizeof(lineout), _("%s %d"), + if (header_hint < 0) + header_hint = two_header_lines(month, year); + if (header_hint) { + snprintf(lineout, sizeof(lineout), _("%s"), full_month[month - 1]); + center_str(lineout, out->s[pos], ARRAY_SIZE(out->s[pos]), width); + pos++; + snprintf(lineout, sizeof(lineout), _("%ld"), year); + center_str(lineout, out->s[pos], ARRAY_SIZE(out->s[pos]), width); + pos++; + } else { + /* TRANSLATORS: %s is the month name, %ld the year number. + * You can change the order and/or add something here; + * e.g. for Basque the translation should be "%2$ldko %1$s". + */ + snprintf(lineout, sizeof(lineout), _("%s %ld"), full_month[month - 1], year); - center_str(lineout, out->s[0], ARRAY_SIZE(out->s[0]), width); + center_str(lineout, out->s[pos], ARRAY_SIZE(out->s[pos]), width); + pos++; + } - snprintf(out->s[1], FMT_ST_CHARS, "%s", - julian ? j_day_headings : day_headings); - for (row = 0; row < 6; row++) { + snprintf(out->s[pos++], FMT_ST_CHARS, "%s", day_headings); + for (row = 0; row < DAYS_IN_WEEK - 1; row++) { int has_hl = 0; - for (col = 0, p = lineout; col < 7; col++) { - int xd = days[row * 7 + col]; + for (col = 0, p = lineout; col < DAYS_IN_WEEK; col++) { + int xd = days[row * DAYS_IN_WEEK + col]; if (xd != SPACE && (xd & TODAY_FLAG)) has_hl = 1; p = ascii_day(p, xd); } *p = '\0'; - trim_trailing_spaces(lineout); - snprintf(out->s[row+2], FMT_ST_CHARS, "%s", lineout); + snprintf(out->s[row+pos], FMT_ST_CHARS, "%s", lineout); if (has_hl) - Hrow = out->s[row+2]; + Hrow = out->s[row+pos]; } + pos += row; + return pos; } -void -monthly(int day, int month, int year) { - int i; +static void monthly(int day, int month, long year) +{ + int i, rows; struct fmt_st out; - do_monthly(day, month, year, &out); - for (i = 0; i < FMT_ST_LINES; i++) { + rows = do_monthly(day, month, year, &out, -1); + for (i = 0; i < rows; i++) { my_putstring(out.s[i]); my_putstring("\n"); } } -void -monthly3(int day, int month, int year) { +static int two_header_lines(int month, long year) +{ + char lineout[FMT_ST_CHARS]; + size_t width = (julian ? J_WEEK_LEN : WEEK_LEN) - 1; + size_t len; + snprintf(lineout, sizeof(lineout), "%ld", year); + len = strlen(lineout); + len += strlen(full_month[month - 1]) + 1; + if (width < len) + return 1; + return 0; +} + +static void monthly3(int day, int month, long year) +{ char lineout[FMT_ST_CHARS]; int i; - int width; + int width, rows, two_lines; struct fmt_st out_prev; struct fmt_st out_curm; struct fmt_st out_next; - int prev_month, prev_year; - int next_month, next_year; + int prev_month, next_month; + long prev_year, next_year; + memset(&out_prev, 0, sizeof(struct fmt_st)); + memset(&out_curm, 0, sizeof(struct fmt_st)); + memset(&out_next, 0, sizeof(struct fmt_st)); if (month == 1) { - prev_month = 12; + prev_month = MONTHS_IN_YEAR; prev_year = year - 1; } else { prev_month = month - 1; prev_year = year; } - if (month == 12) { + if (month == MONTHS_IN_YEAR) { next_month = 1; next_year = year + 1; } else { next_month = month + 1; next_year = year; } - - do_monthly(day, prev_month, prev_year, &out_prev); - do_monthly(day, month, year, &out_curm); - do_monthly(day, next_month, next_year, &out_next); + two_lines = two_header_lines(prev_month, prev_year); + two_lines += two_header_lines(month, year); + two_lines += two_header_lines(next_month, next_year); + if (0 < two_lines) + rows = FMT_ST_LINES; + else + rows = FMT_ST_LINES - 1; + do_monthly(day, prev_month, prev_year, &out_prev, two_lines); + do_monthly(day, month, year, &out_curm, two_lines); + do_monthly(day, next_month, next_year, &out_next, two_lines); width = (julian ? J_WEEK_LEN : WEEK_LEN) -1; - for (i = 0; i < 2; i++) { + for (i = 0; i < (two_lines ? 3 : 2); i++) { snprintf(lineout, sizeof(lineout), "%s %s %s\n", out_prev.s[i], out_curm.s[i], out_next.s[i]); my_putstring(lineout); } - for (i = 2; i < FMT_ST_LINES; i++) { + for (i = two_lines ? 3 : 2; i < rows; i++) { int w1, w2, w3; w1 = w2 = w3 = width; @@ -547,7 +576,7 @@ monthly3(int day, int month, int year) { w2 += (out_curm.s[i] == Hrow ? Slen : 0); w3 += (out_next.s[i] == Hrow ? Slen : 0); #endif - snprintf(lineout, sizeof(lineout), "%-*s %-*s %-*s\n", + snprintf(lineout, sizeof(lineout), "%-*s %-*s %-*s\n", w1, out_prev.s[i], w2, out_curm.s[i], w3, out_next.s[i]); @@ -556,79 +585,62 @@ monthly3(int day, int month, int year) { } } -void -j_yearly(int day, int year) { - int col, *dp, i, month, row, which_cal; - int days[12][MAXDAYS]; - char *p, lineout[80]; - - snprintf(lineout, sizeof(lineout), "%d", year); - center(lineout, J_WEEK_LEN*2 + J_HEAD_SEP - 1, 0); - my_putstring("\n\n"); - - for (i = 0; i < 12; i++) - day_array(day, i + 1, year, days[i]); - memset(lineout, ' ', sizeof(lineout) - 1); - lineout[sizeof(lineout) - 1] = '\0'; - for (month = 0; month < 12; month += 2) { - center(full_month[month], J_WEEK_LEN-1, J_HEAD_SEP+1); - center(full_month[month + 1], J_WEEK_LEN-1, 0); - snprintf(lineout, sizeof(lineout), - "\n%s%*s %s\n", j_day_headings, J_HEAD_SEP, "", - j_day_headings); - my_putstring(lineout); - for (row = 0; row < 6; row++) { - p = lineout; - for (which_cal = 0; which_cal < 2; which_cal++) { - dp = &days[month + which_cal][row * 7]; - for (col = 0; col < 7; col++) - p = ascii_day(p, *dp++); - p += sprintf(p, " "); - } - *p = '\0'; - trim_trailing_spaces(lineout); - my_putstring(lineout); - my_putstring("\n"); - } - } - my_putstring("\n"); -} - -void -yearly(int day, int year) { +static void yearly(int day, long year, int julian) +{ int col, *dp, i, month, row, which_cal; - int days[12][MAXDAYS]; + int maxrow, sep_len, week_len; + int days[MONTHS_IN_YEAR][MAXDAYS]; char *p; + /* three weeks + separators + \0 */ char lineout[ sizeof(day_headings) + 2 + sizeof(day_headings) + 2 + sizeof(day_headings) + 1 ]; - snprintf(lineout, sizeof(lineout), "%d", year); - center(lineout, WEEK_LEN*3 + HEAD_SEP*2 - 1, 0); + if (julian) { + maxrow = J_MONTH_COLS; + sep_len = J_HEAD_SEP; + week_len = J_WEEK_LEN; + } else { + maxrow = MONTH_COLS; + sep_len = HEAD_SEP; + week_len = WEEK_LEN; + } + snprintf(lineout, sizeof(lineout), "%ld", year); + /* 2013-04-28: The -1 near sep_len makes year header to be + * aligned exactly how it has been aligned for long time, but it + * is unexplainable. */ + center(lineout, (week_len + sep_len) * maxrow - sep_len - 1, 0); my_putstring("\n\n"); - for (i = 0; i < 12; i++) + for (i = 0; i < MONTHS_IN_YEAR; i++) day_array(day, i + 1, year, days[i]); - memset(lineout, ' ', sizeof(lineout) - 1); - lineout[sizeof(lineout) - 1] = '\0'; - for (month = 0; month < 12; month += 3) { - center(full_month[month], WEEK_LEN-1, HEAD_SEP+1); - center(full_month[month + 1], WEEK_LEN-1, HEAD_SEP+1); - center(full_month[month + 2], WEEK_LEN-1, 0); - snprintf(lineout, sizeof(lineout), - "\n%s%*s %s%*s %s\n", day_headings, HEAD_SEP, - "", day_headings, HEAD_SEP, "", day_headings); + + for (month = 0; month < MONTHS_IN_YEAR; month += maxrow) { + center(full_month[month], week_len - 1, sep_len + 1); + if (julian) { + center(full_month[month + 1], week_len - 1, 0); + } else { + center(full_month[month + 1], week_len - 1, sep_len + 1); + center(full_month[month + 2], week_len - 1, 0); + } + if (julian) + snprintf(lineout, sizeof(lineout), + "\n%s%*s %s\n", day_headings, sep_len, "", day_headings); + else + snprintf(lineout, sizeof(lineout), + "\n%s%*s %s%*s %s\n", day_headings, sep_len, + "", day_headings, sep_len, "", day_headings); + my_putstring(lineout); - for (row = 0; row < 6; row++) { + for (row = 0; row < DAYS_IN_WEEK - 1; row++) { p = lineout; - for (which_cal = 0; which_cal < 3; which_cal++) { - dp = &days[month + which_cal][row * 7]; - for (col = 0; col < 7; col++) + for (which_cal = 0; which_cal < maxrow; which_cal++) { + dp = &days[month + which_cal][row * DAYS_IN_WEEK]; + for (col = 0; col < DAYS_IN_WEEK; col++) p = ascii_day(p, *dp++); p += sprintf(p, " "); } *p = '\0'; - trim_trailing_spaces(lineout); my_putstring(lineout); my_putstring("\n"); } @@ -643,23 +655,23 @@ yearly(int day, int year) { * out end to end. You would have 42 numbers or spaces. This routine * builds that array for any month from Jan. 1 through Dec. 9999. */ -void -day_array(int day, int month, int year, int *days) { +static void day_array(int day, int month, long year, int *days) +{ int julday, daynum, dw, dm; - int *d_sep1752; - - if (month == 9 && year == 1752) { - int sep1752_ofs = (weekstart + SEP1752_OFS) % 7; - d_sep1752 = julian ? j_sep1752 : sep1752; - memcpy(days, d_sep1752 + sep1752_ofs, MAXDAYS * sizeof(int)); - for (dm=0; dm<MAXDAYS; dm++) - if (j_sep1752[dm + sep1752_ofs] == day) + const int *sep1752; + + memcpy(days, empty, MAXDAYS * sizeof(int)); + if (year == REFORMATION_YEAR && month == REFORMATION_MONTH) { + sep1752 = julian ? j_sep1752 : d_sep1752; + memcpy(days, sep1752 + weekstart, + ((MAXDAYS / 2) - weekstart) * sizeof(int)); + for (dm = 0; dm < MAXDAYS / 2; dm++) + if (j_sep1752[dm] == day) days[dm] |= TODAY_FLAG; return; } - memcpy(days, empty, MAXDAYS * sizeof(int)); dm = days_in_month[leap_year(year)][month]; - dw = (day_in_week(1, month, year) - weekstart + 7) % 7; + dw = (day_in_week(1, month, year) - weekstart + DAYS_IN_WEEK) % DAYS_IN_WEEK; julday = day_in_year(1, month, year); daynum = julian ? julday : 1; while (dm--) { @@ -674,8 +686,8 @@ day_array(int day, int month, int year, int *days) { * day_in_year -- * return the 1 based day number within the year */ -int -day_in_year(int day, int month, int year) { +static int day_in_year(int day, int month, long year) +{ int i, leap; leap = leap_year(year); @@ -688,24 +700,37 @@ day_in_year(int day, int month, int year) { * day_in_week * return the 0 based day number for any date from 1 Jan. 1 to * 31 Dec. 9999. Assumes the Gregorian reformation eliminates - * 3 Sep. 1752 through 13 Sep. 1752. Returns Thursday for all - * missing days. + * 3 Sep. 1752 through 13 Sep. 1752, and returns invalid weekday + * during the period of 11 days. */ -int -day_in_week(int day, int month, int year) { - long temp; - - temp = (long)(year - 1) * 365 + leap_years_since_year_1(year - 1) - + day_in_year(day, month, year); - if (temp < FIRST_MISSING_DAY) - return ((temp - 1 + SATURDAY) % 7); - if (temp >= (FIRST_MISSING_DAY + NUMBER_MISSING_DAYS)) - return (((temp - 1 + SATURDAY) - NUMBER_MISSING_DAYS) % 7); - return (THURSDAY); +static int day_in_week(int d, int m, long y) +{ + static const int reform[] = { + SUNDAY, WEDNESDAY, TUESDAY, FRIDAY, SUNDAY, WEDNESDAY, + FRIDAY, MONDAY, THURSDAY, SATURDAY, TUESDAY, THURSDAY + }; + static const int old[] = { + FRIDAY, MONDAY, SUNDAY, WEDNESDAY, FRIDAY, MONDAY, + WEDNESDAY, SATURDAY, TUESDAY, THURSDAY, SUNDAY, TUESDAY + }; + if (y != 1753) + y -= m < 3; + else + y -= (m < 3) + 14; + if (REFORMATION_YEAR < y + || (y == REFORMATION_YEAR && 9 < m) + || (y == REFORMATION_YEAR && m == 9 && 13 < d)) + return (y + (y / 4) - (y / 100) + (y / 400) + reform[m - 1] + + d) % 7; + if (y < REFORMATION_YEAR + || (y == REFORMATION_YEAR && m < 9) + || (y == REFORMATION_YEAR && m == 9 && d < 3)) + return (y + y / 4 + old[m - 1] + d) % 7; + return NONEDAY; } -char * -ascii_day(char *p, int day) { +static char *ascii_day(char *p, int day) +{ int display, val; int highlight = 0; static char *aday[] = { @@ -752,34 +777,19 @@ ascii_day(char *p, int day) { return p; } -void -trim_trailing_spaces(char *s) -{ - char *p; - - for (p = s; *p; ++p) - continue; - while (p > s && isspace(*--p)) - continue; - if (p > s) - ++p; - *p = '\0'; -} - /* * Center string, handling multibyte characters appropriately. * In addition if the string is too large for the width it's truncated. * The number of trailing spaces may be 1 less than the number of leading spaces. */ -int -center_str(const char* src, char* dest, size_t dest_size, size_t width) +static int center_str(const char* src, char* dest, + size_t dest_size, size_t width) { return mbsalign(src, dest, dest_size, &width, MBS_ALIGN_CENTER, MBA_UNIBYTE_FALLBACK); } -void -center(const char *str, size_t len, int separate) +static void center(const char *str, size_t len, int separate) { char lineout[FMT_ST_CHARS]; @@ -794,20 +804,26 @@ center(const char *str, size_t len, int separate) static void __attribute__ ((__noreturn__)) usage(FILE * out) { - fputs(_("\nUsage:\n"), out); - fprintf(out, - _(" %s [options] [[[day] month] year]\n"), - program_invocation_short_name); - - fputs(_("\nOptions:\n"), out); - fputs(_(" -1, --one show only current month (default)\n" - " -3, --three show previous, current and next month\n" - " -s, --sunday Sunday as first day of week\n" - " -m, --monday Monday as first day of week\n" - " -j, --julian output Julian dates\n" - " -y, --year show whole current year\n" - " -V, --version display version information and exit\n" - " -h, --help display this help text and exit\n\n"), out); + fputs(USAGE_HEADER, out); + fprintf(out, _(" %s [options] [[[day] month] year]\n"), program_invocation_short_name); + + fputs(USAGE_SEPARATOR, out); + fputs(_("Display a calendar, or some part of it.\n"), out); + fputs(_("Without any arguments, display the current month.\n"), out); + + fputs(USAGE_OPTIONS, out); + fputs(_(" -1, --one show only a single month (default)\n"), out); + fputs(_(" -3, --three show three months spanning the date\n"), out); + fputs(_(" -s, --sunday Sunday as first day of week\n"), out); + fputs(_(" -m, --monday Monday as first day of week\n"), out); + fputs(_(" -j, --julian output Julian dates\n"), out); + fputs(_(" -y, --year show the whole year\n"), out); + fputs(_(" --color[=<when>] colorize messages (auto, always or never)\n"), out); + + fputs(USAGE_SEPARATOR, out); + fputs(USAGE_HELP, out); + fputs(USAGE_VERSION, out); + fprintf(out, USAGE_MAN_TAIL("cal(1)")); exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); } diff --git a/misc-utils/findmnt.8 b/misc-utils/findmnt.8 index 407636ea4..6b8e8d8fd 100644 --- a/misc-utils/findmnt.8 +++ b/misc-utils/findmnt.8 @@ -74,7 +74,7 @@ than once, then tree-like output is disabled (see the \fB\-\-list\fP option). Print the first matching filesystem only. .TP .BR \-h , " \-\-help" -Print help and exit. +Display help text and exit. .TP .BR \-i , " \-\-invert" Invert the sense of matching. diff --git a/misc-utils/findmnt.c b/misc-utils/findmnt.c index 4a3e760e7..f269246fc 100644 --- a/misc-utils/findmnt.c +++ b/misc-utils/findmnt.c @@ -133,7 +133,7 @@ static struct colinfo infos[FINDMNT_NCOLUMNS] = { [COL_ID] = { "ID", 2, TT_FL_RIGHT, N_("mount ID") }, [COL_OPT_FIELDS] = { "OPT-FIELDS", 0.10, TT_FL_TRUNC, N_("optional mount fields") }, [COL_PROPAGATION] = { "PROPAGATION", 0.10, 0, N_("VFS propagation flags") }, - [COL_FREQ] = { "FREQ", 1, TT_FL_RIGHT, N_("dump(8) frequency in days [fstab only]") }, + [COL_FREQ] = { "FREQ", 1, TT_FL_RIGHT, N_("dump(8) period in days [fstab only]") }, [COL_PASSNO] = { "PASSNO", 1, TT_FL_RIGHT, N_("pass number on parallel fsck(8) [fstab only]") } }; @@ -368,17 +368,24 @@ static char *get_tag_from_udev(const char *devname, int col) { struct udev_device *dev; const char *data = NULL; - char *res = NULL; + char *res = NULL, *path; if (!udev) udev = udev_new(); if (!udev) return NULL; + /* libudev don't like /dev/mapper/ symlinks */ + path = realpath(devname, NULL); + if (path) + devname = path; + if (strncmp(devname, "/dev/", 5) == 0) devname += 5; dev = udev_device_new_from_subsystem_sysname(udev, "block", devname); + free(path); + if (!dev) return NULL; @@ -410,12 +417,17 @@ static char *get_tag_from_udev(const char *devname, int col) #endif /* HAVE_LIBUDEV */ /* Returns LABEL or UUID */ -static const char *get_tag(struct libmnt_fs *fs, const char *tagname, int col) +static char *get_tag(struct libmnt_fs *fs, const char *tagname, int col +#ifndef HAVE_LIBUDEV + __attribute__((__unused__)) +#endif + ) { - const char *t, *v, *res = NULL; + const char *t, *v; + char *res = NULL; if (!mnt_fs_get_tag(fs, &t, &v) && !strcmp(t, tagname)) - res = v; + res = xstrdup(v); else { const char *dev = mnt_fs_get_source(fs); @@ -425,14 +437,18 @@ static const char *get_tag(struct libmnt_fs *fs, const char *tagname, int col) if (dev) res = get_tag_from_udev(dev, col); #endif - if (!res) + if (!res) { res = mnt_cache_find_tag_value(cache, dev, tagname); + if (res && cache) + /* don't return pointer to cache */ + res = xstrdup(res); + } } return res; } -static const char *get_vfs_attr(struct libmnt_fs *fs, int sizetype) +static char *get_vfs_attr(struct libmnt_fs *fs, int sizetype) { struct statvfs buf; uint64_t vfs_attr = 0; @@ -453,7 +469,7 @@ static const char *get_vfs_attr(struct libmnt_fs *fs, int sizetype) break; case COL_USEPERC: if (buf.f_blocks == 0) - return "-"; + return xstrdup("-"); xasprintf(&sizestr, "%.0f%%", (double)(buf.f_blocks - buf.f_bfree) / @@ -461,56 +477,54 @@ static const char *get_vfs_attr(struct libmnt_fs *fs, int sizetype) return sizestr; } - return vfs_attr == 0 ? "0" : + return vfs_attr == 0 ? xstrdup("0") : size_to_human_string(SIZE_SUFFIX_1LETTER, vfs_attr); } /* reads FS data from libmount */ -static const char *get_data(struct libmnt_fs *fs, int num) +static char *get_data(struct libmnt_fs *fs, int num) { - const char *str = NULL; - char *tmp; + char *str = NULL; int col_id = get_column_id(num); switch (col_id) { case COL_SOURCE: { const char *root = mnt_fs_get_root(fs); + const char *spec = mnt_fs_get_srcpath(fs); - str = mnt_fs_get_srcpath(fs); + if (spec && (flags & FL_CANONICALIZE)) + spec = mnt_resolve_path(spec, cache); + if (!spec) { + spec = mnt_fs_get_source(fs); - if (str && (flags & FL_CANONICALIZE)) - str = mnt_resolve_path(str, cache); - if (!str) { - str = mnt_fs_get_source(fs); - - if (str && (flags & FL_EVALUATE)) - str = mnt_resolve_spec(str, cache); - } - if (root && str && !(flags & FL_NOFSROOT) && strcmp(root, "/")) { - xasprintf(&tmp, "%s[%s]", str, root); - str = tmp; + if (spec && (flags & FL_EVALUATE)) + spec = mnt_resolve_spec(spec, cache); } + if (root && spec && !(flags & FL_NOFSROOT) && strcmp(root, "/")) + xasprintf(&str, "%s[%s]", spec, root); + else if (spec) + str = xstrdup(spec); break; } case COL_TARGET: - str = mnt_fs_get_target(fs); + str = xstrdup(mnt_fs_get_target(fs)); break; case COL_FSTYPE: - str = mnt_fs_get_fstype(fs); + str = xstrdup(mnt_fs_get_fstype(fs)); break; case COL_OPTIONS: - str = mnt_fs_get_options(fs); + str = xstrdup(mnt_fs_get_options(fs)); break; case COL_VFS_OPTIONS: - str = mnt_fs_get_vfs_options(fs); + str = xstrdup(mnt_fs_get_vfs_options(fs)); break; case COL_FS_OPTIONS: - str = mnt_fs_get_fs_options(fs); + str = xstrdup(mnt_fs_get_fs_options(fs)); break; case COL_OPT_FIELDS: - str = mnt_fs_get_optional_fields(fs); + str = xstrdup(mnt_fs_get_optional_fields(fs)); break; case COL_UUID: str = get_tag(fs, "UUID", col_id); @@ -532,10 +546,9 @@ static const char *get_data(struct libmnt_fs *fs, int num) break; if ((tt_flags & TT_FL_RAW) || (tt_flags & TT_FL_EXPORT)) - xasprintf(&tmp, "%u:%u", major(devno), minor(devno)); + xasprintf(&str, "%u:%u", major(devno), minor(devno)); else - xasprintf(&tmp, "%3u:%-3u", major(devno), minor(devno)); - str = tmp; + xasprintf(&str, "%3u:%-3u", major(devno), minor(devno)); break; } case COL_SIZE: @@ -545,19 +558,15 @@ static const char *get_data(struct libmnt_fs *fs, int num) str = get_vfs_attr(fs, col_id); break; case COL_FSROOT: - str = mnt_fs_get_root(fs); + str = xstrdup(mnt_fs_get_root(fs)); break; case COL_TID: - if (mnt_fs_get_tid(fs)) { - xasprintf(&tmp, "%d", mnt_fs_get_tid(fs)); - str = tmp; - } + if (mnt_fs_get_tid(fs)) + xasprintf(&str, "%d", mnt_fs_get_tid(fs)); break; case COL_ID: - if (mnt_fs_get_id(fs)) { - xasprintf(&tmp, "%d", mnt_fs_get_id(fs)); - str = tmp; - } + if (mnt_fs_get_id(fs)) + xasprintf(&str, "%d", mnt_fs_get_id(fs)); break; case COL_PROPAGATION: if (mnt_fs_is_kernel(fs)) { @@ -570,29 +579,25 @@ static const char *get_data(struct libmnt_fs *fs, int num) n = xstrdup((fl & MS_SHARED) ? "shared" : "private"); if (fl & MS_SLAVE) { - xasprintf(&tmp, "%s,slave", n); + xasprintf(&str, "%s,slave", n); free(n); - n = tmp; + n = str; } if (fl & MS_UNBINDABLE) { - xasprintf(&tmp, "%s,unbindable", n); + xasprintf(&str, "%s,unbindable", n); free(n); - n = tmp; + n = str; } str = n; } break; case COL_FREQ: - if (!mnt_fs_is_kernel(fs)) { - xasprintf(&tmp, "%d", mnt_fs_get_freq(fs)); - str = tmp; - } + if (!mnt_fs_is_kernel(fs)) + xasprintf(&str, "%d", mnt_fs_get_freq(fs)); break; case COL_PASSNO: - if (!mnt_fs_is_kernel(fs)) { - xasprintf(&tmp, "%d", mnt_fs_get_passno(fs)); - str = tmp; - } + if (!mnt_fs_is_kernel(fs)) + xasprintf(&str, "%d", mnt_fs_get_passno(fs)); break; default: break; @@ -600,12 +605,12 @@ static const char *get_data(struct libmnt_fs *fs, int num) return str; } -static const char *get_tabdiff_data(struct libmnt_fs *old_fs, +static char *get_tabdiff_data(struct libmnt_fs *old_fs, struct libmnt_fs *new_fs, int change, int num) { - const char *str = NULL; + char *str = NULL; switch (get_column_id(num)) { case COL_ACTION: @@ -626,16 +631,17 @@ static const char *get_tabdiff_data(struct libmnt_fs *old_fs, str = _("unknown"); break; } + str = xstrdup(str); break; case COL_OLD_OPTIONS: if (old_fs && (change == MNT_TABDIFF_REMOUNT || change == MNT_TABDIFF_UMOUNT)) - str = mnt_fs_get_options(old_fs); + str = xstrdup(mnt_fs_get_options(old_fs)); break; case COL_OLD_TARGET: if (old_fs && (change == MNT_TABDIFF_MOVE || change == MNT_TABDIFF_UMOUNT)) - str = mnt_fs_get_target(old_fs); + str = xstrdup(mnt_fs_get_target(old_fs)); break; default: if (new_fs) @@ -795,7 +801,7 @@ static struct libmnt_table *parse_tabfiles(char **files, break; } if (rc) { - mnt_free_table(tb); + mnt_unref_table(tb); warn(_("can't read %s"), path); return NULL; } @@ -815,8 +821,9 @@ static int tab_is_tree(struct libmnt_table *tb) if (!itr) return 0; - if (mnt_table_next_fs(tb, itr, &fs) == 0) - rc = mnt_fs_get_id(fs) > 0 && mnt_fs_get_parent_id(fs) > 0; + rc = (mnt_table_next_fs(tb, itr, &fs) == 0 && + mnt_fs_is_kernel(fs) && + mnt_fs_get_root(fs)); mnt_free_iter(itr); return rc; @@ -831,14 +838,6 @@ static int match_func(struct libmnt_fs *fs, const char *m; void *md; - m = get_match(COL_TARGET); - if (m && !mnt_fs_match_target(fs, m, cache)) - return rc; - - m = get_match(COL_SOURCE); - if (m && !mnt_fs_match_source(fs, m, cache)) - return rc; - m = get_match(COL_FSTYPE); if (m && !mnt_fs_match_fstype(fs, m)) return rc; @@ -851,6 +850,14 @@ static int match_func(struct libmnt_fs *fs, if (md && mnt_fs_get_devno(fs) != *((dev_t *) md)) return rc; + m = get_match(COL_TARGET); + if (m && !mnt_fs_match_target(fs, m, cache)) + return rc; + + m = get_match(COL_SOURCE); + if (m && !mnt_fs_match_source(fs, m, cache)) + return rc; + if ((flags & FL_DF) && !(flags & FL_ALL)) { const char *type = mnt_fs_get_fstype(fs); @@ -1076,7 +1083,7 @@ static int poll_table(struct libmnt_table *tb, const char *tabfile, rc = 0; done: - mnt_free_table(tb_new); + mnt_unref_table(tb_new); mnt_free_tabdiff(diff); mnt_free_iter(itr); if (f) @@ -1424,7 +1431,7 @@ int main(int argc, char *argv[]) /* * initialize output formatting (tt.h) */ - tt = tt_new_table(tt_flags); + tt = tt_new_table(tt_flags | TT_FL_FREEDATA); if (!tt) { warn(_("failed to initialize output table")); goto leave; @@ -1485,8 +1492,9 @@ int main(int argc, char *argv[]) leave: tt_free_table(tt); - mnt_free_table(tb); - mnt_free_cache(cache); + mnt_unref_table(tb); + mnt_unref_cache(cache); + free(tabfiles); #ifdef HAVE_LIBUDEV udev_unref(udev); diff --git a/misc-utils/getopt.1 b/misc-utils/getopt.1 index 6558e12bf..7fd872012 100644 --- a/misc-utils/getopt.1 +++ b/misc-utils/getopt.1 @@ -2,11 +2,20 @@ .SH NAME getopt \- parse command options (enhanced) .SH SYNOPSIS -getopt optstring parameters +.BI getopt +.I optstring parameters .br -getopt [options] [\-\-] optstring parameters +.B getopt +.RI [ options ] +.RB [ \-\- ] +.I optstring parameters .br -getopt [options] \-o|\-\-options optstring [options] [\-\-] +.B getopt +.RI [ options ] +.BR \-o | \-\-options +.I optstring +.RI [ options ] +.RB [ \-\- ] .I parameters .SH DESCRIPTION .B getopt @@ -21,10 +30,11 @@ routines to do this. The parameters .B getopt is called with can be divided into two parts: options which modify -the way getopt will parse -.RI ( options -and -.BR \-o | \-\-options +the way +.B getopt +will do the parsing +.RI "(the " options +and the .I optstring in the .BR SYNOPSIS ), @@ -44,10 +54,10 @@ part is used as the short options string. .PP If the environment variable .B GETOPT_COMPATIBLE -is set, or if its first parameter is not an option (does not start +is set, or if the first \fIparameter\fR is not an option (does not start with a .RB ' \- ', -this is the first format in the +the first format in the .BR SYNOPSIS ), .B getopt will generate output that is compatible with that of other versions of @@ -82,8 +92,7 @@ Allow long options to start with a single .RB ' \- '. .TP .BR \-h , " \-\-help" -Output a small usage guide and exit successfully. No other output is -generated. +Display help text and exit. No other output is generated. .TP .BR \-l , " \-\-longoptions \fIlongopts\fP" The long (multi\-character) options to be recognized. More than one @@ -129,11 +138,11 @@ Disable error reporting by getopt(3). Do not generate normal output. Errors are still reported by .BR getopt (3), unless you also use -.IR \-q . +.BR \-q . .TP .BR \-s , " \-\-shell \fIshell\fP" -Set quoting conventions to those of shell. If no \-s argument is -found, the +Set quoting conventions to those of \fIshell\fR. +If the \fB\-s\fR option is not given, the .SM BASH conventions are used. Valid arguments are currently .RB ' sh ' @@ -162,8 +171,7 @@ is set, will return and error status 0. .TP .BR \-V , " \-\-version" -Output version information and exit successfully. No other output is -generated. +Display version information and exit. No other output is generated. .SH PARSING This section specifies the format of the second part of the parameters of @@ -193,7 +201,7 @@ A simple short option is a .RB ' \- ' followed by a short option character. If the option has a required argument, it may be written directly after the option character or as -the next parameter (ie. separated by whitespace on the command +the next parameter (i.e. separated by whitespace on the command line). If the option has an optional argument, it must be written directly after the option character if present. .PP @@ -340,8 +348,8 @@ If the first character is .RB ' + ', or if the environment variable .B POSIXLY_CORRECT -is set, parsing stops as soon as the first non\-option parameter (ie. -a parameter that does not start with a +is set, parsing stops as soon as the first non\-option parameter +(i.e. a parameter that does not start with a .RB ' \- ') is found that is not an option argument. The remaining parameters are all interpreted as non\-option parameters. @@ -365,10 +373,11 @@ modifications, and with some advantages. .PP If the first character of the first parameter of getopt is not a .RB ' \- ', -getopt goes into compatibility mode. It will interpret its first +.B getopt +goes into compatibility mode. It will interpret its first parameter as the string of short options, and all other arguments -will be parsed. It will still do parameter shuffling (ie. all -non\-option parameters are outputted at the end), unless the +will be parsed. It will still do parameter shuffling (i.e. all +non\-option parameters are output at the end), unless the environment variable .B POSIXLY_CORRECT is set. @@ -407,7 +416,10 @@ if it is called with Example scripts for (ba)sh and (t)csh are provided with the .BR getopt (1) distribution, and are optionally installed in -.BR /usr/share/getopt/ . +.BR /usr/share/getopt/ +or +.BR /usr/share/doc/ +in the util-linux subdirectory. .SH ENVIRONMENT .IP POSIXLY_CORRECT This environment variable is examined by the diff --git a/misc-utils/logger.1 b/misc-utils/logger.1 index 09ecdc4f8..c7c3de0f5 100644 --- a/misc-utils/logger.1 +++ b/misc-utils/logger.1 @@ -38,7 +38,7 @@ logger \- a shell command interface to the syslog(3) system log module .SH SYNOPSIS .B logger -[options] [message] +.RI [ options "] [" message ] .SH DESCRIPTION .B logger makes entries in the system log. It provides a shell command @@ -47,6 +47,19 @@ interface to the system log module. .SH OPTIONS .TP +\fB\-d\fR, \fB\-\-udp\fR +Use datagram (UDP) only. By default the connection is tried to the +.I syslog +port defined in /etc/services, which is often +.IR 514 . +.TP +\fB\-h\fR, \fB\-\-help\fR +Display help text and exit. +.TP +\fB\-i\fR, \fB\-\-id\fR +Log the process ID of the logger process with each line. +.TP +.TP \fB\-n\fR, \fB\-\-server\fR \fIserver\fR Write to the specified remote syslog .I server @@ -54,36 +67,17 @@ instead of to the builtin syslog routines. Unless .B \-\-udp or .B \-\-tcp -is specified the logger will first try to use UDP, but if it fails a TCP -connection is attempted. -.TP -\fB\-d\fR, \fB\-\-udp\fR -Use datagram (UDP) only. By default the connection is tried to -.I syslog -port defined in /etc/services, which is often -.IR 514 . -.TP -\fB\-T\fR, \fB\-\-tcp\fR -Use stream (TCP) only. By default the connection is tried to -.I syslog-conn -port defined in /etc/services, which is often -.IR 601 . +is specified, \fBlogger\fR will first try to use UDP, +but if thist fails a TCP connection is attempted. .TP \fB\-P\fR, \fB\-\-port\fR \fIport\fR Use the specified .IR port . -.TP -\fB\-i\fR, \fB\-\-id\fR -Log the process ID of the logger process with each line. -.TP \fB\-f\fR, \fB\-\-file\fR \fIfile\fR Log the contents of the specified .IR file . This option cannot be combined with a command-line message. .TP -\fB\-h\fR, \fB\-\-help\fR -Display a help text and exit. -.TP \fB\-p\fR, \fB\-\-priority\fR \fIpriority\fR Enter the message into the log with the specified .IR priority . @@ -97,9 +91,28 @@ logs the message as informational in the local3 facility. The default is .IR user.notice . .TP +\fB\-\-prio\-prefix\fR +Look for a syslog prefix on every line read from standard input. +This prefix is a number within angle brackets that contains both the facility +and the level. This decimal prefix is constructed by multiplying the +facility by 8 and then adding the level. Thus, for example, \fIlocal0.info\fR, +facility=16 and level=6, becomes \fI<134>\fR. + +If the prefix contains no facility, the facility defaults to what is +specified by the \fB\-p\fR option. Similarly, if no prefix is provided, +the line is logged using the \fB\-p\fR \fIpriority\fR. + +This option doesn't affect a command-line message. +.TP \fB\-s\fR, \fB\-\-stderr\fR Output the message to standard error as well as to the system log. .TP +\fB\-T\fR, \fB\-\-tcp\fR +Use stream (TCP) only. By default the connection is tried to the +.I syslog-conn +port defined in /etc/services, which is often +.IR 601 . +.TP \fB\-t\fR, \fB\-\-tag\fR \fItag\fR Mark every line to be logged with the specified .IR tag . @@ -118,8 +131,8 @@ End the argument list. This is to allow the to start with a hyphen (\-). .TP .I message -Write the message to log; if not specified, and the -.I \-f +Write this \fImessage\fR to the log; if not specified, and the +.B \-f flag is not provided, standard input is logged. .PP The diff --git a/misc-utils/logger.c b/misc-utils/logger.c index c83c0b817..07176470e 100644 --- a/misc-utils/logger.c +++ b/misc-utils/logger.c @@ -64,6 +64,30 @@ enum { ALL_TYPES = TYPE_UDP | TYPE_TCP }; +enum { + OPT_PRIO_PREFIX = CHAR_MAX + 1 +}; + + +static char* get_prio_prefix(char *msg, int *prio) +{ + int p; + char *end = NULL; + int facility = *prio & LOG_FACMASK; + + errno = 0; + p = strtoul(msg + 1, &end, 10); + + if (errno || !end || end == msg + 1 || end[0] != '>') + return msg; + + if (p & LOG_FACMASK) + facility = p & LOG_FACMASK; + + *prio = facility | (p & LOG_PRIMASK); + return end + 1; +} + static int decode(char *name, CODE *codetab) { register CODE *c; @@ -101,8 +125,7 @@ static int pencode(char *s) return ((lev & LOG_PRIMASK) | (fac & LOG_FACMASK)); } -static int -unix_socket(const char *path, const int socket_type) +static int unix_socket(const char *path, const int socket_type) { int fd, i; static struct sockaddr_un s_addr; /* AF_UNIX address of local logger */ @@ -135,8 +158,8 @@ unix_socket(const char *path, const int socket_type) return fd; } -static int -inet_socket(const char *servername, const char *port, const int socket_type) +static int inet_socket(const char *servername, const char *port, + const int socket_type) { int fd, errcode, i; struct addrinfo hints, *res; @@ -159,7 +182,7 @@ inet_socket(const char *servername, const char *port, const int socket_type) hints.ai_family = AF_UNSPEC; errcode = getaddrinfo(servername, p, &hints, &res); if (errcode != 0) - errx(EXIT_FAILURE, _("getaddrinfo %s:%s: %s"), + errx(EXIT_FAILURE, _("failed to resolve name %s port %s: %s"), servername, p, gai_strerror(errcode)); if ((fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) { freeaddrinfo(res); @@ -176,13 +199,13 @@ inet_socket(const char *servername, const char *port, const int socket_type) } if (i == 0) - errx(EXIT_FAILURE, _("failed to connect %s port %s"), servername, p); + errx(EXIT_FAILURE, _("failed to connect to %s port %s"), servername, p); return fd; } -static void -mysyslog(int fd, int logflags, int pri, char *tag, char *msg) { +static void mysyslog(int fd, int logflags, int pri, char *tag, char *msg) +{ char buf[1000], pid[30], *cp, *tp; time_t now; @@ -211,23 +234,26 @@ mysyslog(int fd, int logflags, int pri, char *tag, char *msg) { static void __attribute__ ((__noreturn__)) usage(FILE *out) { - fputs(_("\nUsage:\n"), out); - fprintf(out, - _(" %s [options] [message]\n"), program_invocation_short_name); + fputs(USAGE_HEADER, out); + fprintf(out, _(" %s [options] [<message>]\n"), program_invocation_short_name); - fputs(_("\nOptions:\n"), out); + fputs(USAGE_OPTIONS, out); fputs(_(" -T, --tcp use TCP only\n"), out); - fputs(_(" -d, --udp use UDP only\n" - " -i, --id log the process ID too\n" - " -f, --file <file> log the contents of this file\n" - " -h, --help display this help text and exit\n"), out); - fputs(_(" -n, --server <name> write to this remote syslog server\n" - " -P, --port <number> use this UDP port\n" - " -p, --priority <prio> mark given message with this priority\n" - " -s, --stderr output message to standard error as well\n"), out); - fputs(_(" -t, --tag <tag> mark every line with this tag\n" - " -u, --socket <socket> write to this Unix socket\n" - " -V, --version output version information and exit\n\n"), out); + fputs(_(" -d, --udp use UDP only\n"), out); + fputs(_(" -i, --id log the process ID too\n"), out); + fputs(_(" -f, --file <file> log the contents of this file\n"), out); + fputs(_(" -n, --server <name> write to this remote syslog server\n"), out); + fputs(_(" -P, --port <number> use this UDP port\n"), out); + fputs(_(" -p, --priority <prio> mark given message with this priority\n"), out); + fputs(_(" --prio-prefix look for a prefix on every line read from stdin\n"), out); + fputs(_(" -s, --stderr output message to standard error as well\n"), out); + fputs(_(" -t, --tag <tag> mark every line with this tag\n"), out); + fputs(_(" -u, --socket <socket> write to this Unix socket\n"), out); + + fputs(USAGE_SEPARATOR, out); + fputs(USAGE_HELP, out); + fputs(USAGE_VERSION, out); + fprintf(out, USAGE_MAN_TAIL("logger(1)")); exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); } @@ -238,9 +264,9 @@ static void __attribute__ ((__noreturn__)) usage(FILE *out) * Reads from an input and arranges to write the result on the system * log. */ -int -main(int argc, char **argv) { - int ch, logflags, pri; +int main(int argc, char **argv) +{ + int ch, logflags, pri, prio_prefix; char *tag, buf[1024]; char *usock = NULL; char *server = NULL; @@ -260,6 +286,7 @@ main(int argc, char **argv) { { "port", required_argument, 0, 'P' }, { "version", no_argument, 0, 'V' }, { "help", no_argument, 0, 'h' }, + { "prio-prefix", no_argument, 0, OPT_PRIO_PREFIX }, { NULL, 0, 0, 0 } }; @@ -271,9 +298,10 @@ main(int argc, char **argv) { tag = NULL; pri = LOG_NOTICE; logflags = 0; + prio_prefix = 0; while ((ch = getopt_long(argc, argv, "f:ip:st:u:dTn:P:Vh", longopts, NULL)) != -1) { - switch((char)ch) { + switch (ch) { case 'f': /* file to log */ if (freopen(optarg, "r", stdin) == NULL) err(EXIT_FAILURE, _("file %s"), @@ -311,6 +339,9 @@ main(int argc, char **argv) { exit(EXIT_SUCCESS); case 'h': usage(stdout); + case OPT_PRIO_PREFIX: + prio_prefix = 1; + break; case '?': default: usage(stderr); @@ -360,6 +391,8 @@ main(int argc, char **argv) { mysyslog(LogSock, logflags, pri, tag, buf); } } else { + char *msg; + int default_priority = pri; while (fgets(buf, sizeof(buf), stdin) != NULL) { /* glibc is buggy and adds an additional newline, so we have to remove it here until glibc is fixed */ @@ -368,10 +401,15 @@ main(int argc, char **argv) { if (len > 0 && buf[len - 1] == '\n') buf[len - 1] = '\0'; + msg = buf; + pri = default_priority; + if (prio_prefix && msg[0] == '<') + msg = get_prio_prefix(msg, &pri); + if (!usock && !server) - syslog(pri, "%s", buf); + syslog(pri, "%s", msg); else - mysyslog(LogSock, logflags, pri, tag, buf); + mysyslog(LogSock, logflags, pri, tag, msg); } } if (!usock && !server) diff --git a/misc-utils/look.1 b/misc-utils/look.1 index fe8d8fd8e..d1d8f1bd4 100644 --- a/misc-utils/look.1 +++ b/misc-utils/look.1 @@ -81,7 +81,7 @@ are compared. Display help text and exit. .TP .BR \-V , " \-\-version" -Output version information and exit. +Display version information and exit. .PP The .B look diff --git a/misc-utils/lsblk.8 b/misc-utils/lsblk.8 index 78243dce0..ea7e7bee8 100644 --- a/misc-utils/lsblk.8 +++ b/misc-utils/lsblk.8 @@ -56,7 +56,7 @@ The authoritative information about filesystems and raids is provided by the command. .TP .BR \-h , " \-\-help" -Print a help text and exit. +Display help text and exit. .TP .BR \-I , " \-\-include " \fIlist\fP Include devices specified by the comma-separated \fIlist\fR of major device numbers. @@ -106,7 +106,7 @@ This option is equivalent to .BR -o\ NAME,ALIGNMENT,MIN-IO,OPT-IO,PHY-SEC,LOG-SEC,ROTA,SCHED,RQ-SIZE,WSAME . .TP .BR \-V , " \-\-version" -Output version information and exit. +Display version information and exit. .SH NOTES For partitions, some information (e.g. queue attributes) is inherited from the parent device. diff --git a/misc-utils/lsblk.c b/misc-utils/lsblk.c index a62042bef..9b53be35d 100644 --- a/misc-utils/lsblk.c +++ b/misc-utils/lsblk.c @@ -372,8 +372,12 @@ static char *get_device_mountpoint(struct blkdev_cxt *cxt) mnt_table_parse_mtab(mtab, NULL); } - /* try /etc/mtab or /proc/self/mountinfo */ - fs = mnt_table_find_srcpath(mtab, cxt->filename, MNT_ITER_BACKWARD); + /* Note that maj:min in /proc/self/mouninfo does not have to match with + * devno as returned by stat(), so we have to try devname too + */ + fs = mnt_table_find_devno(mtab, makedev(cxt->maj, cxt->min), MNT_ITER_BACKWARD); + if (!fs) + fs = mnt_table_find_srcpath(mtab, cxt->filename, MNT_ITER_BACKWARD); if (!fs) return is_active_swap(cxt->filename) ? xstrdup("[SWAP]") : NULL; @@ -899,7 +903,7 @@ static void set_tt_data(struct blkdev_cxt *cxt, int col, int id, struct tt_line if (cxt->discard && p) tt_line_set_data(ln, col, p); else - tt_line_set_data(ln, col, "0"); + tt_line_set_data(ln, col, xstrdup("0")); break; case COL_DGRAN: if (lsblk->bytes) @@ -932,7 +936,7 @@ static void set_tt_data(struct blkdev_cxt *cxt, int col, int id, struct tt_line if (cxt->discard && p) tt_line_set_data(ln, col, p); else - tt_line_set_data(ln, col, "0"); + tt_line_set_data(ln, col, xstrdup("0")); break; case COL_WSAME: if (lsblk->bytes) @@ -944,7 +948,7 @@ static void set_tt_data(struct blkdev_cxt *cxt, int col, int id, struct tt_line "queue/write_same_max_bytes", &x) == 0) p = size_to_human_string(SIZE_SUFFIX_1LETTER, x); } - tt_line_set_data(ln, col, p ? p : "0"); + tt_line_set_data(ln, col, p ? p : xstrdup("0")); break; }; } @@ -1367,20 +1371,19 @@ static void __attribute__((__noreturn__)) help(FILE *out) fputs(_(" -d, --nodeps don't print slaves or holders\n"), out); fputs(_(" -D, --discard print discard capabilities\n"), out); fputs(_(" -e, --exclude <list> exclude devices by major number (default: RAM disks)\n"), out); - fputs(_(" -I, --include <list> show only devices with specified major numbers\n"), out); fputs(_(" -f, --fs output info about filesystems\n"), out); - fputs(_(" -h, --help usage information (this)\n"), out); fputs(_(" -i, --ascii use ascii characters only\n"), out); - fputs(_(" -m, --perms output info about permissions\n"), out); + fputs(_(" -I, --include <list> show only devices with specified major numbers\n"), out); fputs(_(" -l, --list use list format output\n"), out); + fputs(_(" -m, --perms output info about permissions\n"), out); fputs(_(" -n, --noheadings don't print headings\n"), out); fputs(_(" -o, --output <list> output columns\n"), out); - fputs(_(" -p, --paths print complate device path\n"), out); + fputs(_(" -p, --paths print complete device path\n"), out); fputs(_(" -P, --pairs use key=\"value\" output format\n"), out); fputs(_(" -r, --raw use raw output format\n"), out); fputs(_(" -s, --inverse inverse dependencies\n"), out); - fputs(_(" -t, --topology output info about topology\n"), out); fputs(_(" -S, --scsi output info about SCSI devices\n"), out); + fputs(_(" -t, --topology output info about topology\n"), out); fputs(USAGE_SEPARATOR, out); fputs(USAGE_HELP, out); fputs(USAGE_VERSION, out); @@ -1575,7 +1578,7 @@ int main(int argc, char *argv[]) /* * initialize output columns */ - if (!(lsblk->tt = tt_new_table(tt_flags))) + if (!(lsblk->tt = tt_new_table(tt_flags | TT_FL_FREEDATA))) errx(EXIT_FAILURE, _("failed to initialize output table")); for (i = 0; i < ncolumns; i++) { @@ -1600,9 +1603,10 @@ int main(int argc, char *argv[]) leave: tt_free_table(lsblk->tt); - mnt_free_table(mtab); - mnt_free_table(swaps); - mnt_free_cache(mntcache); + + mnt_unref_table(mtab); + mnt_unref_table(swaps); + mnt_unref_cache(mntcache); #ifdef HAVE_LIBUDEV udev_unref(udev); #endif diff --git a/misc-utils/lslocks.8 b/misc-utils/lslocks.8 index 461220182..20ff0dcbb 100644 --- a/misc-utils/lslocks.8 +++ b/misc-utils/lslocks.8 @@ -16,7 +16,7 @@ lists information about all the currently held file locks in a Linux system. .SH OPTIONS .TP .BR \-h , " \-\-help" -Print a help text and exit. +Display help text and exit. .TP .BR \-n , " \-\-noheadings" Do not print a header line. diff --git a/misc-utils/lslocks.c b/misc-utils/lslocks.c index de3094a01..ab85bf7c3 100644 --- a/misc-utils/lslocks.c +++ b/misc-utils/lslocks.c @@ -450,7 +450,7 @@ static int show_locks(struct list_head *locks, int tt_flags) struct list_head *p, *pnext; struct tt *tt; - tt = tt_new_table(tt_flags); + tt = tt_new_table(tt_flags | TT_FL_FREEDATA); if (!tt) { warn(_("failed to initialize output table")); return -1; @@ -592,6 +592,6 @@ int main(int argc, char *argv[]) if (!rc && !list_empty(&locks)) rc = show_locks(&locks, tt_flags); - mnt_free_table(tab); + mnt_unref_table(tab); return rc; } diff --git a/misc-utils/mcookie.1 b/misc-utils/mcookie.1 index e7579c4b9..fc7e03047 100644 --- a/misc-utils/mcookie.1 +++ b/misc-utils/mcookie.1 @@ -34,10 +34,10 @@ input is read from stdin. Explain what is being done. .TP \fB\-V\fR, \fB\-\-version\fR -Output version information and exit. +Display version information and exit. .TP \fB\-h\fR, \fB\-\-help\fR -Display this help and exit. +Display help text and exit. .SH BUGS The entropy in the generated 128-bit is probably quite small (and, therefore, vulnerable to attack) unless a non-pseudorandom number generator diff --git a/misc-utils/mcookie.c b/misc-utils/mcookie.c index da641a176..3761c4b8c 100644 --- a/misc-utils/mcookie.c +++ b/misc-utils/mcookie.c @@ -147,8 +147,9 @@ int main(int argc, char **argv) count = hash_file(&ctx, fd); if (verbose) fprintf(stderr, - _("Got %d bytes from %s\n"), count, - file); + P_("Got %d byte from %s\n", + "Got %d bytes from %s\n", count), + count, file); if (fd != STDIN_FILENO) if (close(fd)) @@ -171,8 +172,9 @@ int main(int argc, char **argv) close(fd); if (verbose) fprintf(stderr, - _("Got %d bytes from %s\n"), r, - rngs[i].path); + P_("Got %d byte from %s\n", + "Got %d bytes from %s\n", r), + r, rngs[i].path); if (rngs[i].minlength && r >= rngs[i].minlength) break; } else if (verbose) diff --git a/misc-utils/namei.1 b/misc-utils/namei.1 index 88e249d72..550dc9740 100644 --- a/misc-utils/namei.1 +++ b/misc-utils/namei.1 @@ -55,9 +55,9 @@ Vertically align the modes and owners. .IP "\fB\-x, \-\-mountpoints\fP" Show mountpoint directories with a 'D' rather than a 'd'. .IP "\fB\-h\fR, \fB\-\-help\fR" -Output help text and exit. +Display help text and exit. .IP "\fB\-V\fR, \fB\-\-version\fR" -Output version information and exit. +Display version information and exit. .SH AUTHOR The original .B namei diff --git a/misc-utils/sd-daemon.c b/misc-utils/sd-daemon.c index 763e079b4..485b30102 100644 --- a/misc-utils/sd-daemon.c +++ b/misc-utils/sd-daemon.c @@ -25,18 +25,14 @@ ***/ #ifndef _GNU_SOURCE -#define _GNU_SOURCE +# define _GNU_SOURCE #endif #include <sys/types.h> #include <sys/stat.h> #include <sys/socket.h> #include <sys/un.h> -#ifdef __BIONIC__ -#include <linux/fcntl.h> -#else -#include <sys/fcntl.h> -#endif +#include <fcntl.h> #include <netinet/in.h> #include <stdlib.h> #include <errno.h> @@ -47,22 +43,22 @@ #include <stddef.h> #include <limits.h> -#if defined(__linux__) -#include <mqueue.h> +#if defined(__linux__) && !defined(SD_DAEMON_DISABLE_MQ) +# include <mqueue.h> #endif #include "sd-daemon.h" #if (__GNUC__ >= 4) -#ifdef SD_EXPORT_SYMBOLS +# ifdef SD_EXPORT_SYMBOLS /* Export symbols */ -#define _sd_export_ __attribute__ ((visibility("default"))) -#else +# define _sd_export_ __attribute__ ((visibility("default"))) +# else /* Don't export the symbols */ -#define _sd_export_ __attribute__ ((visibility("hidden"))) -#endif +# define _sd_export_ __attribute__ ((visibility("hidden"))) +# endif #else -#define _sd_export_ +# define _sd_export_ #endif _sd_export_ int sd_listen_fds(int unset_environment) { @@ -75,7 +71,8 @@ _sd_export_ int sd_listen_fds(int unset_environment) { char *p = NULL; unsigned long l; - if (!(e = getenv("LISTEN_PID"))) { + e = getenv("LISTEN_PID"); + if (!e) { r = 0; goto finish; } @@ -83,12 +80,12 @@ _sd_export_ int sd_listen_fds(int unset_environment) { errno = 0; l = strtoul(e, &p, 10); - if (errno != 0) { + if (errno > 0) { r = -errno; goto finish; } - if (!p || *p || l <= 0) { + if (!p || p == e || *p || l <= 0) { r = -EINVAL; goto finish; } @@ -99,7 +96,8 @@ _sd_export_ int sd_listen_fds(int unset_environment) { goto finish; } - if (!(e = getenv("LISTEN_FDS"))) { + e = getenv("LISTEN_FDS"); + if (!e) { r = 0; goto finish; } @@ -107,12 +105,12 @@ _sd_export_ int sd_listen_fds(int unset_environment) { errno = 0; l = strtoul(e, &p, 10); - if (errno != 0) { + if (errno > 0) { r = -errno; goto finish; } - if (!p || *p) { + if (!p || p == e || *p) { r = -EINVAL; goto finish; } @@ -120,7 +118,8 @@ _sd_export_ int sd_listen_fds(int unset_environment) { for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) l; fd ++) { int flags; - if ((flags = fcntl(fd, F_GETFD)) < 0) { + flags = fcntl(fd, F_GETFD); + if (flags < 0) { r = -errno; goto finish; } @@ -152,7 +151,6 @@ _sd_export_ int sd_is_fifo(int fd, const char *path) { if (fd < 0) return -EINVAL; - memset(&st_fd, 0, sizeof(st_fd)); if (fstat(fd, &st_fd) < 0) return -errno; @@ -162,7 +160,6 @@ _sd_export_ int sd_is_fifo(int fd, const char *path) { if (path) { struct stat st_path; - memset(&st_path, 0, sizeof(st_path)); if (stat(path, &st_path) < 0) { if (errno == ENOENT || errno == ENOTDIR) @@ -272,15 +269,13 @@ _sd_export_ int sd_is_socket(int fd, int family, int type, int listening) { if (family < 0) return -EINVAL; - if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) + r = sd_is_socket_internal(fd, type, listening); + if (r <= 0) return r; if (family > 0) { - union sockaddr_union sockaddr; - socklen_t l; - - memset(&sockaddr, 0, sizeof(sockaddr)); - l = sizeof(sockaddr); + union sockaddr_union sockaddr = {}; + socklen_t l = sizeof(sockaddr); if (getsockname(fd, &sockaddr.sa, &l) < 0) return -errno; @@ -295,19 +290,17 @@ _sd_export_ int sd_is_socket(int fd, int family, int type, int listening) { } _sd_export_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) { - union sockaddr_union sockaddr; - socklen_t l; + union sockaddr_union sockaddr = {}; + socklen_t l = sizeof(sockaddr); int r; if (family != 0 && family != AF_INET && family != AF_INET6) return -EINVAL; - if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) + r = sd_is_socket_internal(fd, type, listening); + if (r <= 0) return r; - memset(&sockaddr, 0, sizeof(sockaddr)); - l = sizeof(sockaddr); - if (getsockname(fd, &sockaddr.sa, &l) < 0) return -errno; @@ -340,16 +333,14 @@ _sd_export_ int sd_is_socket_inet(int fd, int family, int type, int listening, u } _sd_export_ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) { - union sockaddr_union sockaddr; - socklen_t l; + union sockaddr_union sockaddr = {}; + socklen_t l = sizeof(sockaddr); int r; - if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) + r = sd_is_socket_internal(fd, type, listening); + if (r <= 0) return r; - memset(&sockaddr, 0, sizeof(sockaddr)); - l = sizeof(sockaddr); - if (getsockname(fd, &sockaddr.sa, &l) < 0) return -errno; @@ -360,10 +351,10 @@ _sd_export_ int sd_is_socket_unix(int fd, int type, int listening, const char *p return 0; if (path) { - if (length <= 0) + if (length == 0) length = strlen(path); - if (length <= 0) + if (length == 0) /* Unnamed socket */ return l == offsetof(struct sockaddr_un, sun_path); @@ -383,7 +374,7 @@ _sd_export_ int sd_is_socket_unix(int fd, int type, int listening, const char *p } _sd_export_ int sd_is_mq(int fd, const char *path) { -#if !defined(__linux__) +#if !defined(__linux__) || defined(SD_DAEMON_DISABLE_MQ) return 0; #else struct mq_attr attr; @@ -434,7 +425,8 @@ _sd_export_ int sd_notify(int unset_environment, const char *state) { goto finish; } - if (!(e = getenv("NOTIFY_SOCKET"))) + e = getenv("NOTIFY_SOCKET"); + if (!e) return 0; /* Must be an abstract socket, or an absolute path */ @@ -443,7 +435,8 @@ _sd_export_ int sd_notify(int unset_environment, const char *state) { goto finish; } - if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0) { + fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); + if (fd < 0) { r = -errno; goto finish; } @@ -513,18 +506,15 @@ _sd_export_ int sd_booted(void) { #if defined(DISABLE_SYSTEMD) || !defined(__linux__) return 0; #else + struct stat st; - struct stat a, b; - - /* We simply test whether the systemd cgroup hierarchy is - * mounted */ - - if (lstat("/sys/fs/cgroup", &a) < 0) - return 0; + /* We test whether the runtime unit file directory has been + * created. This takes place in mount-setup.c, so is + * guaranteed to happen very early during boot. */ - if (lstat("/sys/fs/cgroup/systemd", &b) < 0) + if (lstat("/run/systemd/system/", &st) < 0) return 0; - return a.st_dev != b.st_dev; + return !!S_ISDIR(st.st_mode); #endif } diff --git a/misc-utils/sd-daemon.h b/misc-utils/sd-daemon.h index fe51159ee..daa3f4c85 100644 --- a/misc-utils/sd-daemon.h +++ b/misc-utils/sd-daemon.h @@ -59,20 +59,20 @@ extern "C" { You may find an up-to-date version of these source files online: http://cgit.freedesktop.org/systemd/systemd/plain/src/systemd/sd-daemon.h - http://cgit.freedesktop.org/systemd/systemd/plain/src/sd-daemon.c + http://cgit.freedesktop.org/systemd/systemd/plain/src/libsystemd-daemon/sd-daemon.c This should compile on non-Linux systems, too, but with the exception of the sd_is_xxx() calls all functions will become NOPs. - See sd-daemon(7) for more information. + See sd-daemon(3) for more information. */ #ifndef _sd_printf_attr_ -#if __GNUC__ >= 4 -#define _sd_printf_attr_(a,b) __attribute__ ((format (printf, a, b))) -#else -#define _sd_printf_attr_(a,b) -#endif +# if __GNUC__ >= 4 +# define _sd_printf_attr_(a,b) __attribute__ ((format (printf, a, b))) +# else +# define _sd_printf_attr_(a,b) +# endif #endif /* diff --git a/misc-utils/uuidd.c b/misc-utils/uuidd.c index 668aac7a3..d381eea9e 100644 --- a/misc-utils/uuidd.c +++ b/misc-utils/uuidd.c @@ -36,6 +36,7 @@ extern int optind; #include "all-io.h" #include "c.h" #include "closestream.h" +#include "strutils.h" #ifdef USE_SOCKET_ACTIVATION #include "sd-daemon.h" @@ -217,8 +218,7 @@ static int create_pidfile(const char *pidfile_path, int quiet) fd_pidfile = open(pidfile_path, O_CREAT | O_RDWR, 0664); if (fd_pidfile < 0) { if (!quiet) - fprintf(stderr, _("Failed to open/create %s: %m\n"), - pidfile_path); + warn(_("cannot open %s"), pidfile_path); exit(EXIT_FAILURE); } cleanup_pidfile = pidfile_path; @@ -232,7 +232,7 @@ static int create_pidfile(const char *pidfile_path, int quiet) if ((errno == EAGAIN) || (errno == EINTR)) continue; if (!quiet) - fprintf(stderr, _("Failed to lock %s: %m\n"), pidfile_path); + warn(_("cannot lock %s"), pidfile_path); exit(EXIT_FAILURE); } @@ -256,7 +256,7 @@ static int create_socket(const char *socket_path, int will_fork, int quiet) if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { if (!quiet) - fprintf(stderr, _("Couldn't create unix stream socket: %m")); + warn(_("couldn't create unix stream socket")); exit(EXIT_FAILURE); } @@ -281,8 +281,7 @@ static int create_socket(const char *socket_path, int will_fork, int quiet) if (bind(s, (const struct sockaddr *) &my_addr, sizeof(struct sockaddr_un)) < 0) { if (!quiet) - fprintf(stderr, - _("Couldn't bind unix socket %s: %m\n"), socket_path); + warn(_("couldn't bind unix socket %s"), socket_path); exit(EXIT_FAILURE); } umask(save_umask); @@ -319,8 +318,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path, sizeof(reply_buf), 0, NULL); if (ret > 0) { if (!uuidd_cxt->quiet) - fprintf(stderr, - _("uuidd daemon already running at pid %s\n"), + warnx(_("uuidd daemon is already running at pid %s"), reply_buf); exit(EXIT_FAILURE); } @@ -331,8 +329,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path, uuidd_cxt->quiet); if (listen(s, SOMAXCONN) < 0) { if (!uuidd_cxt->quiet) - fprintf(stderr, _("Couldn't listen on unix " - "socket %s: %m\n"), socket_path); + warn(_("couldn't listen on unix socket %s"), socket_path); exit(EXIT_FAILURE); } @@ -357,10 +354,8 @@ static void server_loop(const char *socket_path, const char *pidfile_path, #ifdef USE_SOCKET_ACTIVATION if (uuidd_cxt->no_sock) { - if (sd_listen_fds(0) != 1) { - fprintf(stderr, _("No or too many file descriptors received.\n")); - exit(EXIT_FAILURE); - } + if (sd_listen_fds(0) != 1) + errx(EXIT_FAILURE, _("no or too many file descriptors received")); s = SD_LISTEN_FDS_START + 0; } @@ -381,10 +376,10 @@ static void server_loop(const char *socket_path, const char *pidfile_path, len = read(ns, &op, 1); if (len != 1) { if (len < 0) - perror("read"); + warn(_("read failed")); else - fprintf(stderr, _("Error reading from client, " - "len = %d\n"), len); + warnx(_("error reading from client, len = %d"), + len); goto shutdown_socket; } if ((op == UUIDD_OP_BULK_TIME_UUID) || @@ -485,9 +480,9 @@ int main(int argc, char **argv) const char *socket_path = UUIDD_SOCKET_PATH; const char *pidfile_path = NULL; const char *pidfile_path_param = NULL; - const char *err_context; + const char *err_context = NULL; char buf[1024], *cp; - char str[UUID_STR_LEN], *tmp; + char str[UUID_STR_LEN]; uuid_t uu; int i, c, ret; int do_type = 0, do_kill = 0, num = 0; @@ -530,11 +525,8 @@ int main(int argc, char **argv) do_kill++; break; case 'n': - num = strtol(optarg, &tmp, 0); - if ((num < 1) || *tmp) { - fprintf(stderr, _("Bad number: %s\n"), optarg); - return EXIT_FAILURE; - } + num = strtou32_or_err(optarg, + _("failed to parse --uuids")); break; case 'p': pidfile_path_param = optarg; @@ -551,9 +543,8 @@ int main(int argc, char **argv) uuidd_cxt.no_fork = 1; no_pid = 1; #else - fprintf(stderr, - _("uuidd has been built without support for socket activation.\n")); - return EXIT_FAILURE; + errx(EXIT_FAILURE, _("uuidd has been built without " + "support for socket activation")); #endif break; case 'q': @@ -570,11 +561,8 @@ int main(int argc, char **argv) do_type = UUIDD_OP_TIME_UUID; break; case 'T': - uuidd_cxt.timeout = strtol(optarg, &tmp, 0); - if (uuidd_cxt.timeout < 0 || *tmp) { - fprintf(stderr, _("Bad number: %s\n"), optarg); - return EXIT_FAILURE; - } + uuidd_cxt.timeout = strtou32_or_err(optarg, + _("failed to parse --timeout")); break; case 'V': printf(UTIL_LINUX_VERSION); @@ -587,8 +575,7 @@ int main(int argc, char **argv) } if (no_pid && pidfile_path_param && !uuidd_cxt.quiet) - fprintf(stderr, _("Both --pid and --no-pid specified. " - "Ignoring --no-pid.\n")); + warnx(_("Both --pid and --no-pid specified. Ignoring --no-pid.")); if (!no_pid && !pidfile_path_param) pidfile_path = UUIDD_PIDFILE_PATH; @@ -597,16 +584,16 @@ int main(int argc, char **argv) /* custom socket path and socket-activation make no sense */ if (s_flag && uuidd_cxt.no_sock && !uuidd_cxt.quiet) - fprintf(stderr, _("Both --socket-activation and --socket specified. " - "Ignoring --socket\n")); + warnx(_("Both --socket-activation and --socket specified. " + "Ignoring --socket.")); if (num && do_type) { ret = call_daemon(socket_path, do_type + 2, buf, sizeof(buf), &num, &err_context); - if (ret < 0) { - printf(_("Error calling uuidd daemon (%s): %m\n"), err_context); - return EXIT_FAILURE; - } + if (ret < 0) + err(EXIT_FAILURE, _("error calling uuidd daemon (%s)"), + err_context ? : _("unexpected error")); + if (do_type == UUIDD_OP_TIME_UUID) { if (ret != sizeof(uu) + sizeof(num)) unexpected_size(ret); @@ -631,10 +618,9 @@ int main(int argc, char **argv) if (do_type) { ret = call_daemon(socket_path, do_type, (char *) &uu, sizeof(uu), 0, &err_context); - if (ret < 0) { - printf(_("Error calling uuidd daemon (%s): %m\n"), err_context); - return EXIT_FAILURE; - } + if (ret < 0) + err(EXIT_FAILURE, _("error calling uuidd daemon (%s)"), + err_context ? : _("unexpected error")); if (ret != sizeof(uu)) unexpected_size(ret); @@ -650,13 +636,12 @@ int main(int argc, char **argv) ret = kill(do_kill, SIGTERM); if (ret < 0) { if (!uuidd_cxt.quiet) - fprintf(stderr, - _("Couldn't kill uuidd running " - "at pid %d: %m\n"), do_kill); + warn(_("couldn't kill uuidd running " + "at pid %d"), do_kill); return EXIT_FAILURE; } if (!uuidd_cxt.quiet) - printf(_("Killed uuidd running at pid %d\n"), + printf(_("Killed uuidd running at pid %d.\n"), do_kill); } return EXIT_SUCCESS; diff --git a/misc-utils/wipefs.8 b/misc-utils/wipefs.8 index 39f732b5c..0f280b38a 100644 --- a/misc-utils/wipefs.8 +++ b/misc-utils/wipefs.8 @@ -23,6 +23,9 @@ does not erase the filesystem itself nor any other data from the device. When used without options \fB-a\fR or \fB-o\fR, it lists all visible filesystems and the offsets of their basic signatures. +.B wipefs +calls BLKRRPART ioctl when erase partition table to inform kernel about the change. + Note that some filesystems or some partition tables store more magic strings on the devices. The .B wipefs @@ -40,12 +43,16 @@ erased. Erase all available signatures. The set of erased signatures can be restricted with the \fB\-t\fP \fIlist\fP option. .TP +.BR \-b , " \-\-backup" +Create a signature backup to the file $HOME/wipefs-<devname>-<offset>.bak. +For more details see EXAMPLES section. +.TP .BR \-f , " \-\-force" Force erasure, even if the filesystem is mounted. This is required in order to erase the partition table on a block device. .TP .BR \-h , " \-\-help" -Print help and exit. +Display help text and exit. .TP .BR -n , " \-\-no\-act" Causes everything to be done except for the write() call. @@ -74,7 +81,15 @@ can be prefixed with 'no' to specify the types on which no action should be taken. For more details see mount(8). .TP .BR -V , " \-\-version" -Output version information and exit. +Display version information and exit. +.SH EXAMPLES +.TP +.BR "wipefs --all --backup /dev/sdb" +Erases all signatures from the device /dev/sdb and creates a signature backup +file ~/wipefs-sdb-<offset>.bak for each signature. +.TP +.BR "dd if=~/wipefs-sdb-0x00000438.bak of=/dev/sdb seek=$((0x00000438)) bs=1 conv=notrunc" +Restores ext2 signature from the backup file ~/wipefs-sdb-0x00000438.bak. .SH AUTHOR Karel Zak <kzak@redhat.com> .SH ENVIRONMENT diff --git a/misc-utils/wipefs.c b/misc-utils/wipefs.c index ce3d2b816..cd2fd985e 100644 --- a/misc-utils/wipefs.c +++ b/misc-utils/wipefs.c @@ -40,21 +40,24 @@ #include "c.h" #include "closestream.h" #include "optutils.h" +#include "blkdev.h" struct wipe_desc { loff_t offset; /* magic string offset */ size_t len; /* length of magic string */ unsigned char *magic; /* magic string */ - int zap; /* zap this offset? */ char *usage; /* raid, filesystem, ... */ char *type; /* FS type */ char *label; /* FS label */ char *uuid; /* FS uuid */ - int on_disk; - struct wipe_desc *next; + + unsigned int zap : 1, + on_disk : 1, + is_parttable : 1; + }; enum { @@ -62,6 +65,14 @@ enum { WP_MODE_PARSABLE }; +enum { + WP_FL_NOACT = (1 << 1), + WP_FL_ALL = (1 << 2), + WP_FL_QUIET = (1 << 3), + WP_FL_BACKUP = (1 << 4), + WP_FL_FORCE = (1 << 5) +}; + static const char *type_pattern; static void @@ -72,7 +83,7 @@ print_pretty(struct wipe_desc *wp, int line) printf("----------------------------------------------------------------\n"); } - printf("0x%-17jx %s [%s]", wp->offset, wp->type, wp->usage); + printf("0x%-17jx %s [%s]", wp->offset, wp->type, _(wp->usage)); if (wp->label && *wp->label) printf("\n%27s %s", "LABEL:", wp->label); @@ -141,7 +152,7 @@ add_offset(struct wipe_desc *wp0, loff_t offset, int zap) wp = xcalloc(1, sizeof(struct wipe_desc)); wp->offset = offset; wp->next = wp0; - wp->zap = zap; + wp->zap = zap ? 1 : 0; return wp; } @@ -164,7 +175,7 @@ get_desc_for_probe(struct wipe_desc *wp, blkid_probe pr) const char *off, *type, *mag, *p, *usage = NULL; size_t len; loff_t offset; - int rc; + int rc, ispt = 0; /* superblocks */ if (blkid_probe_lookup_value(pr, "TYPE", &type, NULL) == 0) { @@ -181,7 +192,8 @@ get_desc_for_probe(struct wipe_desc *wp, blkid_probe pr) rc = blkid_probe_lookup_value(pr, "PTMAGIC", &mag, &len); if (rc) return wp; - usage = "partition table"; + usage = N_("partition table"); + ispt = 1; } else return wp; @@ -199,6 +211,7 @@ get_desc_for_probe(struct wipe_desc *wp, blkid_probe pr) wp->type = xstrdup(type); wp->on_disk = 1; + wp->is_parttable = ispt ? 1 : 0; wp->magic = xmalloc(len); memcpy(wp->magic, mag, len); @@ -240,7 +253,8 @@ new_probe(const char *devname, int mode) blkid_probe_enable_superblocks(pr, 1); blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_MAGIC | BLKID_SUBLKS_TYPE | BLKID_SUBLKS_USAGE | - BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID); + BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | + BLKID_SUBLKS_BADCSUM); blkid_probe_enable_partitions(pr, 1); blkid_probe_set_partitions_flags(pr, BLKID_PARTS_MAGIC); @@ -287,19 +301,22 @@ free_wipe(struct wipe_desc *wp) } } -static void do_wipe_real(blkid_probe pr, const char *devname, struct wipe_desc *w, int noact, int quiet) +static void do_wipe_real(blkid_probe pr, const char *devname, + struct wipe_desc *w, int flags) { size_t i; - if (blkid_do_wipe(pr, noact)) + if (blkid_do_wipe(pr, (flags & WP_FL_NOACT) != 0)) warn(_("%s: failed to erase %s magic string at offset 0x%08jx"), devname, w->type, w->offset); - if (quiet) + if (flags & WP_FL_QUIET) return; - printf(_("%s: %zd bytes were erased at offset 0x%08jx (%s): "), - devname, w->len, w->offset, w->type); + printf(P_("%s: %zd byte was erased at offset 0x%08jx (%s): ", + "%s: %zd bytes were erased at offset 0x%08jx (%s): ", + w->len), + devname, w->len, w->offset, w->type); for (i = 0; i < w->len; i++) { printf("%02x", w->magic[i]); @@ -309,21 +326,61 @@ static void do_wipe_real(blkid_probe pr, const char *devname, struct wipe_desc * putchar('\n'); } +static void do_backup(struct wipe_desc *wp, const char *base) +{ + char *fname = NULL; + int fd; + + xasprintf(&fname, "%s0x%08jx.bak", base, wp->offset); + + fd = open(fname, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR); + if (fd < 0) + goto err; + if (write_all(fd, wp->magic, wp->len) != 0) + goto err; + close(fd); + free(fname); + return; +err: + err(EXIT_FAILURE, _("%s: failed to create a signature backup"), fname); +} + +static void rereadpt(int fd, const char *devname) +{ +#ifdef BLKRRPART + struct stat st; + + if (fstat(fd, &st) || !S_ISBLK(st.st_mode)) + return; + + errno = 0; + ioctl(fd, BLKRRPART); + printf(_("%s: calling ioclt to re-read partition table: %m\n"), devname); +#endif +} + static struct wipe_desc * -do_wipe(struct wipe_desc *wp, const char *devname, int noact, int all, int quiet, int force) +do_wipe(struct wipe_desc *wp, const char *devname, int flags) { - int flags; + int mode = O_RDWR, reread = 0; blkid_probe pr; struct wipe_desc *w, *wp0; - int zap = all ? 1 : wp->zap; + int zap = (flags & WP_FL_ALL) ? 1 : wp->zap; + char *backup = NULL; - flags = O_RDWR; - if (!force) - flags |= O_EXCL; - pr = new_probe(devname, flags); + if (!(flags & WP_FL_FORCE)) + mode |= O_EXCL; + pr = new_probe(devname, mode); if (!pr) return NULL; + if (zap && (flags & WP_FL_BACKUP)) { + const char *home = getenv ("HOME"); + if (!home) + errx(EXIT_FAILURE, _("failed to create a signature backup, $HOME undefined")); + xasprintf (&backup, "%s/wipefs-%s-", home, basename(devname)); + } + wp0 = clone_offset(wp); while (blkid_do_probe(pr) == 0) { @@ -345,19 +402,29 @@ do_wipe(struct wipe_desc *wp, const char *devname, int noact, int all, int quiet if (!wp->on_disk) continue; - if (zap) - do_wipe_real(pr, devname, wp, noact, quiet); + if (zap) { + if (backup) + do_backup(wp, backup); + do_wipe_real(pr, devname, wp, flags); + if (wp->is_parttable) + reread = 1; + } } for (w = wp0; w != NULL; w = w->next) { - if (!w->on_disk && !quiet) + if (!w->on_disk && !(flags & WP_FL_QUIET)) warnx(_("%s: offset 0x%jx not found"), devname, w->offset); } fsync(blkid_probe_get_fd(pr)); + + if (reread) + rereadpt(blkid_probe_get_fd(pr), devname); + close(blkid_probe_get_fd(pr)); blkid_free_probe(pr); free_wipe(wp0); + free(backup); return wp; } @@ -372,6 +439,7 @@ usage(FILE *out) fputs(_("\nOptions:\n"), out); fputs(_(" -a, --all wipe all magic strings (BE CAREFUL!)\n" + " -b, --backup create a signature backup in $HOME\n" " -f, --force force erasure\n" " -h, --help show this help text\n" " -n, --no-act do everything except the actual write() call\n" @@ -391,11 +459,12 @@ int main(int argc, char **argv) { struct wipe_desc *wp0 = NULL, *wp; - int c, all = 0, force = 0, has_offset = 0, noact = 0, quiet = 0; + int c, has_offset = 0, flags = 0; int mode = WP_MODE_PRETTY; static const struct option longopts[] = { { "all", 0, 0, 'a' }, + { "backup", 0, 0, 'b' }, { "force", 0, 0, 'f' }, { "help", 0, 0, 'h' }, { "no-act", 0, 0, 'n' }, @@ -424,16 +493,19 @@ main(int argc, char **argv) switch(c) { case 'a': - all++; + flags |= WP_FL_ALL; + break; + case 'b': + flags |= WP_FL_BACKUP; break; case 'f': - force++; + flags |= WP_FL_FORCE; break; case 'h': usage(stdout); break; case 'n': - noact++; + flags |= WP_FL_NOACT; break; case 'o': wp0 = add_offset(wp0, strtosize_or_err(optarg, @@ -444,7 +516,7 @@ main(int argc, char **argv) mode = WP_MODE_PARSABLE; break; case 'q': - quiet++; + flags |= WP_FL_QUIET; break; case 't': type_pattern = optarg; @@ -461,7 +533,10 @@ main(int argc, char **argv) if (optind == argc) usage(stderr); - if (!all && !has_offset) { + if ((flags & WP_FL_BACKUP) && !((flags & WP_FL_ALL) || has_offset)) + warnx(_("The --backup option is meaningless in this context")); + + if (!(flags & WP_FL_ALL) && !has_offset) { /* * Print only */ @@ -477,8 +552,7 @@ main(int argc, char **argv) */ while (optind < argc) { wp = clone_offset(wp0); - wp = do_wipe(wp, argv[optind++], noact, all, quiet, - force); + wp = do_wipe(wp, argv[optind++], flags); free_wipe(wp); } } |
