sync: add support for -d -f FILE
authorDenys Vlasenko <vda.linux@googlemail.com>
Tue, 21 Jul 2015 17:50:48 +0000 (19:50 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Tue, 21 Jul 2015 17:50:48 +0000 (19:50 +0200)
Based on the patch by Ari Sundholm <ari@tuxera.com>

function                                             old     new   delta
sync_main                                             20     163    +143
packed_usage                                       30653   30673     +20
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 163/0)             Total: 163 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
coreutils/Config.src
coreutils/Kbuild.src
coreutils/sync.c
include/applets.src.h

index 1ec3a0a993a73cbc3dc76430b5100fbde20aa2df..02155d22016611f4a665f11a88a30e1b7a982e27 100644 (file)
@@ -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
index ec4ef7df247d5b9e3bc93bd2c37ade1a3152ce0f..4ec075ac67284ae4033fde8c43c1adeb647222ca 100644 (file)
@@ -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
index 7d98a1e301fa1dfe19da08793476a16369e5778c..974e904520cefd7f9449593745835c95008938c5 100644 (file)
@@ -3,16 +3,39 @@
  * Mini sync implementation for busybox
  *
  * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>.
+ * Copyright (C) 2015 by Ari Sundholm <ari@tuxera.com>
  *
  * 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"
 
 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
 }
index b80c4f4e842e063c5d1783b67281368f800763d4..9f3ac78cb7fcde0503f3b43a46164ecf46aff0d0 100644 (file)
@@ -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))