994ca72fcb9f9ff58a07634a45e85242d8073d20
[pcu.git] / fsync.c
blob994ca72fcb9f9ff58a07634a45e85242d8073d20
1 #include "compat-util.h"
2 #include <dirent.h>
3 #include <libgen.h>
5 #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
6 static int have_fdatasync = 1;
7 #else
8 static int have_fdatasync;
9 #endif
11 /* TODO: sync_file_range() if on Linux */
13 static int usage(const char * argv0)
15 fprintf(stderr, "Usage: %s [-d] [-D] FILE...\n", argv0);
16 return 1;
19 static int do_sync(const char *path, int data_only, int directory)
21 int fd;
22 const char *errfunc = "";
24 if ((fd = open(path, O_RDWR|O_NOATIME)) < 0) {
25 if (errno == EISDIR) {
26 directory = 1;
27 goto sync_dir;
29 errfunc = "open";
30 goto err;
33 if (data_only && have_fdatasync) {
34 if (fdatasync(fd) < 0) {
35 errfunc = "fdatasync";
36 goto err;
38 } else {
39 if (fsync(fd) < 0) {
40 errfunc = "fsync";
41 goto err;
45 if (close(fd) < 0) {
46 errfunc = "close";
47 goto err;
50 sync_dir:
51 if (directory) {
52 char *dpath;
53 DIR *dir;
55 if (!(dpath = strdup(path))){
56 errfunc = "strdup";
57 goto err;
59 if (!(dir = opendir(dirname(dpath)))) {
60 errfunc = "opendir";
61 goto err;
63 if (fsync(dirfd(dir)) < 0) {
64 errfunc = "(directory) fsync";
65 goto err;
67 if (closedir(dir) < 0) {
68 errfunc = "closedir";
69 goto err;
71 free(dpath);
74 return 0;
75 err:
76 fprintf(stderr, "%s: %s(): %s\n", path, errfunc, strerror(errno));
77 return -1;
80 int main(int argc, char * const argv[])
82 int data_only = 0;
83 int directory = 0;
84 int opt;
85 int argi = 1;
87 while ((opt = getopt(argc, argv, "dD")) != -1) {
88 ++argi;
89 switch(opt) {
90 case 'd':
91 data_only = 1;
92 break;
93 case 'D':
94 directory = 1;
95 break;
96 default:
97 return usage(argv[0]);
101 if (argi >= argc)
102 return usage(argv[0]);
104 for (; argi < argc; ++argi) {
105 if (do_sync(argv[argi], data_only, directory) < 0)
106 return 1;
109 return 0;