diff --git a/coreutils/Config.src b/coreutils/Config.src index 1ec3a0a99..02155d220 100644 --- a/coreutils/Config.src +++ b/coreutils/Config.src @@ -571,12 +571,6 @@ config SUM help checksum and count the blocks in a file -config SYNC - bool "sync" - default y - help - sync is used to flush filesystem buffers. - config TAC bool "tac" default y diff --git a/coreutils/Kbuild.src b/coreutils/Kbuild.src index ec4ef7df2..4ec075ac6 100644 --- a/coreutils/Kbuild.src +++ b/coreutils/Kbuild.src @@ -68,7 +68,6 @@ lib-$(CONFIG_SORT) += sort.o lib-$(CONFIG_STAT) += stat.o lib-$(CONFIG_STTY) += stty.o lib-$(CONFIG_SUM) += sum.o -lib-$(CONFIG_SYNC) += sync.o lib-$(CONFIG_TAC) += tac.o lib-$(CONFIG_TEE) += tee.o lib-$(CONFIG_TRUE) += true.o diff --git a/coreutils/sync.c b/coreutils/sync.c index 7d98a1e30..974e90452 100644 --- a/coreutils/sync.c +++ b/coreutils/sync.c @@ -3,16 +3,39 @@ * Mini sync implementation for busybox * * Copyright (C) 1995, 1996 by Bruce Perens . + * Copyright (C) 2015 by Ari Sundholm * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ /* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */ +//config:config SYNC +//config: bool "sync" +//config: default y +//config: help +//config: sync is used to flush filesystem buffers. +//config:config FEATURE_SYNC_FANCY +//config: bool "Enable -d and -f flags (requres syncfs(2) in libc)" +//config: default y +//config: depends on SYNC +//config: help +//config: sync -d FILE... executes fdatasync() on each FILE. +//config: sync -f FILE... executes syncfs() on each FILE. + +//kbuild:lib-$(CONFIG_SYNC) += sync.o +//applet:IF_SYNC(APPLET_NOFORK(sync, sync, BB_DIR_BIN, BB_SUID_DROP, sync)) //usage:#define sync_trivial_usage -//usage: "" +//usage: ""IF_FEATURE_SYNC_FANCY("[-df] [FILE]...") //usage:#define sync_full_usage "\n\n" +//usage: IF_NOT_FEATURE_SYNC_FANCY( //usage: "Write all buffered blocks to disk" +//usage: ) +//usage: IF_FEATURE_SYNC_FANCY( +//usage: "Write all buffered blocks (in FILEs) to disk" +//usage: "\n -d Avoid syncing metadata" +//usage: "\n -f Sync filesystems underlying FILEs" +//usage: ) #include "libbb.h" @@ -21,10 +44,59 @@ int sync_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int sync_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) { +#if !ENABLE_FEATURE_SYNC_FANCY /* coreutils-6.9 compat */ bb_warn_ignoring_args(argv[1]); - sync(); - return EXIT_SUCCESS; +#else + unsigned opts; + int ret = EXIT_SUCCESS; + + enum { + OPT_DATASYNC = (1 << 0), + OPT_SYNCFS = (1 << 1), + }; + + opt_complementary = "d--f:f--d"; + opts = getopt32(argv, "df"); + argv += optind; + + /* Handle the no-argument case. */ + if (!argv[0]) + sync(); + + while (*argv) { + int fd = open_or_warn(*argv, O_RDONLY); + + if (fd < 0) { + ret = EXIT_FAILURE; + goto next; + } + if (opts & OPT_DATASYNC) { + if (fdatasync(fd)) + goto err; + goto do_close; + } + if (opts & OPT_SYNCFS) { + /* + * syncfs is documented to only fail with EBADF, + * which can't happen here. So, no error checks. + */ + syncfs(fd); + goto do_close; + } + if (fsync(fd)) { + err: + bb_simple_perror_msg(*argv); + ret = EXIT_FAILURE; + } + do_close: + close(fd); + next: + ++argv; + } + + return ret; +#endif } diff --git a/include/applets.src.h b/include/applets.src.h index b80c4f4e8..9f3ac78cb 100644 --- a/include/applets.src.h +++ b/include/applets.src.h @@ -337,7 +337,6 @@ IF_SVLOGD(APPLET(svlogd, BB_DIR_USR_SBIN, BB_SUID_DROP)) IF_SWAPONOFF(APPLET_ODDNAME(swapoff, swap_on_off, BB_DIR_SBIN, BB_SUID_DROP, swapoff)) IF_SWAPONOFF(APPLET_ODDNAME(swapon, swap_on_off, BB_DIR_SBIN, BB_SUID_DROP, swapon)) IF_SWITCH_ROOT(APPLET(switch_root, BB_DIR_SBIN, BB_SUID_DROP)) -IF_SYNC(APPLET_NOFORK(sync, sync, BB_DIR_BIN, BB_SUID_DROP, sync)) IF_BB_SYSCTL(APPLET(sysctl, BB_DIR_SBIN, BB_SUID_DROP)) IF_SYSLOGD(APPLET(syslogd, BB_DIR_SBIN, BB_SUID_DROP)) IF_TAC(APPLET_NOEXEC(tac, tac, BB_DIR_USR_BIN, BB_SUID_DROP, tac))