1 /* vi: set sw=4 ts=4: */
2 /*
3  * Mini sync implementation for busybox
4  *
5  * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>.
6  * Copyright (C) 2015 by Ari Sundholm <ari@tuxera.com>
7  *
8  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9  */
10 //config:config SYNC
11 //config:	bool "sync"
12 //config:	default y
13 //config:	help
14 //config:	  sync is used to flush filesystem buffers.
15 //config:config FEATURE_SYNC_FANCY
16 //config:	bool "Enable -d and -f flags (requires syncfs(2) in libc)"
17 //config:	default y
18 //config:	depends on SYNC
19 //config:	help
20 //config:	  sync -d FILE... executes fdatasync() on each FILE.
21 //config:	  sync -f FILE... executes syncfs() on each FILE.
22 
23 //applet:IF_SYNC(APPLET_NOFORK(sync, sync, BB_DIR_BIN, BB_SUID_DROP, sync))
24 
25 //kbuild:lib-$(CONFIG_SYNC) += sync.o
26 
27 /* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */
28 
29 //usage:#define sync_trivial_usage
30 //usage:       ""IF_FEATURE_SYNC_FANCY("[-df] [FILE]...")
31 //usage:#define sync_full_usage "\n\n"
32 //usage:    IF_NOT_FEATURE_SYNC_FANCY(
33 //usage:       "Write all buffered blocks to disk"
34 //usage:    )
35 //usage:    IF_FEATURE_SYNC_FANCY(
36 //usage:       "Write all buffered blocks (in FILEs) to disk"
37 //usage:     "\n	-d	Avoid syncing metadata"
38 //usage:     "\n	-f	Sync filesystems underlying FILEs"
39 //usage:    )
40 
41 #include "libbb.h"
42 
43 /* This is a NOFORK applet. Be very careful! */
44 
45 int sync_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
sync_main(int argc UNUSED_PARAM,char ** argv IF_NOT_DESKTOP (UNUSED_PARAM))46 int sync_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM))
47 {
48 #if !ENABLE_FEATURE_SYNC_FANCY
49 	/* coreutils-6.9 compat */
50 	bb_warn_ignoring_args(argv[1]);
51 	sync();
52 	return EXIT_SUCCESS;
53 #else
54 	unsigned opts;
55 	int ret = EXIT_SUCCESS;
56 
57 	enum {
58 		OPT_DATASYNC = (1 << 0),
59 		OPT_SYNCFS   = (1 << 1),
60 	};
61 
62 	opt_complementary = "d--f:f--d";
63 	opts = getopt32(argv, "df");
64 	argv += optind;
65 
66 	/* Handle the no-argument case. */
67 	if (!argv[0])
68 		sync();
69 
70 	while (*argv) {
71 		int fd = open_or_warn(*argv, O_RDONLY);
72 
73 		if (fd < 0) {
74 			ret = EXIT_FAILURE;
75 			goto next;
76 		}
77 		if (opts & OPT_DATASYNC) {
78 			if (fdatasync(fd))
79 				goto err;
80 			goto do_close;
81 		}
82 		if (opts & OPT_SYNCFS) {
83 			/*
84 			 * syncfs is documented to only fail with EBADF,
85 			 * which can't happen here. So, no error checks.
86 			 */
87 			syncfs(fd);
88 			goto do_close;
89 		}
90 		if (fsync(fd)) {
91  err:
92 			bb_simple_perror_msg(*argv);
93 			ret = EXIT_FAILURE;
94 		}
95  do_close:
96 		close(fd);
97  next:
98 		++argv;
99 	}
100 
101 	return ret;
102 #endif
103 }
104