From 4d1616179745ee3883a726aaf13468e9c44dff9e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 17 Jun 2021 23:53:30 +0200 Subject: xxd: implement -o DISPLAYOFFSET function old new delta xxd_main 680 710 +30 xstrtoll - 30 +30 bb_dump_dump 1511 1531 +20 rewrite 941 951 +10 packed_usage 33629 33639 +10 .rodata 103250 103252 +2 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 5/0 up/down: 102/0) Total: 102 bytes Signed-off-by: Denys Vlasenko --- include/dump.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/dump.h b/include/dump.h index 9193a6925..54f5629a7 100644 --- a/include/dump.h +++ b/include/dump.h @@ -32,8 +32,9 @@ typedef struct dumper_t { off_t dump_skip; /* bytes to skip */ int dump_length; /* max bytes to read */ smallint dump_vflag; /*enum dump_vflag_t*/ - const char *eofstring; FS *fshead; + const char *xxd_eofstring; + long long xxd_displayoff; } dumper_t; dumper_t* alloc_dumper(void) FAST_FUNC; -- cgit v1.2.3-55-g6feb From 2c436679fbb5fa38b0e7a505022a2075fab87d84 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 18 Jun 2021 00:59:17 +0200 Subject: xxd: implement -i "C style output" function old new delta xxd_main 710 888 +178 .rodata 103252 103331 +79 print_C_style - 78 +78 packed_usage 33639 33652 +13 next 276 278 +2 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 4/0 up/down: 350/0) Total: 350 bytes Signed-off-by: Denys Vlasenko --- include/dump.h | 1 + libbb/dump.c | 29 ++++++++++++++-------------- util-linux/hexdump_xxd.c | 49 +++++++++++++++++++++++++++++++++++++----------- 3 files changed, 53 insertions(+), 26 deletions(-) (limited to 'include') diff --git a/include/dump.h b/include/dump.h index 54f5629a7..10fc5d900 100644 --- a/include/dump.h +++ b/include/dump.h @@ -34,6 +34,7 @@ typedef struct dumper_t { smallint dump_vflag; /*enum dump_vflag_t*/ FS *fshead; const char *xxd_eofstring; + off_t address; /* address/offset in stream */ long long xxd_displayoff; } dumper_t; diff --git a/libbb/dump.c b/libbb/dump.c index 9c16f1f94..f8bb6fd03 100644 --- a/libbb/dump.c +++ b/libbb/dump.c @@ -34,7 +34,6 @@ typedef struct priv_dumper_t { FU *endfu; off_t savaddress; /* saved address/offset in stream */ off_t eaddress; /* end address */ - off_t address; /* address/offset in stream */ int blocksize; smallint exitval; /* final exit value */ @@ -335,14 +334,14 @@ static void do_skip(priv_dumper_t *dumper, const char *fname) ) { /* If st_size is valid and pub.dump_skip >= st_size */ dumper->pub.dump_skip -= sbuf.st_size; - dumper->address += sbuf.st_size; + dumper->pub.address += sbuf.st_size; return; } if (fseeko(stdin, dumper->pub.dump_skip, SEEK_SET)) { bb_simple_perror_msg_and_die(fname); } - dumper->address += dumper->pub.dump_skip; - dumper->savaddress = dumper->address; + dumper->pub.address += dumper->pub.dump_skip; + dumper->savaddress = dumper->pub.address; dumper->pub.dump_skip = 0; } @@ -381,7 +380,7 @@ static unsigned char *get(priv_dumper_t *dumper) int blocksize = dumper->blocksize; if (!dumper->get__curp) { - dumper->address = (off_t)0; /*DBU:[dave@cray.com] initialize,initialize..*/ + dumper->pub.address = (off_t)0; /*DBU:[dave@cray.com] initialize,initialize..*/ dumper->get__curp = xmalloc(blocksize); dumper->get__savp = xzalloc(blocksize); /* need to be initialized */ } else { @@ -389,7 +388,7 @@ static unsigned char *get(priv_dumper_t *dumper) dumper->get__curp = dumper->get__savp; dumper->get__savp = tmp; dumper->savaddress += blocksize; - dumper->address = dumper->savaddress; + dumper->pub.address = dumper->savaddress; } need = blocksize; nread = 0; @@ -412,7 +411,7 @@ static unsigned char *get(priv_dumper_t *dumper) } } memset(dumper->get__curp + nread, 0, need); - dumper->eaddress = dumper->address + nread; + dumper->eaddress = dumper->pub.address + nread; return dumper->get__curp; } n = fread(dumper->get__curp + nread, sizeof(unsigned char), @@ -444,7 +443,7 @@ static unsigned char *get(priv_dumper_t *dumper) } dumper->pub.dump_vflag = DUP; dumper->savaddress += blocksize; - dumper->address = dumper->savaddress; + dumper->pub.address = dumper->savaddress; need = blocksize; nread = 0; } else { @@ -545,8 +544,8 @@ static void display(priv_dumper_t* dumper) fs = dumper->pub.fshead; savebp = bp; - saveaddress = dumper->address; - for (; fs; fs = fs->nextfs, bp = savebp, dumper->address = saveaddress) { + saveaddress = dumper->pub.address; + for (; fs; fs = fs->nextfs, bp = savebp, dumper->pub.address = saveaddress) { FU *fu; for (fu = fs->nextfu; fu; fu = fu->nextfu) { int cnt; @@ -555,10 +554,10 @@ static void display(priv_dumper_t* dumper) } for (cnt = fu->reps; cnt; --cnt) { PR *pr; - for (pr = fu->nextpr; pr; dumper->address += pr->bcnt, + for (pr = fu->nextpr; pr; dumper->pub.address += pr->bcnt, bp += pr->bcnt, pr = pr->nextpr) { if (dumper->eaddress - && dumper->address >= dumper->eaddress + && dumper->pub.address >= dumper->eaddress ) { if (dumper->pub.xxd_eofstring) { /* xxd support: requested to not pad incomplete blocks */ @@ -574,7 +573,7 @@ static void display(priv_dumper_t* dumper) } switch (pr->flags) { case F_ADDRESS: - printf(pr->fmt, (unsigned long long) dumper->address + dumper->pub.xxd_displayoff); + printf(pr->fmt, (unsigned long long) dumper->pub.address + dumper->pub.xxd_displayoff); break; case F_BPAD: printf(pr->fmt, ""); @@ -668,10 +667,10 @@ static void display(priv_dumper_t* dumper) * of blocksize, and no partial block ever found. */ if (!dumper->eaddress) { - if (!dumper->address) { + if (!dumper->pub.address) { return; } - dumper->eaddress = dumper->address; + dumper->eaddress = dumper->pub.address; } for (pr = dumper->endfu->nextpr; pr; pr = pr->nextpr) { switch (pr->flags) { diff --git a/util-linux/hexdump_xxd.c b/util-linux/hexdump_xxd.c index 817250c69..aa215569f 100644 --- a/util-linux/hexdump_xxd.c +++ b/util-linux/hexdump_xxd.c @@ -41,12 +41,13 @@ // -u use upper case hex letters. //usage:#define xxd_trivial_usage -//usage: "[-pr] [-g N] [-c N] [-n LEN] [-s OFS] [-o OFS] [FILE]" +//usage: "[-pri] [-g N] [-c N] [-n LEN] [-s OFS] [-o OFS] [FILE]" //usage:#define xxd_full_usage "\n\n" //usage: "Hex dump FILE (or stdin)\n" //usage: "\n -g N Bytes per group" //usage: "\n -c N Bytes per line" //usage: "\n -p Show only hex bytes, assumes -c30" +//usage: "\n -i C include file style" // exactly the same help text lines in hexdump and xxd: //usage: "\n -l LENGTH Show only first LENGTH bytes" //usage: "\n -s OFFSET Skip OFFSET bytes" @@ -62,10 +63,11 @@ #define OPT_s (1 << 1) #define OPT_a (1 << 2) #define OPT_p (1 << 3) -#define OPT_r (1 << 4) -#define OPT_g (1 << 5) -#define OPT_c (1 << 6) -#define OPT_o (1 << 7) +#define OPT_i (1 << 4) +#define OPT_r (1 << 5) +#define OPT_g (1 << 6) +#define OPT_c (1 << 7) +#define OPT_o (1 << 8) static void reverse(unsigned opt, unsigned cols, const char *filename) { @@ -126,6 +128,15 @@ static void reverse(unsigned opt, unsigned cols, const char *filename) fflush_stdout_and_exit(EXIT_SUCCESS); } +static void print_C_style(const char *p, const char *hdr) +{ + printf(hdr, isdigit(p[0]) ? "__" : ""); + while (*p) { + bb_putchar(isalnum(*p) ? *p : '_'); + p++; + } +} + int xxd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int xxd_main(int argc UNUSED_PARAM, char **argv) { @@ -135,10 +146,11 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) unsigned bytes = 2; unsigned cols = 0; unsigned opt; + int r; dumper = alloc_dumper(); - opt = getopt32(argv, "^" "l:s:aprg:+c:+o:" "\0" "?1" /* 1 argument max */, + opt = getopt32(argv, "^" "l:s:apirg:+c:+o:" "\0" "?1" /* 1 argument max */, &opt_l, &opt_s, &bytes, &cols, &opt_o ); argv += optind; @@ -173,8 +185,11 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) bytes = cols; /* -p ignores -gN */ } else { if (cols == 0) - cols = 16; - bb_dump_add(dumper, "\"%08.8_ax: \""); // "address: " + cols = (opt & OPT_i) ? 12 : 16; + if (opt & OPT_i) + bytes = 1; /* -i ignores -gN */ + else + bb_dump_add(dumper, "\"%08.8_ax: \""); // "address: " } if (opt & OPT_r) { @@ -186,7 +201,10 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) bb_dump_add(dumper, buf); } else if (bytes == 1) { - sprintf(buf, "%u/1 \"%%02x \"", cols); // cols * "xx " + if (opt & OPT_i) + sprintf(buf, "%u/1 \" 0x%%02x,\"", cols); // cols * " 0xxx," + else + sprintf(buf, "%u/1 \"%%02x \"", cols); // cols * "xx " bb_dump_add(dumper, buf); } else { @@ -210,7 +228,7 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) free(bigbuf); } - if (!(opt & OPT_p)) { + if (!(opt & (OPT_p|OPT_i))) { sprintf(buf, "\" \"%u/1 \"%%_p\"\"\n\"", cols); // " ASCII\n" bb_dump_add(dumper, buf); } else { @@ -218,5 +236,14 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) dumper->xxd_eofstring = "\n"; } - return bb_dump_dump(dumper, argv); + if ((opt & OPT_i) && argv[0]) { + print_C_style(argv[0], "unsigned char %s"); + printf("[] = {\n"); + } + r = bb_dump_dump(dumper, argv); + if (r == 0 && (opt & OPT_i) && argv[0]) { + print_C_style(argv[0], "};\nunsigned int %s"); + printf("_len = %"OFF_FMT"u;\n", dumper->address); + } + return r; } -- cgit v1.2.3-55-g6feb From dc30f3dce27bdcccb8450a2418061b4bcdc0ea14 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 18 Jun 2021 12:08:02 +0200 Subject: free: implement -h function old new delta .rodata 103331 103363 +32 packed_usage 33652 33654 +2 free_main 657 588 -69 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 34/-69) Total: -35 bytes Signed-off-by: Denys Vlasenko --- include/libbb.h | 4 +-- procps/free.c | 80 ++++++++++++++++++++++++++++++++++++--------------------- 2 files changed, 53 insertions(+), 31 deletions(-) (limited to 'include') diff --git a/include/libbb.h b/include/libbb.h index a3f76a206..9a95a176d 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1065,10 +1065,10 @@ char *smart_ulltoa5(unsigned long long ul, char buf[5], const char *scale) FAST_ /* If block_size == 0, display size without fractional part, * else display (size * block_size) with one decimal digit. * If display_unit == 0, show value no bigger than 1024 with suffix (K,M,G...), - * else divide by display_unit and do not use suffix. */ + * else divide by display_unit and do not use suffix. + * Returns "auto pointer" */ #define HUMAN_READABLE_MAX_WIDTH 7 /* "1024.0G" */ #define HUMAN_READABLE_MAX_WIDTH_STR "7" -//TODO: provide pointer to buf (avoid statics)? const char *make_human_readable_str(unsigned long long size, unsigned long block_size, unsigned long display_unit) FAST_FUNC; /* Put a string of hex bytes ("1b2e66fe"...), return advanced pointer */ diff --git a/procps/free.c b/procps/free.c index 568362913..0b68e1b88 100644 --- a/procps/free.c +++ b/procps/free.c @@ -19,9 +19,9 @@ //kbuild:lib-$(CONFIG_FREE) += free.o //usage:#define free_trivial_usage -//usage: "" IF_DESKTOP("[-bkmg]") +//usage: "" IF_DESKTOP("[-bkmgh]") //usage:#define free_full_usage "\n\n" -//usage: "Display the amount of free and used system memory" +//usage: "Display free and used memory" //usage: //usage:#define free_example_usage //usage: "$ free\n" @@ -29,6 +29,27 @@ //usage: " Mem: 257628 248724 8904 59644 93124\n" //usage: " Swap: 128516 8404 120112\n" //usage: "Total: 386144 257128 129016\n" +//procps-ng 3.3.15: +// -b, --bytes show output in bytes +// --kilo show output in kilobytes +// --mega show output in megabytes +// --giga show output in gigabytes +// --tera show output in terabytes +// --peta show output in petabytes +// -k, --kibi show output in kibibytes +// -m, --mebi show output in mebibytes +// -g, --gibi show output in gibibytes +// --tebi show output in tebibytes +// --pebi show output in pebibytes +// -h, --human show human-readable output +// --si use powers of 1000 not 1024 +// -l, --lohi show detailed low and high memory statistics +// -t, --total show total for RAM + swap +// -s N, --seconds N repeat printing every N seconds +// -c N, --count N repeat printing N times, then exit +// -w, --wide wide output +// +//NB: if we implement -s or -c, need to stop being NOFORK! #include "libbb.h" #ifdef __linux__ @@ -38,18 +59,22 @@ struct globals { unsigned mem_unit; #if ENABLE_DESKTOP - uint8_t unit_steps; -# define G_unit_steps g->unit_steps + unsigned unit; +# define G_unit g->unit #else -# define G_unit_steps 10 +# define G_unit (1 << 10) #endif unsigned long cached_kb, available_kb, reclaimable_kb; }; /* Because of NOFORK, "globals" are not in global data */ -static unsigned long long scale(struct globals *g, unsigned long d) +static const char *scale(struct globals *g, unsigned long d) { - return ((unsigned long long)d * g->mem_unit) >> G_unit_steps; + /* Display (size * block_size) with one decimal digit. + * If display_unit == 0, show value no bigger than 1024 with suffix (K,M,G...), + * else divide by display_unit and do not use suffix. + * Returns "auto pointer" */ + return make_human_readable_str(d, g->mem_unit, G_unit); } /* NOINLINE reduces main() stack usage, which makes code smaller (on x86 at least) */ @@ -88,20 +113,27 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) int seen_available; #if ENABLE_DESKTOP - G.unit_steps = 10; + G.unit = 1 << 10; if (argv[1] && argv[1][0] == '-') { switch (argv[1][1]) { case 'b': - G.unit_steps = 0; + G.unit = 1; break; case 'k': /* 2^10 */ - /* G.unit_steps = 10; - already is */ + /* G.unit = 1 << 10; - already is */ break; case 'm': /* 2^20 */ - G.unit_steps = 20; + G.unit = 1 << 20; break; case 'g': /* 2^30 */ - G.unit_steps = 30; + G.unit = 1 << 30; + break; +// case 't': +// -- WRONG, -t is not "terabytes" in procps-ng, it's --total +// G.unit = 1 << 40; +// break; + case 'h': + G.unit = 0; /* human readable */ break; default: bb_show_usage(); @@ -126,23 +158,13 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) cached += ((unsigned long long) G.reclaimable_kb * 1024) / G.mem_unit; cached_plus_free = cached + info.freeram; -/* In case (long long * G.mem_unit) can overflow, this can be used to reduce the chances */ -#if 0 //ENABLE_DESKTOP - while (!(G.mem_unit & 1) && G.unit_steps != 0) { - G.mem_unit >>= 1; - G.unit_steps--; - //bb_error_msg("mem_unit:%d unit_steps:%d", G.mem_unit, G.unit_steps); - } -#endif - -#define FIELDS_6 "%12llu %11llu %11llu %11llu %11llu %11llu\n" -#define FIELDS_3 (FIELDS_6 + 6 + 7 + 7) -#define FIELDS_2 (FIELDS_6 + 6 + 7 + 7 + 7) - - printf(FIELDS_6, + printf("%12s%12s%12s", scale(&G, info.totalram), //total scale(&G, info.totalram - cached_plus_free), //used - scale(&G, info.freeram), //free + scale(&G, info.freeram) //free + ); + /* using two printf's: only 4 auto strings are supported, we need 6 */ + printf("%12s%12s%12s\n", scale(&G, info.sharedram), //shared scale(&G, cached), //buff/cache scale(&G, available) //available @@ -152,14 +174,14 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) * buffer cache as free memory. */ if (!seen_available) { printf("-/+ buffers/cache: "); - printf(FIELDS_2, + printf("%12s%12s%12s\n" + 4, scale(&G, info.totalram - cached_plus_free), //used scale(&G, cached_plus_free) //free ); } #if BB_MMU printf("Swap: "); - printf(FIELDS_3, + printf("%12s%12s%12s\n", scale(&G, info.totalswap), //total scale(&G, info.totalswap - info.freeswap), //used scale(&G, info.freeswap) //free -- cgit v1.2.3-55-g6feb From 526b8347906a18d756386092fafa0b42ba0b4563 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 20 Jun 2021 10:57:24 +0200 Subject: lsattr,chattr: support -p function old new delta fgetsetprojid - 107 +107 list_attributes 169 222 +53 change_attributes 277 326 +49 chattr_main 272 307 +35 close_silently - 22 +22 .rodata 103378 103393 +15 packed_usage 33658 33666 +8 fgetsetversion 88 74 -14 fgetsetflags 162 148 -14 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 5/2 up/down: 289/-28) Total: 261 bytes Signed-off-by: Denys Vlasenko --- e2fsprogs/chattr.c | 28 ++++++++++++++++++++-------- e2fsprogs/e2fs_lib.c | 34 ++++++++++++++++++++++++++++++---- e2fsprogs/e2fs_lib.h | 5 +++++ e2fsprogs/lsattr.c | 32 +++++++++++++++++++++----------- include/bb_e2fs_defs.h | 12 ++++++++++++ 5 files changed, 88 insertions(+), 23 deletions(-) (limited to 'include') diff --git a/e2fsprogs/chattr.c b/e2fsprogs/chattr.c index 1d267f7a4..5a7545e09 100644 --- a/e2fsprogs/chattr.c +++ b/e2fsprogs/chattr.c @@ -20,12 +20,12 @@ //kbuild:lib-$(CONFIG_CHATTR) += chattr.o e2fs_lib.o //usage:#define chattr_trivial_usage -//usage: "[-R] [-v VERSION] [-+=AacDdijsStTu] FILE..." +//usage: "[-R] [-v VERSION] [-p PROJID] [-+=AacDdijsStTu] FILE..." //usage:#define chattr_full_usage "\n\n" //usage: "Change ext2 file attributes\n" //usage: "\n -R Recurse" -//TODD? "\n -p NUM Set project number" //usage: "\n -v NUM Set version/generation number" +//usage: "\n -p NUM Set project number" //-V, -f accepted but ignored //usage: "\nModifiers:" //usage: "\n -,+,= Remove/add/set attributes" @@ -45,16 +45,18 @@ #include "libbb.h" #include "e2fs_lib.h" -#define OPT_ADD 1 -#define OPT_REM 2 -#define OPT_SET 4 -#define OPT_SET_VER 8 +#define OPT_ADD (1 << 0) +#define OPT_REM (1 << 1) +#define OPT_SET (1 << 2) +#define OPT_SET_VER (1 << 3) +#define OPT_SET_PROJ (1 << 4) struct globals { unsigned long version; unsigned long af; unsigned long rf; int flags; + uint32_t projid; smallint recursive; }; @@ -108,7 +110,13 @@ static char** decode_arg(char **argv, struct globals *gp) gp->flags |= OPT_SET_VER; continue; } -//TODO: "-p PROJECT_NUM" ? + if (*arg == 'p') { + if (!*++argv) + bb_show_usage(); + gp->projid = xatou32(*argv); + gp->flags |= OPT_SET_PROJ; + continue; + } /* not a known option, try as an attribute */ } *fl |= get_flag(*arg); @@ -151,7 +159,11 @@ static void change_attributes(const char *name, struct globals *gp) if (gp->flags & OPT_SET_VER) if (fsetversion(name, gp->version) != 0) - bb_perror_msg("setting version on %s", name); + bb_perror_msg("setting %s on %s", "version", name); + + if (gp->flags & OPT_SET_PROJ) + if (fsetprojid(name, gp->projid) != 0) + bb_perror_msg("setting %s on %s", "project ID", name); if (gp->flags & OPT_SET) { fsflags = gp->af; diff --git a/e2fsprogs/e2fs_lib.c b/e2fsprogs/e2fs_lib.c index 8bd4da622..bc9aa53e5 100644 --- a/e2fsprogs/e2fs_lib.c +++ b/e2fsprogs/e2fs_lib.c @@ -51,14 +51,14 @@ int fgetsetversion(const char *name, unsigned long *get_version, unsigned long s { #if HAVE_EXT2_IOCTLS int fd, r; - IF_LONG_IS_WIDER(int ver;) + IF_LONG_IS_WIDER(unsigned ver;) fd = open(name, O_RDONLY | O_NONBLOCK); if (fd == -1) return -1; if (!get_version) { IF_LONG_IS_WIDER( - ver = (int) set_version; + ver = (unsigned) set_version; r = ioctl(fd, EXT2_IOC_SETVERSION, &ver); ) IF_LONG_IS_SAME( @@ -81,6 +81,32 @@ int fgetsetversion(const char *name, unsigned long *get_version, unsigned long s #endif /* ! HAVE_EXT2_IOCTLS */ } +int fgetsetprojid(const char *name, uint32_t *get, uint32_t set) +{ +#if HAVE_EXT2_IOCTLS + struct ext2_fsxattr fsxattr; + int fd, r; + + fd = open(name, O_RDONLY | O_NONBLOCK); + if (fd == -1) + return -1; + r = ioctl(fd, EXT2_IOC_FSGETXATTR, &fsxattr); + /* note: ^^^ may fail in 32-bit userspace on 64-bit kernel (seen on 4.12.0) */ + if (r == 0) { + if (get) { + *get = fsxattr.fsx_projid; + } else { + fsxattr.fsx_projid = set; + r = ioctl(fd, EXT2_IOC_FSSETXATTR, &fsxattr); + } + } + close_silently(fd); + return r; +#else /* ! HAVE_EXT2_IOCTLS */ + errno = EOPNOTSUPP; + return -1; +#endif /* ! HAVE_EXT2_IOCTLS */ +} /* Get/set a file flags on an ext2 file system */ int fgetsetflags(const char *name, unsigned long *get_flags, unsigned long set_flags) @@ -88,7 +114,7 @@ int fgetsetflags(const char *name, unsigned long *get_flags, unsigned long set_f #if HAVE_EXT2_IOCTLS struct stat buf; int fd, r; - IF_LONG_IS_WIDER(int f;) + IF_LONG_IS_WIDER(unsigned f;) if (stat(name, &buf) == 0 /* stat is ok */ && !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode) @@ -101,7 +127,7 @@ int fgetsetflags(const char *name, unsigned long *get_flags, unsigned long set_f if (!get_flags) { IF_LONG_IS_WIDER( - f = (int) set_flags; + f = (unsigned) set_flags; r = ioctl(fd, EXT2_IOC_SETFLAGS, &f); ) IF_LONG_IS_SAME( diff --git a/e2fsprogs/e2fs_lib.h b/e2fsprogs/e2fs_lib.h index ae28c353b..82a1581cb 100644 --- a/e2fsprogs/e2fs_lib.h +++ b/e2fsprogs/e2fs_lib.h @@ -21,6 +21,11 @@ int fgetsetversion(const char *name, unsigned long *get_version, unsigned long s #define fgetversion(name, version) fgetsetversion(name, version, 0) #define fsetversion(name, version) fgetsetversion(name, NULL, version) +/* Get/set a file project ID on an ext2 file system */ +int fgetsetprojid(const char *name, uint32_t *get, uint32_t set); +#define fgetprojid(name, projid) fgetsetprojid(name, projid, 0) +#define fsetprojid(name, projid) fgetsetprojid(name, NULL, projid) + /* Get/set a file flags on an ext2 file system */ int fgetsetflags(const char *name, unsigned long *get_flags, unsigned long set_flags); #define fgetflags(name, flags) fgetsetflags(name, flags, 0) diff --git a/e2fsprogs/lsattr.c b/e2fsprogs/lsattr.c index 91205ff65..9b035f584 100644 --- a/e2fsprogs/lsattr.c +++ b/e2fsprogs/lsattr.c @@ -21,38 +21,48 @@ //kbuild:lib-$(CONFIG_LSATTR) += lsattr.o e2fs_lib.o //usage:#define lsattr_trivial_usage -//usage: "[-Radlv] [FILE]..." +//usage: "[-Radlpv] [FILE]..." //usage:#define lsattr_full_usage "\n\n" //usage: "List ext2 file attributes\n" //usage: "\n -R Recurse" -//usage: "\n -a Don't hide entries starting with ." -//usage: "\n -d List directory entries instead of contents" +//usage: "\n -a Include names starting with ." +//usage: "\n -d List directory names, not contents" +// -a,-d text should match ls --help //usage: "\n -l List long flag names" +//usage: "\n -p List project ID" //usage: "\n -v List version/generation number" #include "libbb.h" #include "e2fs_lib.h" enum { - OPT_RECUR = 0x1, - OPT_ALL = 0x2, - OPT_DIRS_OPT = 0x4, - OPT_PF_LONG = 0x8, - OPT_GENERATION = 0x10, + OPT_RECUR = 1 << 0, + OPT_ALL = 1 << 1, + OPT_DIRS_OPT = 1 << 2, + OPT_PF_LONG = 1 << 3, + OPT_GENERATION = 1 << 4, + OPT_PROJID = 1 << 5, }; static void list_attributes(const char *name) { unsigned long fsflags; - unsigned long generation; if (fgetflags(name, &fsflags) != 0) goto read_err; + if (option_mask32 & OPT_PROJID) { + uint32_t p; + if (fgetprojid(name, &p) != 0) + goto read_err; + printf("%5lu ", (unsigned long)p); + } + if (option_mask32 & OPT_GENERATION) { + unsigned long generation; if (fgetversion(name, &generation) != 0) goto read_err; - printf("%5lu ", generation); + printf("%-10lu ", generation); } if (option_mask32 & OPT_PF_LONG) { @@ -111,7 +121,7 @@ static void lsattr_args(const char *name) int lsattr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int lsattr_main(int argc UNUSED_PARAM, char **argv) { - getopt32(argv, "Radlv"); + getopt32(argv, "Radlvp"); argv += optind; if (!*argv) diff --git a/include/bb_e2fs_defs.h b/include/bb_e2fs_defs.h index 3f5e3c45b..2d72288ed 100644 --- a/include/bb_e2fs_defs.h +++ b/include/bb_e2fs_defs.h @@ -195,6 +195,18 @@ struct ext2_dx_countlimit { #define EXT2_IOC_SETFLAGS _IOW('f', 2, long) #define EXT2_IOC_GETVERSION _IOR('v', 1, long) #define EXT2_IOC_SETVERSION _IOW('v', 2, long) +//NB: despite "long" in defs above, these ioctls use an _int_! +//passing them a pointer to long will read/write only int-sized data! +struct ext2_fsxattr { + uint32_t fsx_xflags; /* xflags field value (get/set) */ + uint32_t fsx_extsize; /* extsize field value (get/set)*/ + uint32_t fsx_nextents; /* nextents field value (get) */ + uint32_t fsx_projid; /* project identifier (get/set) */ + uint32_t fsx_cowextsize; /* CoW extsize field value (get/set)*/ + unsigned char fsx_pad[8]; +}; +#define EXT2_IOC_FSGETXATTR _IOR('X', 31, struct ext2_fsxattr) +#define EXT2_IOC_FSSETXATTR _IOW('X', 32, struct ext2_fsxattr) /* * Structure of an inode on the disk -- cgit v1.2.3-55-g6feb From 83dff7f43154cd41e4d2e5831060a2d2ddc6596e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 20 Jun 2021 12:34:05 +0200 Subject: lsattr: support more ext2 flags function old new delta e2attr_flags_lname 214 285 +71 e2attr_flags_value 52 80 +28 e2attr_flags_sname 14 21 +7 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/0 up/down: 106/0) Total: 106 bytes Signed-off-by: Denys Vlasenko --- e2fsprogs/e2fs_lib.c | 27 +++++++++++++++++++-------- include/bb_e2fs_defs.h | 11 ++++++----- 2 files changed, 25 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/e2fsprogs/e2fs_lib.c b/e2fsprogs/e2fs_lib.c index bc9aa53e5..8d56add2d 100644 --- a/e2fsprogs/e2fs_lib.c +++ b/e2fsprogs/e2fs_lib.c @@ -158,9 +158,7 @@ const uint32_t e2attr_flags_value[] ALIGN4 = { EXT2_COMPRBLK_FL, EXT2_DIRTY_FL, EXT2_NOCOMPR_FL, - EXT2_ECOMPR_FL, #endif - EXT2_INDEX_FL, EXT2_SECRM_FL, EXT2_UNRM_FL, EXT2_SYNC_FL, @@ -170,26 +168,31 @@ const uint32_t e2attr_flags_value[] ALIGN4 = { EXT2_NODUMP_FL, EXT2_NOATIME_FL, EXT2_COMPR_FL, + EXT2_ECOMPR_FL, EXT3_JOURNAL_DATA_FL, + EXT2_INDEX_FL, EXT2_NOTAIL_FL, - EXT2_TOPDIR_FL + EXT2_TOPDIR_FL, + EXT2_EXTENT_FL, + EXT2_NOCOW_FL, + EXT2_CASEFOLD_FL, + EXT2_INLINE_DATA_FL, + EXT2_PROJINHERIT_FL, + EXT2_VERITY_FL, }; const char e2attr_flags_sname[] ALIGN1 = #ifdef ENABLE_COMPRESSION - "BZXE" + "BZX" #endif - "I" - "suSDiadAcjtT"; + "suSDiadAcEjItTeCFNPV"; static const char e2attr_flags_lname[] ALIGN1 = #ifdef ENABLE_COMPRESSION "Compressed_File" "\0" "Compressed_Dirty_File" "\0" "Compression_Raw_Access" "\0" - "Compression_Error" "\0" #endif - "Indexed_directory" "\0" "Secure_Deletion" "\0" "Undelete" "\0" "Synchronous_Updates" "\0" @@ -199,9 +202,17 @@ static const char e2attr_flags_lname[] ALIGN1 = "No_Dump" "\0" "No_Atime" "\0" "Compression_Requested" "\0" + "Encrypted" "\0" "Journaled_Data" "\0" + "Indexed_directory" "\0" "No_Tailmerging" "\0" "Top_of_Directory_Hierarchies" "\0" + "Extents" "\0" + "No_COW" "\0" + "Casefold" "\0" + "Inline_Data" "\0" + "Project_Hierarchy" "\0" + "Verity" "\0" /* Another trailing NUL is added by compiler */; void print_e2flags(FILE *f, unsigned long flags, unsigned options) diff --git a/include/bb_e2fs_defs.h b/include/bb_e2fs_defs.h index 2d72288ed..608cbf0b0 100644 --- a/include/bb_e2fs_defs.h +++ b/include/bb_e2fs_defs.h @@ -182,11 +182,12 @@ struct ext2_dx_countlimit { #define EXT2_NOTAIL_FL 0x00008000 /* file tail should not be merged */ #define EXT2_DIRSYNC_FL 0x00010000 /* Synchronous directory modifications */ #define EXT2_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/ -#define EXT3_EXTENTS_FL 0x00080000 /* Inode uses extents */ -#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */ - -#define EXT2_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */ -#define EXT2_FL_USER_MODIFIABLE 0x000080FF /* User modifiable flags */ +#define EXT2_EXTENT_FL 0x00080000 /* Extents */ +#define EXT2_VERITY_FL 0x00100000 +#define EXT2_NOCOW_FL 0x00800000 /* Do not cow file */ +#define EXT2_INLINE_DATA_FL 0x10000000 +#define EXT2_PROJINHERIT_FL 0x20000000 +#define EXT2_CASEFOLD_FL 0x40000000 /* * ioctl commands -- cgit v1.2.3-55-g6feb From 0ec52d438a41be92d2d8e8651242b4d9faf23a6c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 21 Jun 2021 19:35:33 +0200 Subject: cp: implement -t DIR function old new delta packed_usage 33713 33734 +21 .rodata 103670 103672 +2 cp_main 506 500 -6 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 23/-6) Total: 17 bytes Signed-off-by: Denys Vlasenko --- coreutils/cp.c | 130 +++++++++++++++++++++++++++++++------------------------- include/libbb.h | 17 +++++--- 2 files changed, 82 insertions(+), 65 deletions(-) (limited to 'include') diff --git a/coreutils/cp.c b/coreutils/cp.c index ac00e09bf..8b9e03c95 100644 --- a/coreutils/cp.c +++ b/coreutils/cp.c @@ -37,8 +37,55 @@ /* http://www.opengroup.org/onlinepubs/007904975/utilities/cp.html */ +// Options of cp from GNU coreutils 6.10: +// -a, --archive +// -f, --force +// -i, --interactive +// -l, --link +// -L, --dereference +// -P, --no-dereference +// -R, -r, --recursive +// -s, --symbolic-link +// -v, --verbose +// -H follow command-line symbolic links in SOURCE +// -d same as --no-dereference --preserve=links +// -p same as --preserve=mode,ownership,timestamps +// -c same as --preserve=context +// -u, --update +// copy only when the SOURCE file is newer than the destination +// file or when the destination file is missing +// --remove-destination +// remove each existing destination file before attempting to open +// --parents +// use full source file name under DIRECTORY +// -T, --no-target-directory +// treat DEST as a normal file +// NOT SUPPORTED IN BBOX: +// --backup[=CONTROL] +// make a backup of each existing destination file +// -b like --backup but does not accept an argument +// --copy-contents +// copy contents of special files when recursive +// --preserve[=ATTR_LIST] +// preserve attributes (default: mode,ownership,timestamps), +// if possible additional attributes: security context,links,all +// --no-preserve=ATTR_LIST +// --sparse=WHEN +// control creation of sparse files +// --strip-trailing-slashes +// remove any trailing slashes from each SOURCE argument +// -S, --suffix=SUFFIX +// override the usual backup suffix +// -t, --target-directory=DIRECTORY +// copy all SOURCE arguments into DIRECTORY +// -x, --one-file-system +// stay on this file system +// -Z, --context=CONTEXT +// (SELinux) set SELinux security context of copy to CONTEXT + //usage:#define cp_trivial_usage -//usage: "[-arPLHpfilsTu] SOURCE... DEST" +//usage: "[-arPLHpfilsTu] SOURCE DEST\n" +//usage: "or: cp [-arPLHpfilsu] SOURCE... { -t DIRECTORY | DIRECTORY }" //usage:#define cp_full_usage "\n\n" //usage: "Copy SOURCEs to DEST\n" //usage: "\n -a Same as -dpR" @@ -53,7 +100,8 @@ //usage: "\n -f Overwrite" //usage: "\n -i Prompt before overwrite" //usage: "\n -l,-s Create (sym)links" -//usage: "\n -T Treat DEST as a normal file" +//usage: "\n -T Refuse to copy if DEST is a directory" +//usage: "\n -t DIR Copy all SOURCEs into DIR" //usage: "\n -u Copy only newer files" #include "libbb.h" @@ -73,14 +121,12 @@ int cp_main(int argc, char **argv) int flags; int status; enum { - FILEUTILS_CP_OPTNUM = sizeof(FILEUTILS_CP_OPTSTR)-1, #if ENABLE_FEATURE_CP_LONG_OPTIONS /*OPT_rmdest = FILEUTILS_RMDEST = 1 << FILEUTILS_CP_OPTNUM */ OPT_parents = 1 << (FILEUTILS_CP_OPTNUM+1), OPT_reflink = 1 << (FILEUTILS_CP_OPTNUM+2), #endif }; - #if ENABLE_FEATURE_CP_LONG_OPTIONS # if ENABLE_FEATURE_CP_REFLINK char *reflink = NULL; @@ -94,7 +140,8 @@ int cp_main(int argc, char **argv) // -r and -R are the same // -R (and therefore -r) turns on -d (coreutils does this) // -a = -pdR - "-2:l--s:s--l:Pd:rRd:Rd:apdR", + /* At least one argument. (Usually two+, but -t DIR can have only one) */ + "-1:l--s:s--l:Pd:rRd:Rd:apdR", "archive\0" No_argument "a" "force\0" No_argument "f" "interactive\0" No_argument "i" @@ -110,6 +157,9 @@ int cp_main(int argc, char **argv) "parents\0" No_argument "\xfe" # if ENABLE_FEATURE_CP_REFLINK "reflink\0" Optional_argument "\xfd" +# endif + , &last +# if ENABLE_FEATURE_CP_REFLINK , &reflink # endif ); @@ -128,55 +178,10 @@ int cp_main(int argc, char **argv) flags = getopt32(argv, "^" FILEUTILS_CP_OPTSTR "\0" - "-2:l--s:s--l:Pd:rRd:Rd:apdR" + "-1:l--s:s--l:Pd:rRd:Rd:apdR" + , &last ); #endif - /* Options of cp from GNU coreutils 6.10: - * -a, --archive - * -f, --force - * -i, --interactive - * -l, --link - * -L, --dereference - * -P, --no-dereference - * -R, -r, --recursive - * -s, --symbolic-link - * -v, --verbose - * -H follow command-line symbolic links in SOURCE - * -d same as --no-dereference --preserve=links - * -p same as --preserve=mode,ownership,timestamps - * -c same as --preserve=context - * -u, --update - * copy only when the SOURCE file is newer than the destination - * file or when the destination file is missing - * --remove-destination - * remove each existing destination file before attempting to open - * --parents - * use full source file name under DIRECTORY - * -T, --no-target-directory - * treat DEST as a normal file - * NOT SUPPORTED IN BBOX: - * --backup[=CONTROL] - * make a backup of each existing destination file - * -b like --backup but does not accept an argument - * --copy-contents - * copy contents of special files when recursive - * --preserve[=ATTR_LIST] - * preserve attributes (default: mode,ownership,timestamps), - * if possible additional attributes: security context,links,all - * --no-preserve=ATTR_LIST - * --sparse=WHEN - * control creation of sparse files - * --strip-trailing-slashes - * remove any trailing slashes from each SOURCE argument - * -S, --suffix=SUFFIX - * override the usual backup suffix - * -t, --target-directory=DIRECTORY - * copy all SOURCE arguments into DIRECTORY - * -x, --one-file-system - * stay on this file system - * -Z, --context=CONTEXT - * (SELinux) set SELinux security context of copy to CONTEXT - */ argc -= optind; argv += optind; /* Reverse this bit. If there is -d, bit is not set: */ @@ -195,15 +200,22 @@ int cp_main(int argc, char **argv) #endif status = EXIT_SUCCESS; - last = argv[argc - 1]; - /* If there are only two arguments and... */ - if (argc == 2) { + if (!(flags & FILEUTILS_TARGET_DIR)) { + last = argv[argc - 1]; + if (argc < 2) + bb_show_usage(); + if (argc != 2) { + if (flags & FILEUTILS_NO_TARGET_DIR) + bb_show_usage(); + /* "cp A B C... DIR" - target must be dir */ + } else /* argc == 2 */ { + /* "cp A B" - only case where target can be not a dir */ s_flags = cp_mv_stat2(*argv, &source_stat, (flags & FILEUTILS_DEREFERENCE) ? stat : lstat); - if (s_flags < 0) + if (s_flags < 0) /* error other than ENOENT */ return EXIT_FAILURE; d_flags = cp_mv_stat(last, &dest_stat); - if (d_flags < 0) + if (d_flags < 0) /* error other than ENOENT */ return EXIT_FAILURE; if (flags & FILEUTILS_NO_TARGET_DIR) { /* -T */ @@ -235,9 +247,9 @@ int cp_main(int argc, char **argv) dest = last; goto DO_COPY; /* NB: argc==2 -> *++argv==last */ } - } else if (flags & FILEUTILS_NO_TARGET_DIR) { - bb_simple_error_msg_and_die("too many arguments"); + } } + /* else: last is DIR from "t -DIR" */ while (1) { #if ENABLE_FEATURE_CP_LONG_OPTIONS diff --git a/include/libbb.h b/include/libbb.h index 9a95a176d..e38e97ac2 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -460,13 +460,18 @@ enum { /* cp.c, mv.c, install.c depend on these values. CAREFUL when changing th FILEUTILS_VERBOSE = (1 << 12) * ENABLE_FEATURE_VERBOSE, /* -v */ FILEUTILS_UPDATE = 1 << 13, /* -u */ FILEUTILS_NO_TARGET_DIR = 1 << 14, /* -T */ + FILEUTILS_TARGET_DIR = 1 << 15, /* -t DIR */ #if ENABLE_SELINUX - FILEUTILS_PRESERVE_SECURITY_CONTEXT = 1 << 15, /* -c */ + FILEUTILS_PRESERVE_SECURITY_CONTEXT = 1 << 16, /* -c */ #endif - FILEUTILS_RMDEST = 1 << (16 - !ENABLE_SELINUX), /* --remove-destination */ - /* bit 17 skipped for "cp --parents" */ - FILEUTILS_REFLINK = 1 << (18 - !ENABLE_SELINUX), /* cp --reflink=auto */ - FILEUTILS_REFLINK_ALWAYS = 1 << (19 - !ENABLE_SELINUX), /* cp --reflink[=always] */ +#define FILEUTILS_CP_OPTSTR "pdRfilsLHarPvuTt:" IF_SELINUX("c") +/* How many bits in FILEUTILS_CP_OPTSTR? */ + FILEUTILS_CP_OPTNUM = 17 - !ENABLE_SELINUX, + + FILEUTILS_RMDEST = 1 << (17 - !ENABLE_SELINUX), /* --remove-destination */ + /* bit 18 skipped for "cp --parents" */ + FILEUTILS_REFLINK = 1 << (19 - !ENABLE_SELINUX), /* cp --reflink=auto */ + FILEUTILS_REFLINK_ALWAYS = 1 << (20 - !ENABLE_SELINUX), /* cp --reflink[=always] */ /* * Hole. cp may have some bits set here, * they should not affect remove_file()/copy_file() @@ -476,7 +481,7 @@ enum { /* cp.c, mv.c, install.c depend on these values. CAREFUL when changing th #endif FILEUTILS_IGNORE_CHMOD_ERR = 1 << 31, }; -#define FILEUTILS_CP_OPTSTR "pdRfilsLHarPvuT" IF_SELINUX("c") + extern int remove_file(const char *path, int flags) FAST_FUNC; /* NB: without FILEUTILS_RECUR in flags, it will basically "cat" * the source, not copy (unless "source" is a directory). -- cgit v1.2.3-55-g6feb From 56bbbfae7df48f778362d1848d2a4afd2c293d76 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 22 Jun 2021 15:28:34 +0200 Subject: cp: implement -n function old new delta .rodata 103681 103722 +41 packed_usage 33698 33717 +19 copy_file 1678 1696 +18 cp_main 500 492 -8 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/1 up/down: 78/-8) Total: 70 bytes Signed-off-by: Denys Vlasenko --- coreutils/cp.c | 19 +++++++++++-------- include/libbb.h | 29 +++++++++++++++-------------- libbb/copy_file.c | 2 ++ 3 files changed, 28 insertions(+), 22 deletions(-) (limited to 'include') diff --git a/coreutils/cp.c b/coreutils/cp.c index 8b9e03c95..b7f0e290f 100644 --- a/coreutils/cp.c +++ b/coreutils/cp.c @@ -84,8 +84,8 @@ // (SELinux) set SELinux security context of copy to CONTEXT //usage:#define cp_trivial_usage -//usage: "[-arPLHpfilsTu] SOURCE DEST\n" -//usage: "or: cp [-arPLHpfilsu] SOURCE... { -t DIRECTORY | DIRECTORY }" +//usage: "[-arPLHpfinlsTu] SOURCE DEST\n" +//usage: "or: cp [-arPLHpfinlsu] SOURCE... { -t DIRECTORY | DIRECTORY }" //usage:#define cp_full_usage "\n\n" //usage: "Copy SOURCEs to DEST\n" //usage: "\n -a Same as -dpR" @@ -99,6 +99,7 @@ //usage: "\n -p Preserve file attributes if possible" //usage: "\n -f Overwrite" //usage: "\n -i Prompt before overwrite" +//usage: "\n -n Don't overwrite" //usage: "\n -l,-s Create (sym)links" //usage: "\n -T Refuse to copy if DEST is a directory" //usage: "\n -t DIR Copy all SOURCEs into DIR" @@ -122,9 +123,9 @@ int cp_main(int argc, char **argv) int status; enum { #if ENABLE_FEATURE_CP_LONG_OPTIONS - /*OPT_rmdest = FILEUTILS_RMDEST = 1 << FILEUTILS_CP_OPTNUM */ - OPT_parents = 1 << (FILEUTILS_CP_OPTNUM+1), - OPT_reflink = 1 << (FILEUTILS_CP_OPTNUM+2), + /*OPT_rmdest = FILEUTILS_RMDEST = 1 << FILEUTILS_CP_OPTBITS */ + OPT_parents = 1 << (FILEUTILS_CP_OPTBITS+1), + OPT_reflink = 1 << (FILEUTILS_CP_OPTBITS+2), #endif }; #if ENABLE_FEATURE_CP_LONG_OPTIONS @@ -134,23 +135,25 @@ int cp_main(int argc, char **argv) flags = getopt32long(argv, "^" FILEUTILS_CP_OPTSTR "\0" - // Need at least two arguments + // Need at least one argument. (Usually two+, but -t DIR can have only one) // Soft- and hardlinking doesn't mix // -P and -d are the same (-P is POSIX, -d is GNU) // -r and -R are the same // -R (and therefore -r) turns on -d (coreutils does this) // -a = -pdR - /* At least one argument. (Usually two+, but -t DIR can have only one) */ - "-1:l--s:s--l:Pd:rRd:Rd:apdR", + // -i overrides -n and vice versa (last wins) + "-1:l--s:s--l:Pd:rRd:Rd:apdR:i-n:n-i", "archive\0" No_argument "a" "force\0" No_argument "f" "interactive\0" No_argument "i" + "no-clobber\0" No_argument "n" "link\0" No_argument "l" "dereference\0" No_argument "L" "no-dereference\0" No_argument "P" "recursive\0" No_argument "R" "symbolic-link\0" No_argument "s" "no-target-directory\0" No_argument "T" + "target-directory\0" Required_argument "t" "verbose\0" No_argument "v" "update\0" No_argument "u" "remove-destination\0" No_argument "\xff" diff --git a/include/libbb.h b/include/libbb.h index e38e97ac2..251d7231c 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -450,28 +450,29 @@ enum { /* cp.c, mv.c, install.c depend on these values. CAREFUL when changing th FILEUTILS_RECUR = 1 << 2, /* -R */ FILEUTILS_FORCE = 1 << 3, /* -f */ FILEUTILS_INTERACTIVE = 1 << 4, /* -i */ - FILEUTILS_MAKE_HARDLINK = 1 << 5, /* -l */ - FILEUTILS_MAKE_SOFTLINK = 1 << 6, /* -s */ - FILEUTILS_DEREF_SOFTLINK = 1 << 7, /* -L */ - FILEUTILS_DEREFERENCE_L0 = 1 << 8, /* -H */ + FILEUTILS_NO_OVERWRITE = 1 << 5, /* -n */ + FILEUTILS_MAKE_HARDLINK = 1 << 6, /* -l */ + FILEUTILS_MAKE_SOFTLINK = 1 << 7, /* -s */ + FILEUTILS_DEREF_SOFTLINK = 1 << 8, /* -L */ + FILEUTILS_DEREFERENCE_L0 = 1 << 9, /* -H */ /* -a = -pdR (mapped in cp.c) */ /* -r = -dR (mapped in cp.c) */ /* -P = -d (mapped in cp.c) */ - FILEUTILS_VERBOSE = (1 << 12) * ENABLE_FEATURE_VERBOSE, /* -v */ - FILEUTILS_UPDATE = 1 << 13, /* -u */ - FILEUTILS_NO_TARGET_DIR = 1 << 14, /* -T */ - FILEUTILS_TARGET_DIR = 1 << 15, /* -t DIR */ + FILEUTILS_VERBOSE = (1 << 13) * ENABLE_FEATURE_VERBOSE, /* -v */ + FILEUTILS_UPDATE = 1 << 14, /* -u */ + FILEUTILS_NO_TARGET_DIR = 1 << 15, /* -T */ + FILEUTILS_TARGET_DIR = 1 << 16, /* -t DIR */ #if ENABLE_SELINUX - FILEUTILS_PRESERVE_SECURITY_CONTEXT = 1 << 16, /* -c */ + FILEUTILS_PRESERVE_SECURITY_CONTEXT = 1 << 17, /* -c */ #endif -#define FILEUTILS_CP_OPTSTR "pdRfilsLHarPvuTt:" IF_SELINUX("c") +#define FILEUTILS_CP_OPTSTR "pdRfinlsLHarPvuTt:" IF_SELINUX("c") /* How many bits in FILEUTILS_CP_OPTSTR? */ - FILEUTILS_CP_OPTNUM = 17 - !ENABLE_SELINUX, + FILEUTILS_CP_OPTBITS = 18 - !ENABLE_SELINUX, - FILEUTILS_RMDEST = 1 << (17 - !ENABLE_SELINUX), /* --remove-destination */ + FILEUTILS_RMDEST = 1 << (19 - !ENABLE_SELINUX), /* cp --remove-destination */ /* bit 18 skipped for "cp --parents" */ - FILEUTILS_REFLINK = 1 << (19 - !ENABLE_SELINUX), /* cp --reflink=auto */ - FILEUTILS_REFLINK_ALWAYS = 1 << (20 - !ENABLE_SELINUX), /* cp --reflink[=always] */ + FILEUTILS_REFLINK = 1 << (20 - !ENABLE_SELINUX), /* cp --reflink=auto */ + FILEUTILS_REFLINK_ALWAYS = 1 << (21 - !ENABLE_SELINUX), /* cp --reflink[=always] */ /* * Hole. cp may have some bits set here, * they should not affect remove_file()/copy_file() diff --git a/libbb/copy_file.c b/libbb/copy_file.c index 49d1ec9c6..044bc3c20 100644 --- a/libbb/copy_file.c +++ b/libbb/copy_file.c @@ -111,6 +111,8 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags) bb_error_msg("'%s' and '%s' are the same file", source, dest); return -1; } + if (flags & FILEUTILS_NO_OVERWRITE) /* cp -n */ + return 0; dest_exists = 1; } -- cgit v1.2.3-55-g6feb From 1746218beebc7e180f3eaed905277f9f46983ac4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 24 Jun 2021 11:42:55 +0200 Subject: move iterate_on_dir() from e2fsprogs to libbb Signed-off-by: Denys Vlasenko --- e2fsprogs/e2fs_lib.c | 27 --------------------------- e2fsprogs/e2fs_lib.h | 5 ----- include/libbb.h | 5 +++++ libbb/iterate_on_dir.c | 28 ++++++++++++++++++++++++++++ 4 files changed, 33 insertions(+), 32 deletions(-) create mode 100644 libbb/iterate_on_dir.c (limited to 'include') diff --git a/e2fsprogs/e2fs_lib.c b/e2fsprogs/e2fs_lib.c index e32336ae6..9b68d8901 100644 --- a/e2fsprogs/e2fs_lib.c +++ b/e2fsprogs/e2fs_lib.c @@ -8,33 +8,6 @@ #include "libbb.h" #include "e2fs_lib.h" -#if INT_MAX == LONG_MAX -#define IF_LONG_IS_SAME(...) __VA_ARGS__ -#define IF_LONG_IS_WIDER(...) -#else -#define IF_LONG_IS_SAME(...) -#define IF_LONG_IS_WIDER(...) __VA_ARGS__ -#endif - -/* Iterate a function on each entry of a directory */ -int iterate_on_dir(const char *dir_name, - int FAST_FUNC (*func)(const char *, struct dirent *, void *), - void *private) -{ - DIR *dir; - struct dirent *de; - - dir = opendir(dir_name); - if (dir == NULL) { - return -1; - } - while ((de = readdir(dir)) != NULL) { - func(dir_name, de, private); - } - closedir(dir); - return 0; -} - /* Print file attributes on an ext2 file system */ const uint32_t e2attr_flags_value[] ALIGN4 = { #ifdef ENABLE_COMPRESSION diff --git a/e2fsprogs/e2fs_lib.h b/e2fsprogs/e2fs_lib.h index 879272f44..bab447a94 100644 --- a/e2fsprogs/e2fs_lib.h +++ b/e2fsprogs/e2fs_lib.h @@ -11,11 +11,6 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN -/* Iterate a function on each entry of a directory */ -int iterate_on_dir(const char *dir_name, - int FAST_FUNC (*func)(const char *, struct dirent *, void *), - void *private); - /* Print file attributes on an ext2 file system */ void print_e2flags_long(unsigned flags); void print_e2flags(unsigned flags); diff --git a/include/libbb.h b/include/libbb.h index 251d7231c..7d6ab4a93 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -512,6 +512,11 @@ int recursive_action(const char *fileName, unsigned flags, void *userData ) FAST_FUNC; +/* Simpler version: call a function on each dirent in a directory */ +int iterate_on_dir(const char *dir_name, + int FAST_FUNC (*func)(const char *, struct dirent *, void *), + void *private) FAST_FUNC; + extern int device_open(const char *device, int mode) FAST_FUNC; enum { GETPTY_BUFSIZE = 16 }; /* more than enough for "/dev/ttyXXX" */ extern int xgetpty(char *line) FAST_FUNC; diff --git a/libbb/iterate_on_dir.c b/libbb/iterate_on_dir.c new file mode 100644 index 000000000..deef72ebf --- /dev/null +++ b/libbb/iterate_on_dir.c @@ -0,0 +1,28 @@ +/* vi: set sw=4 ts=4: */ +/* + * See README for additional information + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ +//kbuild:lib-y += iterate_on_dir.o + +#include "libbb.h" + +/* Iterate a function on each entry of a directory */ +int FAST_FUNC iterate_on_dir(const char *dir_name, + int FAST_FUNC (*func)(const char *, struct dirent *, void *), + void *private) +{ + DIR *dir; + struct dirent *de; + + dir = opendir(dir_name); + if (dir == NULL) { + return -1; + } + while ((de = readdir(dir)) != NULL) { + func(dir_name, de, private); + } + closedir(dir); + return 0; +} -- cgit v1.2.3-55-g6feb