diff options
| author | Ron Yorston <rmy@pobox.com> | 2013-08-27 16:10:53 +0100 |
|---|---|---|
| committer | Ron Yorston <rmy@pobox.com> | 2013-08-27 16:10:53 +0100 |
| commit | 3fd34651ea72ea1c335d3170f234cb0517fd897f (patch) | |
| tree | 36e8fc40cffd464ffda4759020777dd3ca23ca31 /coreutils | |
| parent | e3ac39098326de084a805d0dd31db9666b734f20 (diff) | |
| parent | d6ae4fb446daedfe3073d67be655942e9fa7eb18 (diff) | |
| download | busybox-w32-3fd34651ea72ea1c335d3170f234cb0517fd897f.tar.gz busybox-w32-3fd34651ea72ea1c335d3170f234cb0517fd897f.tar.bz2 busybox-w32-3fd34651ea72ea1c335d3170f234cb0517fd897f.zip | |
Merge branch 'busybox' into merge
Diffstat (limited to 'coreutils')
| -rw-r--r-- | coreutils/catv.c | 43 | ||||
| -rw-r--r-- | coreutils/dd.c | 115 | ||||
| -rw-r--r-- | coreutils/head.c | 4 | ||||
| -rw-r--r-- | coreutils/head_tail.c | 14 | ||||
| -rw-r--r-- | coreutils/head_tail.h | 6 | ||||
| -rw-r--r-- | coreutils/md5_sha1_sum.c | 4 | ||||
| -rw-r--r-- | coreutils/od_bloaty.c | 12 | ||||
| -rw-r--r-- | coreutils/split.c | 11 | ||||
| -rw-r--r-- | coreutils/stty.c | 105 | ||||
| -rw-r--r-- | coreutils/tail.c | 27 |
10 files changed, 167 insertions, 174 deletions
diff --git a/coreutils/catv.c b/coreutils/catv.c index 214b4311a..e3499c597 100644 --- a/coreutils/catv.c +++ b/coreutils/catv.c | |||
| @@ -25,14 +25,23 @@ int catv_main(int argc UNUSED_PARAM, char **argv) | |||
| 25 | { | 25 | { |
| 26 | int retval = EXIT_SUCCESS; | 26 | int retval = EXIT_SUCCESS; |
| 27 | int fd; | 27 | int fd; |
| 28 | unsigned flags; | 28 | unsigned opts; |
| 29 | |||
| 30 | flags = getopt32(argv, "etv"); | ||
| 31 | #define CATV_OPT_e (1<<0) | 29 | #define CATV_OPT_e (1<<0) |
| 32 | #define CATV_OPT_t (1<<1) | 30 | #define CATV_OPT_t (1<<1) |
| 33 | #define CATV_OPT_v (1<<2) | 31 | #define CATV_OPT_v (1<<2) |
| 34 | flags ^= CATV_OPT_v; | 32 | typedef char BUG_const_mismatch[ |
| 33 | CATV_OPT_e == VISIBLE_ENDLINE && CATV_OPT_t == VISIBLE_SHOW_TABS | ||
| 34 | ? 1 : -1 | ||
| 35 | ]; | ||
| 36 | |||
| 37 | opts = getopt32(argv, "etv"); | ||
| 35 | argv += optind; | 38 | argv += optind; |
| 39 | #if 0 /* These consts match, we can just pass "opts" to visible() */ | ||
| 40 | if (opts & CATV_OPT_e) | ||
| 41 | flags |= VISIBLE_ENDLINE; | ||
| 42 | if (opts & CATV_OPT_t) | ||
| 43 | flags |= VISIBLE_SHOW_TABS; | ||
| 44 | #endif | ||
| 36 | 45 | ||
| 37 | /* Read from stdin if there's nothing else to do. */ | 46 | /* Read from stdin if there's nothing else to do. */ |
| 38 | if (!argv[0]) | 47 | if (!argv[0]) |
| @@ -50,29 +59,17 @@ int catv_main(int argc UNUSED_PARAM, char **argv) | |||
| 50 | res = read(fd, read_buf, COMMON_BUFSIZE); | 59 | res = read(fd, read_buf, COMMON_BUFSIZE); |
| 51 | if (res < 0) | 60 | if (res < 0) |
| 52 | retval = EXIT_FAILURE; | 61 | retval = EXIT_FAILURE; |
| 53 | if (res < 1) | 62 | if (res <= 0) |
| 54 | break; | 63 | break; |
| 55 | for (i = 0; i < res; i++) { | 64 | for (i = 0; i < res; i++) { |
| 56 | unsigned char c = read_buf[i]; | 65 | unsigned char c = read_buf[i]; |
| 57 | 66 | if (opts & CATV_OPT_v) { | |
| 58 | if (c > 126 && (flags & CATV_OPT_v)) { | 67 | putchar(c); |
| 59 | if (c == 127) { | 68 | } else { |
| 60 | printf("^?"); | 69 | char buf[sizeof("M-^c")]; |
| 61 | continue; | 70 | visible(c, buf, opts); |
| 62 | } | 71 | fputs(buf, stdout); |
| 63 | printf("M-"); | ||
| 64 | c -= 128; | ||
| 65 | } | ||
| 66 | if (c < 32) { | ||
| 67 | if (c == 10) { | ||
| 68 | if (flags & CATV_OPT_e) | ||
| 69 | bb_putchar('$'); | ||
| 70 | } else if (flags & (c==9 ? CATV_OPT_t : CATV_OPT_v)) { | ||
| 71 | printf("^%c", c+'@'); | ||
| 72 | continue; | ||
| 73 | } | ||
| 74 | } | 72 | } |
| 75 | bb_putchar(c); | ||
| 76 | } | 73 | } |
| 77 | } | 74 | } |
| 78 | if (ENABLE_FEATURE_CLEAN_UP && fd) | 75 | if (ENABLE_FEATURE_CLEAN_UP && fd) |
diff --git a/coreutils/dd.c b/coreutils/dd.c index f6869cb26..db61f665e 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c | |||
| @@ -30,10 +30,10 @@ | |||
| 30 | //usage: "\n conv=noerror Continue after read errors" | 30 | //usage: "\n conv=noerror Continue after read errors" |
| 31 | //usage: "\n conv=sync Pad blocks with zeros" | 31 | //usage: "\n conv=sync Pad blocks with zeros" |
| 32 | //usage: "\n conv=fsync Physically write data out before finishing" | 32 | //usage: "\n conv=fsync Physically write data out before finishing" |
| 33 | //usage: "\n conv=swab Swap every pair of bytes" | ||
| 33 | //usage: ) | 34 | //usage: ) |
| 34 | //usage: "\n" | 35 | //usage: "\n" |
| 35 | //usage: "\nNumbers may be suffixed by c (x1), w (x2), b (x512), kD (x1000), k (x1024)," | 36 | //usage: "\nN may be suffixed by c (1), w (2), b (512), kD (1000), k (1024), MD, M, GD, G" |
| 36 | //usage: "\nMD (x1000000), M (x1048576), GD (x1000000000) or G (x1073741824)" | ||
| 37 | //usage: | 37 | //usage: |
| 38 | //usage:#define dd_example_usage | 38 | //usage:#define dd_example_usage |
| 39 | //usage: "$ dd if=/dev/zero of=/dev/ram1 bs=1M count=4\n" | 39 | //usage: "$ dd if=/dev/zero of=/dev/ram1 bs=1M count=4\n" |
| @@ -151,13 +151,14 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 151 | enum { | 151 | enum { |
| 152 | /* Must be in the same order as OP_conv_XXX! */ | 152 | /* Must be in the same order as OP_conv_XXX! */ |
| 153 | /* (see "flags |= (1 << what)" below) */ | 153 | /* (see "flags |= (1 << what)" below) */ |
| 154 | FLAG_NOTRUNC = 1 << 0, | 154 | FLAG_NOTRUNC = (1 << 0) * ENABLE_FEATURE_DD_IBS_OBS, |
| 155 | FLAG_SYNC = 1 << 1, | 155 | FLAG_SYNC = (1 << 1) * ENABLE_FEATURE_DD_IBS_OBS, |
| 156 | FLAG_NOERROR = 1 << 2, | 156 | FLAG_NOERROR = (1 << 2) * ENABLE_FEATURE_DD_IBS_OBS, |
| 157 | FLAG_FSYNC = 1 << 3, | 157 | FLAG_FSYNC = (1 << 3) * ENABLE_FEATURE_DD_IBS_OBS, |
| 158 | FLAG_SWAB = (1 << 4) * ENABLE_FEATURE_DD_IBS_OBS, | ||
| 158 | /* end of conv flags */ | 159 | /* end of conv flags */ |
| 159 | FLAG_TWOBUFS = 1 << 4, | 160 | FLAG_TWOBUFS = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS, |
| 160 | FLAG_COUNT = 1 << 5, | 161 | FLAG_COUNT = 1 << 6, |
| 161 | }; | 162 | }; |
| 162 | static const char keywords[] ALIGN1 = | 163 | static const char keywords[] ALIGN1 = |
| 163 | "bs\0""count\0""seek\0""skip\0""if\0""of\0" | 164 | "bs\0""count\0""seek\0""skip\0""if\0""of\0" |
| @@ -167,7 +168,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 167 | ; | 168 | ; |
| 168 | #if ENABLE_FEATURE_DD_IBS_OBS | 169 | #if ENABLE_FEATURE_DD_IBS_OBS |
| 169 | static const char conv_words[] ALIGN1 = | 170 | static const char conv_words[] ALIGN1 = |
| 170 | "notrunc\0""sync\0""noerror\0""fsync\0"; | 171 | "notrunc\0""sync\0""noerror\0""fsync\0""swab\0"; |
| 171 | #endif | 172 | #endif |
| 172 | enum { | 173 | enum { |
| 173 | OP_bs = 0, | 174 | OP_bs = 0, |
| @@ -185,11 +186,11 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 185 | OP_conv_sync, | 186 | OP_conv_sync, |
| 186 | OP_conv_noerror, | 187 | OP_conv_noerror, |
| 187 | OP_conv_fsync, | 188 | OP_conv_fsync, |
| 189 | OP_conv_swab, | ||
| 188 | /* Unimplemented conv=XXX: */ | 190 | /* Unimplemented conv=XXX: */ |
| 189 | //nocreat do not create the output file | 191 | //nocreat do not create the output file |
| 190 | //excl fail if the output file already exists | 192 | //excl fail if the output file already exists |
| 191 | //fdatasync physically write output file data before finishing | 193 | //fdatasync physically write output file data before finishing |
| 192 | //swab swap every pair of input bytes | ||
| 193 | //lcase change upper case to lower case | 194 | //lcase change upper case to lower case |
| 194 | //ucase change lower case to upper case | 195 | //ucase change lower case to upper case |
| 195 | //block pad newline-terminated records with spaces to cbs-size | 196 | //block pad newline-terminated records with spaces to cbs-size |
| @@ -197,23 +198,34 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 197 | //ascii from EBCDIC to ASCII | 198 | //ascii from EBCDIC to ASCII |
| 198 | //ebcdic from ASCII to EBCDIC | 199 | //ebcdic from ASCII to EBCDIC |
| 199 | //ibm from ASCII to alternate EBCDIC | 200 | //ibm from ASCII to alternate EBCDIC |
| 201 | /* Partially implemented: */ | ||
| 202 | //swab swap every pair of input bytes: will abort on non-even reads | ||
| 200 | #endif | 203 | #endif |
| 201 | }; | 204 | }; |
| 202 | int exitcode = EXIT_FAILURE; | 205 | smallint exitcode = EXIT_FAILURE; |
| 203 | int devzero = 0; | 206 | int devzero = 0; |
| 204 | size_t ibs = 512, obs = 512; | 207 | int i; |
| 205 | ssize_t n, w; | 208 | size_t ibs = 512; |
| 206 | char *ibuf, *obuf; | 209 | char *ibuf; |
| 207 | /* And these are all zeroed at once! */ | 210 | #if ENABLE_FEATURE_DD_IBS_OBS |
| 211 | size_t obs = 512; | ||
| 212 | char *obuf; | ||
| 213 | #else | ||
| 214 | # define obs ibs | ||
| 215 | # define obuf ibuf | ||
| 216 | #endif | ||
| 217 | /* These are all zeroed at once! */ | ||
| 208 | struct { | 218 | struct { |
| 209 | int flags; | 219 | int flags; |
| 210 | size_t oc; | 220 | size_t oc; |
| 221 | ssize_t prev_read_size; /* for detecting swab failure */ | ||
| 211 | off_t count; | 222 | off_t count; |
| 212 | off_t seek, skip; | 223 | off_t seek, skip; |
| 213 | const char *infile, *outfile; | 224 | const char *infile, *outfile; |
| 214 | } Z; | 225 | } Z; |
| 215 | #define flags (Z.flags ) | 226 | #define flags (Z.flags ) |
| 216 | #define oc (Z.oc ) | 227 | #define oc (Z.oc ) |
| 228 | #define prev_read_size (Z.prev_read_size) | ||
| 217 | #define count (Z.count ) | 229 | #define count (Z.count ) |
| 218 | #define seek (Z.seek ) | 230 | #define seek (Z.seek ) |
| 219 | #define skip (Z.skip ) | 231 | #define skip (Z.skip ) |
| @@ -224,10 +236,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 224 | INIT_G(); | 236 | INIT_G(); |
| 225 | //fflush_all(); - is this needed because of NOEXEC? | 237 | //fflush_all(); - is this needed because of NOEXEC? |
| 226 | 238 | ||
| 227 | for (n = 1; argv[n]; n++) { | 239 | for (i = 1; argv[i]; i++) { |
| 228 | int what; | 240 | int what; |
| 229 | char *val; | 241 | char *val; |
| 230 | char *arg = argv[n]; | 242 | char *arg = argv[i]; |
| 231 | 243 | ||
| 232 | #if ENABLE_DESKTOP | 244 | #if ENABLE_DESKTOP |
| 233 | /* "dd --". NB: coreutils 6.9 will complain if they see | 245 | /* "dd --". NB: coreutils 6.9 will complain if they see |
| @@ -256,6 +268,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 256 | } | 268 | } |
| 257 | if (what == OP_conv) { | 269 | if (what == OP_conv) { |
| 258 | while (1) { | 270 | while (1) { |
| 271 | int n; | ||
| 259 | /* find ',', replace them with NUL so we can use val for | 272 | /* find ',', replace them with NUL so we can use val for |
| 260 | * index_in_strings() without copying. | 273 | * index_in_strings() without copying. |
| 261 | * We rely on val being non-null, else strchr would fault. | 274 | * We rely on val being non-null, else strchr would fault. |
| @@ -263,20 +276,21 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 263 | arg = strchr(val, ','); | 276 | arg = strchr(val, ','); |
| 264 | if (arg) | 277 | if (arg) |
| 265 | *arg = '\0'; | 278 | *arg = '\0'; |
| 266 | what = index_in_strings(conv_words, val); | 279 | n = index_in_strings(conv_words, val); |
| 267 | if (what < 0) | 280 | if (n < 0) |
| 268 | bb_error_msg_and_die(bb_msg_invalid_arg, val, "conv"); | 281 | bb_error_msg_and_die(bb_msg_invalid_arg, val, "conv"); |
| 269 | flags |= (1 << what); | 282 | flags |= (1 << n); |
| 270 | if (!arg) /* no ',' left, so this was the last specifier */ | 283 | if (!arg) /* no ',' left, so this was the last specifier */ |
| 271 | break; | 284 | break; |
| 272 | /* *arg = ','; - to preserve ps listing? */ | 285 | /* *arg = ','; - to preserve ps listing? */ |
| 273 | val = arg + 1; /* skip this keyword and ',' */ | 286 | val = arg + 1; /* skip this keyword and ',' */ |
| 274 | } | 287 | } |
| 275 | continue; /* we trashed 'what', can't fall through */ | 288 | /*continue;*/ |
| 276 | } | 289 | } |
| 277 | #endif | 290 | #endif |
| 278 | if (what == OP_bs) { | 291 | if (what == OP_bs) { |
| 279 | ibs = obs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes); | 292 | ibs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes); |
| 293 | obs = ibs; | ||
| 280 | /*continue;*/ | 294 | /*continue;*/ |
| 281 | } | 295 | } |
| 282 | /* These can be large: */ | 296 | /* These can be large: */ |
| @@ -301,14 +315,17 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 301 | outfile = val; | 315 | outfile = val; |
| 302 | /*continue;*/ | 316 | /*continue;*/ |
| 303 | } | 317 | } |
| 304 | } /* end of "for (argv[n])" */ | 318 | } /* end of "for (argv[i])" */ |
| 305 | 319 | ||
| 306 | //XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever | 320 | //XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever |
| 307 | ibuf = obuf = xmalloc(ibs); | 321 | ibuf = xmalloc(ibs); |
| 322 | obuf = ibuf; | ||
| 323 | #if ENABLE_FEATURE_DD_IBS_OBS | ||
| 308 | if (ibs != obs) { | 324 | if (ibs != obs) { |
| 309 | flags |= FLAG_TWOBUFS; | 325 | flags |= FLAG_TWOBUFS; |
| 310 | obuf = xmalloc(obs); | 326 | obuf = xmalloc(obs); |
| 311 | } | 327 | } |
| 328 | #endif | ||
| 312 | 329 | ||
| 313 | #if ENABLE_FEATURE_DD_SIGNAL_HANDLING | 330 | #if ENABLE_FEATURE_DD_SIGNAL_HANDLING |
| 314 | signal_SA_RESTART_empty_mask(SIGUSR1, dd_output_status); | 331 | signal_SA_RESTART_empty_mask(SIGUSR1, dd_output_status); |
| @@ -317,17 +334,17 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 317 | G.begin_time_us = monotonic_us(); | 334 | G.begin_time_us = monotonic_us(); |
| 318 | #endif | 335 | #endif |
| 319 | 336 | ||
| 320 | if (infile != NULL) | 337 | if (infile) { |
| 321 | if (ENABLE_PLATFORM_MINGW32 && !strcmp(infile, "/dev/zero")) { | 338 | if (ENABLE_PLATFORM_MINGW32 && !strcmp(infile, "/dev/zero")) { |
| 322 | flags |= FLAG_NOERROR; | 339 | flags |= FLAG_NOERROR; |
| 323 | devzero = 1; | 340 | devzero = 1; |
| 324 | } | 341 | } else { |
| 325 | else | ||
| 326 | xmove_fd(xopen(infile, O_RDONLY), ifd); | 342 | xmove_fd(xopen(infile, O_RDONLY), ifd); |
| 327 | else { | 343 | } |
| 344 | } else { | ||
| 328 | infile = bb_msg_standard_input; | 345 | infile = bb_msg_standard_input; |
| 329 | } | 346 | } |
| 330 | if (outfile != NULL) { | 347 | if (outfile) { |
| 331 | int oflag = O_WRONLY | O_CREAT; | 348 | int oflag = O_WRONLY | O_CREAT; |
| 332 | 349 | ||
| 333 | if (!seek && !(flags & FLAG_NOTRUNC)) | 350 | if (!seek && !(flags & FLAG_NOTRUNC)) |
| @@ -352,13 +369,13 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 352 | } | 369 | } |
| 353 | if (skip && !devzero) { | 370 | if (skip && !devzero) { |
| 354 | if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) { | 371 | if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) { |
| 355 | while (skip-- > 0) { | 372 | do { |
| 356 | n = safe_read(ifd, ibuf, ibs); | 373 | ssize_t n = safe_read(ifd, ibuf, ibs); |
| 357 | if (n < 0) | 374 | if (n < 0) |
| 358 | goto die_infile; | 375 | goto die_infile; |
| 359 | if (n == 0) | 376 | if (n == 0) |
| 360 | break; | 377 | break; |
| 361 | } | 378 | } while (--skip != 0); |
| 362 | } | 379 | } |
| 363 | } | 380 | } |
| 364 | if (seek) { | 381 | if (seek) { |
| @@ -367,6 +384,8 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 367 | } | 384 | } |
| 368 | 385 | ||
| 369 | while (!(flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) { | 386 | while (!(flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) { |
| 387 | ssize_t n; | ||
| 388 | |||
| 370 | if (devzero) { | 389 | if (devzero) { |
| 371 | memset(ibuf, 0, ibs); | 390 | memset(ibuf, 0, ibs); |
| 372 | n = ibs; | 391 | n = ibs; |
| @@ -386,6 +405,27 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 386 | * conv=noerror just ignores input bad blocks */ | 405 | * conv=noerror just ignores input bad blocks */ |
| 387 | n = 0; | 406 | n = 0; |
| 388 | } | 407 | } |
| 408 | if (flags & FLAG_SWAB) { | ||
| 409 | uint16_t *p16; | ||
| 410 | ssize_t n2; | ||
| 411 | |||
| 412 | /* Our code allows only last read to be odd-sized */ | ||
| 413 | if (prev_read_size & 1) | ||
| 414 | bb_error_msg_and_die("can't swab %lu byte buffer", | ||
| 415 | (unsigned long)prev_read_size); | ||
| 416 | prev_read_size = n; | ||
| 417 | |||
| 418 | /* If n is odd, last byte is not swapped: | ||
| 419 | * echo -n "qwe" | dd conv=swab | ||
| 420 | * prints "wqe". | ||
| 421 | */ | ||
| 422 | p16 = (void*) ibuf; | ||
| 423 | n2 = (n >> 1); | ||
| 424 | while (--n2 >= 0) { | ||
| 425 | *p16 = bswap_16(*p16); | ||
| 426 | p16++; | ||
| 427 | } | ||
| 428 | } | ||
| 389 | if ((size_t)n == ibs) | 429 | if ((size_t)n == ibs) |
| 390 | G.in_full++; | 430 | G.in_full++; |
| 391 | else { | 431 | else { |
| @@ -412,8 +452,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 412 | oc = 0; | 452 | oc = 0; |
| 413 | } | 453 | } |
| 414 | } | 454 | } |
| 415 | } else if (write_and_stats(ibuf, n, obs, outfile)) | 455 | } else { |
| 416 | goto out_status; | 456 | if (write_and_stats(ibuf, n, obs, outfile)) |
| 457 | goto out_status; | ||
| 458 | } | ||
| 417 | 459 | ||
| 418 | if (flags & FLAG_FSYNC) { | 460 | if (flags & FLAG_FSYNC) { |
| 419 | if (fsync(ofd) < 0) | 461 | if (fsync(ofd) < 0) |
| @@ -422,9 +464,8 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 422 | } | 464 | } |
| 423 | 465 | ||
| 424 | if (ENABLE_FEATURE_DD_IBS_OBS && oc) { | 466 | if (ENABLE_FEATURE_DD_IBS_OBS && oc) { |
| 425 | w = full_write_or_warn(obuf, oc, outfile); | 467 | if (write_and_stats(obuf, oc, obs, outfile)) |
| 426 | if (w < 0) goto out_status; | 468 | goto out_status; |
| 427 | if (w > 0) G.out_part++; | ||
| 428 | } | 469 | } |
| 429 | 470 | ||
| 430 | if (!devzero && close(ifd) < 0) { | 471 | if (!devzero && close(ifd) < 0) { |
diff --git a/coreutils/head.c b/coreutils/head.c index 291e1ce37..9388b026a 100644 --- a/coreutils/head.c +++ b/coreutils/head.c | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/head.html */ | 12 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/head.html */ |
| 13 | 13 | ||
| 14 | //kbuild:lib-$(CONFIG_HEAD) += head.o | 14 | //kbuild:lib-$(CONFIG_HEAD) += head.o |
| 15 | //kbuild:lib-$(CONFIG_HEAD) += head_tail.o | ||
| 16 | 15 | ||
| 17 | //usage:#define head_trivial_usage | 16 | //usage:#define head_trivial_usage |
| 18 | //usage: "[OPTIONS] [FILE]..." | 17 | //usage: "[OPTIONS] [FILE]..." |
| @@ -35,7 +34,6 @@ | |||
| 35 | //usage: "daemon:x:1:1:daemon:/usr/sbin:/bin/sh\n" | 34 | //usage: "daemon:x:1:1:daemon:/usr/sbin:/bin/sh\n" |
| 36 | 35 | ||
| 37 | #include "libbb.h" | 36 | #include "libbb.h" |
| 38 | #include "head_tail.h" | ||
| 39 | 37 | ||
| 40 | /* This is a NOEXEC applet. Be very careful! */ | 38 | /* This is a NOEXEC applet. Be very careful! */ |
| 41 | 39 | ||
| @@ -140,7 +138,7 @@ eat_num(bool *negative_N, const char *p) | |||
| 140 | p++; | 138 | p++; |
| 141 | } | 139 | } |
| 142 | #endif | 140 | #endif |
| 143 | return xatoul_sfx(p, head_tail_suffixes); | 141 | return xatoul_sfx(p, bkm_suffixes); |
| 144 | } | 142 | } |
| 145 | 143 | ||
| 146 | static const char head_opts[] ALIGN1 = | 144 | static const char head_opts[] ALIGN1 = |
diff --git a/coreutils/head_tail.c b/coreutils/head_tail.c deleted file mode 100644 index 1658c0d1b..000000000 --- a/coreutils/head_tail.c +++ /dev/null | |||
| @@ -1,14 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2013 Denys Vlasenko | ||
| 3 | * | ||
| 4 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
| 5 | */ | ||
| 6 | #include "libbb.h" | ||
| 7 | #include "head_tail.h" | ||
| 8 | |||
| 9 | const struct suffix_mult head_tail_suffixes[] = { | ||
| 10 | { "b", 512 }, | ||
| 11 | { "k", 1024 }, | ||
| 12 | { "m", 1024*1024 }, | ||
| 13 | { "", 0 } | ||
| 14 | }; | ||
diff --git a/coreutils/head_tail.h b/coreutils/head_tail.h deleted file mode 100644 index df19e41e0..000000000 --- a/coreutils/head_tail.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2013 Denys Vlasenko | ||
| 3 | * | ||
| 4 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
| 5 | */ | ||
| 6 | extern const struct suffix_mult head_tail_suffixes[]; | ||
diff --git a/coreutils/md5_sha1_sum.c b/coreutils/md5_sha1_sum.c index 92a4d4462..1a5342e87 100644 --- a/coreutils/md5_sha1_sum.c +++ b/coreutils/md5_sha1_sum.c | |||
| @@ -151,7 +151,9 @@ static uint8_t *hash_file(const char *filename) | |||
| 151 | update(&context, in_buf, count); | 151 | update(&context, in_buf, count); |
| 152 | } | 152 | } |
| 153 | hash_value = NULL; | 153 | hash_value = NULL; |
| 154 | if (count == 0) { | 154 | if (count < 0) |
| 155 | bb_perror_msg("can't read '%s'", filename); | ||
| 156 | else /* count == 0 */ { | ||
| 155 | final(&context, in_buf); | 157 | final(&context, in_buf); |
| 156 | hash_value = hash_bin_to_hex(in_buf, hash_len); | 158 | hash_value = hash_bin_to_hex(in_buf, hash_len); |
| 157 | } | 159 | } |
diff --git a/coreutils/od_bloaty.c b/coreutils/od_bloaty.c index ee4f72ca1..c4d11601f 100644 --- a/coreutils/od_bloaty.c +++ b/coreutils/od_bloaty.c | |||
| @@ -1173,12 +1173,6 @@ parse_old_offset(const char *s, off_t *offset) | |||
| 1173 | int od_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 1173 | int od_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| 1174 | int od_main(int argc UNUSED_PARAM, char **argv) | 1174 | int od_main(int argc UNUSED_PARAM, char **argv) |
| 1175 | { | 1175 | { |
| 1176 | static const struct suffix_mult bkm[] = { | ||
| 1177 | { "b", 512 }, | ||
| 1178 | { "k", 1024 }, | ||
| 1179 | { "m", 1024*1024 }, | ||
| 1180 | { "", 0 } | ||
| 1181 | }; | ||
| 1182 | #if ENABLE_LONG_OPTS | 1176 | #if ENABLE_LONG_OPTS |
| 1183 | static const char od_longopts[] ALIGN1 = | 1177 | static const char od_longopts[] ALIGN1 = |
| 1184 | "skip-bytes\0" Required_argument "j" | 1178 | "skip-bytes\0" Required_argument "j" |
| @@ -1237,7 +1231,7 @@ int od_main(int argc UNUSED_PARAM, char **argv) | |||
| 1237 | address_pad_len_char = doxn_address_pad_len_char[pos]; | 1231 | address_pad_len_char = doxn_address_pad_len_char[pos]; |
| 1238 | } | 1232 | } |
| 1239 | if (opt & OPT_N) { | 1233 | if (opt & OPT_N) { |
| 1240 | max_bytes_to_format = xstrtooff_sfx(str_N, 0, bkm); | 1234 | max_bytes_to_format = xstrtooff_sfx(str_N, 0, bkm_suffixes); |
| 1241 | } | 1235 | } |
| 1242 | if (opt & OPT_a) decode_format_string("a"); | 1236 | if (opt & OPT_a) decode_format_string("a"); |
| 1243 | if (opt & OPT_b) decode_format_string("oC"); | 1237 | if (opt & OPT_b) decode_format_string("oC"); |
| @@ -1246,7 +1240,7 @@ int od_main(int argc UNUSED_PARAM, char **argv) | |||
| 1246 | if (opt & OPT_f) decode_format_string("fF"); | 1240 | if (opt & OPT_f) decode_format_string("fF"); |
| 1247 | if (opt & OPT_h) decode_format_string("x2"); | 1241 | if (opt & OPT_h) decode_format_string("x2"); |
| 1248 | if (opt & OPT_i) decode_format_string("d2"); | 1242 | if (opt & OPT_i) decode_format_string("d2"); |
| 1249 | if (opt & OPT_j) n_bytes_to_skip = xstrtooff_sfx(str_j, 0, bkm); | 1243 | if (opt & OPT_j) n_bytes_to_skip = xstrtooff_sfx(str_j, 0, bkm_suffixes); |
| 1250 | if (opt & OPT_l) decode_format_string("d4"); | 1244 | if (opt & OPT_l) decode_format_string("d4"); |
| 1251 | if (opt & OPT_o) decode_format_string("o2"); | 1245 | if (opt & OPT_o) decode_format_string("o2"); |
| 1252 | while (lst_t) { | 1246 | while (lst_t) { |
| @@ -1255,7 +1249,7 @@ int od_main(int argc UNUSED_PARAM, char **argv) | |||
| 1255 | if (opt & OPT_x) decode_format_string("x2"); | 1249 | if (opt & OPT_x) decode_format_string("x2"); |
| 1256 | if (opt & OPT_s) decode_format_string("d2"); | 1250 | if (opt & OPT_s) decode_format_string("d2"); |
| 1257 | if (opt & OPT_S) { | 1251 | if (opt & OPT_S) { |
| 1258 | string_min = xstrtou_sfx(str_S, 0, bkm); | 1252 | string_min = xstrtou_sfx(str_S, 0, bkm_suffixes); |
| 1259 | } | 1253 | } |
| 1260 | 1254 | ||
| 1261 | // Bloat: | 1255 | // Bloat: |
diff --git a/coreutils/split.c b/coreutils/split.c index 11e640442..1e1673efb 100644 --- a/coreutils/split.c +++ b/coreutils/split.c | |||
| @@ -23,17 +23,15 @@ | |||
| 23 | 23 | ||
| 24 | #include "libbb.h" | 24 | #include "libbb.h" |
| 25 | 25 | ||
| 26 | static const struct suffix_mult split_suffices[] = { | ||
| 27 | #if ENABLE_FEATURE_SPLIT_FANCY | 26 | #if ENABLE_FEATURE_SPLIT_FANCY |
| 27 | static const struct suffix_mult split_suffixes[] = { | ||
| 28 | { "b", 512 }, | 28 | { "b", 512 }, |
| 29 | #endif | ||
| 30 | { "k", 1024 }, | 29 | { "k", 1024 }, |
| 31 | { "m", 1024*1024 }, | 30 | { "m", 1024*1024 }, |
| 32 | #if ENABLE_FEATURE_SPLIT_FANCY | ||
| 33 | { "g", 1024*1024*1024 }, | 31 | { "g", 1024*1024*1024 }, |
| 34 | #endif | ||
| 35 | { "", 0 } | 32 | { "", 0 } |
| 36 | }; | 33 | }; |
| 34 | #endif | ||
| 37 | 35 | ||
| 38 | /* Increment the suffix part of the filename. | 36 | /* Increment the suffix part of the filename. |
| 39 | * Returns NULL if we are out of filenames. | 37 | * Returns NULL if we are out of filenames. |
| @@ -86,7 +84,10 @@ int split_main(int argc UNUSED_PARAM, char **argv) | |||
| 86 | if (opt & SPLIT_OPT_l) | 84 | if (opt & SPLIT_OPT_l) |
| 87 | cnt = XATOOFF(count_p); | 85 | cnt = XATOOFF(count_p); |
| 88 | if (opt & SPLIT_OPT_b) // FIXME: also needs XATOOFF | 86 | if (opt & SPLIT_OPT_b) // FIXME: also needs XATOOFF |
| 89 | cnt = xatoull_sfx(count_p, split_suffices); | 87 | cnt = xatoull_sfx(count_p, |
| 88 | IF_FEATURE_SPLIT_FANCY(split_suffixes) | ||
| 89 | IF_NOT_FEATURE_SPLIT_FANCY(km_suffixes) | ||
| 90 | ); | ||
| 90 | sfx = "x"; | 91 | sfx = "x"; |
| 91 | 92 | ||
| 92 | argv += optind; | 93 | argv += optind; |
diff --git a/coreutils/stty.c b/coreutils/stty.c index 96754dd84..378a848e7 100644 --- a/coreutils/stty.c +++ b/coreutils/stty.c | |||
| @@ -246,10 +246,21 @@ enum speed_setting { | |||
| 246 | 246 | ||
| 247 | /* Which member(s) of 'struct termios' a mode uses */ | 247 | /* Which member(s) of 'struct termios' a mode uses */ |
| 248 | enum { | 248 | enum { |
| 249 | /* Do NOT change the order or values, as mode_type_flag() | ||
| 250 | * depends on them */ | ||
| 251 | control, input, output, local, combination | 249 | control, input, output, local, combination |
| 252 | }; | 250 | }; |
| 251 | static tcflag_t *get_ptr_to_tcflag(unsigned type, const struct termios *mode) | ||
| 252 | { | ||
| 253 | static const uint8_t tcflag_offsets[] ALIGN1 = { | ||
| 254 | offsetof(struct termios, c_cflag), /* control */ | ||
| 255 | offsetof(struct termios, c_iflag), /* input */ | ||
| 256 | offsetof(struct termios, c_oflag), /* output */ | ||
| 257 | offsetof(struct termios, c_lflag) /* local */ | ||
| 258 | }; | ||
| 259 | if (type <= local) { | ||
| 260 | return (tcflag_t*) (((char*)mode) + tcflag_offsets[type]); | ||
| 261 | } | ||
| 262 | return NULL; | ||
| 263 | } | ||
| 253 | 264 | ||
| 254 | /* Flags for 'struct mode_info' */ | 265 | /* Flags for 'struct mode_info' */ |
| 255 | #define SANE_SET 1 /* Set in 'sane' mode */ | 266 | #define SANE_SET 1 /* Set in 'sane' mode */ |
| @@ -770,51 +781,6 @@ struct globals { | |||
| 770 | G.max_col = 80; \ | 781 | G.max_col = 80; \ |
| 771 | } while (0) | 782 | } while (0) |
| 772 | 783 | ||
| 773 | |||
| 774 | /* Return a string that is the printable representation of character CH */ | ||
| 775 | /* Adapted from 'cat' by Torbjorn Granlund */ | ||
| 776 | static const char *visible(unsigned ch) | ||
| 777 | { | ||
| 778 | char *bpout = G.buf; | ||
| 779 | |||
| 780 | if (ch == _POSIX_VDISABLE) | ||
| 781 | return "<undef>"; | ||
| 782 | |||
| 783 | if (ch >= 128) { | ||
| 784 | ch -= 128; | ||
| 785 | *bpout++ = 'M'; | ||
| 786 | *bpout++ = '-'; | ||
| 787 | } | ||
| 788 | |||
| 789 | if (ch < 32) { | ||
| 790 | *bpout++ = '^'; | ||
| 791 | *bpout++ = ch + 64; | ||
| 792 | } else if (ch < 127) { | ||
| 793 | *bpout++ = ch; | ||
| 794 | } else { | ||
| 795 | *bpout++ = '^'; | ||
| 796 | *bpout++ = '?'; | ||
| 797 | } | ||
| 798 | |||
| 799 | *bpout = '\0'; | ||
| 800 | return G.buf; | ||
| 801 | } | ||
| 802 | |||
| 803 | static tcflag_t *mode_type_flag(unsigned type, const struct termios *mode) | ||
| 804 | { | ||
| 805 | static const uint8_t tcflag_offsets[] ALIGN1 = { | ||
| 806 | offsetof(struct termios, c_cflag), /* control */ | ||
| 807 | offsetof(struct termios, c_iflag), /* input */ | ||
| 808 | offsetof(struct termios, c_oflag), /* output */ | ||
| 809 | offsetof(struct termios, c_lflag) /* local */ | ||
| 810 | }; | ||
| 811 | |||
| 812 | if (type <= local) { | ||
| 813 | return (tcflag_t*) (((char*)mode) + tcflag_offsets[type]); | ||
| 814 | } | ||
| 815 | return NULL; | ||
| 816 | } | ||
| 817 | |||
| 818 | static void set_speed_or_die(enum speed_setting type, const char *arg, | 784 | static void set_speed_or_die(enum speed_setting type, const char *arg, |
| 819 | struct termios *mode) | 785 | struct termios *mode) |
| 820 | { | 786 | { |
| @@ -1042,6 +1008,7 @@ static void do_display(const struct termios *mode, int all) | |||
| 1042 | #endif | 1008 | #endif |
| 1043 | 1009 | ||
| 1044 | for (i = 0; i != CIDX_min; ++i) { | 1010 | for (i = 0; i != CIDX_min; ++i) { |
| 1011 | char ch; | ||
| 1045 | /* If swtch is the same as susp, don't print both */ | 1012 | /* If swtch is the same as susp, don't print both */ |
| 1046 | #if VSWTCH == VSUSP | 1013 | #if VSWTCH == VSUSP |
| 1047 | if (i == CIDX_swtch) | 1014 | if (i == CIDX_swtch) |
| @@ -1055,8 +1022,12 @@ static void do_display(const struct termios *mode, int all) | |||
| 1055 | continue; | 1022 | continue; |
| 1056 | } | 1023 | } |
| 1057 | #endif | 1024 | #endif |
| 1058 | wrapf("%s = %s;", nth_string(control_name, i), | 1025 | ch = mode->c_cc[control_info[i].offset]; |
| 1059 | visible(mode->c_cc[control_info[i].offset])); | 1026 | if (ch == _POSIX_VDISABLE) |
| 1027 | strcpy(G.buf, "<undef>"); | ||
| 1028 | else | ||
| 1029 | visible(ch, G.buf, 0); | ||
| 1030 | wrapf("%s = %s;", nth_string(control_name, i), G.buf); | ||
| 1060 | } | 1031 | } |
| 1061 | #if VEOF == VMIN | 1032 | #if VEOF == VMIN |
| 1062 | if ((mode->c_lflag & ICANON) == 0) | 1033 | if ((mode->c_lflag & ICANON) == 0) |
| @@ -1072,7 +1043,7 @@ static void do_display(const struct termios *mode, int all) | |||
| 1072 | prev_type = mode_info[i].type; | 1043 | prev_type = mode_info[i].type; |
| 1073 | } | 1044 | } |
| 1074 | 1045 | ||
| 1075 | bitsp = mode_type_flag(mode_info[i].type, mode); | 1046 | bitsp = get_ptr_to_tcflag(mode_info[i].type, mode); |
| 1076 | mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits; | 1047 | mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits; |
| 1077 | if ((*bitsp & mask) == mode_info[i].bits) { | 1048 | if ((*bitsp & mask) == mode_info[i].bits) { |
| 1078 | if (all || (mode_info[i].flags & SANE_UNSET)) | 1049 | if (all || (mode_info[i].flags & SANE_UNSET)) |
| @@ -1091,7 +1062,6 @@ static void do_display(const struct termios *mode, int all) | |||
| 1091 | static void sane_mode(struct termios *mode) | 1062 | static void sane_mode(struct termios *mode) |
| 1092 | { | 1063 | { |
| 1093 | int i; | 1064 | int i; |
| 1094 | tcflag_t *bitsp; | ||
| 1095 | 1065 | ||
| 1096 | for (i = 0; i < NUM_control_info; ++i) { | 1066 | for (i = 0; i < NUM_control_info; ++i) { |
| 1097 | #if VMIN == VEOF | 1067 | #if VMIN == VEOF |
| @@ -1102,14 +1072,17 @@ static void sane_mode(struct termios *mode) | |||
| 1102 | } | 1072 | } |
| 1103 | 1073 | ||
| 1104 | for (i = 0; i < NUM_mode_info; ++i) { | 1074 | for (i = 0; i < NUM_mode_info; ++i) { |
| 1075 | tcflag_t val; | ||
| 1076 | tcflag_t *bitsp = get_ptr_to_tcflag(mode_info[i].type, mode); | ||
| 1077 | |||
| 1078 | if (!bitsp) | ||
| 1079 | continue; | ||
| 1080 | val = *bitsp & ~((unsigned long)mode_info[i].mask); | ||
| 1105 | if (mode_info[i].flags & SANE_SET) { | 1081 | if (mode_info[i].flags & SANE_SET) { |
| 1106 | bitsp = mode_type_flag(mode_info[i].type, mode); | 1082 | *bitsp = val | mode_info[i].bits; |
| 1107 | *bitsp = (*bitsp & ~((unsigned long)mode_info[i].mask)) | 1083 | } else |
| 1108 | | mode_info[i].bits; | 1084 | if (mode_info[i].flags & SANE_UNSET) { |
| 1109 | } else if (mode_info[i].flags & SANE_UNSET) { | 1085 | *bitsp = val & ~mode_info[i].bits; |
| 1110 | bitsp = mode_type_flag(mode_info[i].type, mode); | ||
| 1111 | *bitsp = *bitsp & ~((unsigned long)mode_info[i].mask) | ||
| 1112 | & ~mode_info[i].bits; | ||
| 1113 | } | 1086 | } |
| 1114 | } | 1087 | } |
| 1115 | } | 1088 | } |
| @@ -1119,17 +1092,18 @@ static void set_mode(const struct mode_info *info, int reversed, | |||
| 1119 | { | 1092 | { |
| 1120 | tcflag_t *bitsp; | 1093 | tcflag_t *bitsp; |
| 1121 | 1094 | ||
| 1122 | bitsp = mode_type_flag(info->type, mode); | 1095 | bitsp = get_ptr_to_tcflag(info->type, mode); |
| 1123 | 1096 | ||
| 1124 | if (bitsp) { | 1097 | if (bitsp) { |
| 1098 | tcflag_t val = *bitsp & ~info->mask; | ||
| 1125 | if (reversed) | 1099 | if (reversed) |
| 1126 | *bitsp = *bitsp & ~info->mask & ~info->bits; | 1100 | *bitsp = val & ~info->bits; |
| 1127 | else | 1101 | else |
| 1128 | *bitsp = (*bitsp & ~info->mask) | info->bits; | 1102 | *bitsp = val | info->bits; |
| 1129 | return; | 1103 | return; |
| 1130 | } | 1104 | } |
| 1131 | 1105 | ||
| 1132 | /* Combination mode */ | 1106 | /* !bitsp - it's a "combination" mode */ |
| 1133 | if (info == &mode_info[IDX_evenp] || info == &mode_info[IDX_parity]) { | 1107 | if (info == &mode_info[IDX_evenp] || info == &mode_info[IDX_parity]) { |
| 1134 | if (reversed) | 1108 | if (reversed) |
| 1135 | mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8; | 1109 | mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8; |
| @@ -1534,7 +1508,12 @@ int stty_main(int argc UNUSED_PARAM, char **argv) | |||
| 1534 | perror_on_device_and_die("%s"); | 1508 | perror_on_device_and_die("%s"); |
| 1535 | 1509 | ||
| 1536 | if (memcmp(&mode, &new_mode, sizeof(mode)) != 0) { | 1510 | if (memcmp(&mode, &new_mode, sizeof(mode)) != 0) { |
| 1537 | #if CIBAUD | 1511 | /* |
| 1512 | * I think the below chunk is not necessary on Linux. | ||
| 1513 | * If you are deleting it, also delete STTY_speed_was_set bit - | ||
| 1514 | * it is only ever checked here. | ||
| 1515 | */ | ||
| 1516 | #if 0 /* was "if CIBAUD" */ | ||
| 1538 | /* SunOS 4.1.3 (at least) has the problem that after this sequence, | 1517 | /* SunOS 4.1.3 (at least) has the problem that after this sequence, |
| 1539 | tcgetattr (&m1); tcsetattr (&m1); tcgetattr (&m2); | 1518 | tcgetattr (&m1); tcsetattr (&m1); tcgetattr (&m2); |
| 1540 | sometimes (m1 != m2). The only difference is in the four bits | 1519 | sometimes (m1 != m2). The only difference is in the four bits |
diff --git a/coreutils/tail.c b/coreutils/tail.c index 19fd8f695..07c71ca4b 100644 --- a/coreutils/tail.c +++ b/coreutils/tail.c | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | */ | 25 | */ |
| 26 | 26 | ||
| 27 | //kbuild:lib-$(CONFIG_TAIL) += tail.o | 27 | //kbuild:lib-$(CONFIG_TAIL) += tail.o |
| 28 | //kbuild:lib-$(CONFIG_TAIL) += head_tail.o | ||
| 29 | 28 | ||
| 30 | //usage:#define tail_trivial_usage | 29 | //usage:#define tail_trivial_usage |
| 31 | //usage: "[OPTIONS] [FILE]..." | 30 | //usage: "[OPTIONS] [FILE]..." |
| @@ -51,7 +50,6 @@ | |||
| 51 | //usage: "nameserver 10.0.0.1\n" | 50 | //usage: "nameserver 10.0.0.1\n" |
| 52 | 51 | ||
| 53 | #include "libbb.h" | 52 | #include "libbb.h" |
| 54 | #include "head_tail.h" | ||
| 55 | 53 | ||
| 56 | struct globals { | 54 | struct globals { |
| 57 | bool from_top; | 55 | bool from_top; |
| @@ -69,15 +67,6 @@ static void tail_xprint_header(const char *fmt, const char *filename) | |||
| 69 | static ssize_t tail_read(int fd, char *buf, size_t count) | 67 | static ssize_t tail_read(int fd, char *buf, size_t count) |
| 70 | { | 68 | { |
| 71 | ssize_t r; | 69 | ssize_t r; |
| 72 | off_t current; | ||
| 73 | struct stat sbuf; | ||
| 74 | |||
| 75 | /* /proc files report zero st_size, don't lseek them. */ | ||
| 76 | if (fstat(fd, &sbuf) == 0 && sbuf.st_size > 0) { | ||
| 77 | current = lseek(fd, 0, SEEK_CUR); | ||
| 78 | if (sbuf.st_size < current) | ||
| 79 | xlseek(fd, 0, SEEK_SET); | ||
| 80 | } | ||
| 81 | 70 | ||
| 82 | r = full_read(fd, buf, count); | 71 | r = full_read(fd, buf, count); |
| 83 | if (r < 0) { | 72 | if (r < 0) { |
| @@ -98,7 +87,7 @@ static unsigned eat_num(const char *p) | |||
| 98 | p++; | 87 | p++; |
| 99 | G.from_top = 1; | 88 | G.from_top = 1; |
| 100 | } | 89 | } |
| 101 | return xatou_sfx(p, head_tail_suffixes); | 90 | return xatou_sfx(p, bkm_suffixes); |
| 102 | } | 91 | } |
| 103 | 92 | ||
| 104 | int tail_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 93 | int tail_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| @@ -363,7 +352,19 @@ int tail_main(int argc, char **argv) | |||
| 363 | if (nfiles > header_threshhold) { | 352 | if (nfiles > header_threshhold) { |
| 364 | fmt = header_fmt_str; | 353 | fmt = header_fmt_str; |
| 365 | } | 354 | } |
| 366 | while ((nread = tail_read(fd, tailbuf, BUFSIZ)) > 0) { | 355 | for (;;) { |
| 356 | /* tail -f keeps following files even if they are truncated */ | ||
| 357 | struct stat sbuf; | ||
| 358 | /* /proc files report zero st_size, don't lseek them */ | ||
| 359 | if (fstat(fd, &sbuf) == 0 && sbuf.st_size > 0) { | ||
| 360 | off_t current = lseek(fd, 0, SEEK_CUR); | ||
| 361 | if (sbuf.st_size < current) | ||
| 362 | xlseek(fd, 0, SEEK_SET); | ||
| 363 | } | ||
| 364 | |||
| 365 | nread = tail_read(fd, tailbuf, BUFSIZ); | ||
| 366 | if (nread <= 0) | ||
| 367 | break; | ||
| 367 | if (fmt) { | 368 | if (fmt) { |
| 368 | tail_xprint_header(fmt, filename); | 369 | tail_xprint_header(fmt, filename); |
| 369 | fmt = NULL; | 370 | fmt = NULL; |
