bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] loadables/sync: allow fsync of individual files like GNU coreuti


From: Chris Webb
Subject: [PATCH] loadables/sync: allow fsync of individual files like GNU coreutils
Date: Sun, 18 Dec 2022 12:52:42 +0000

It's often useful to fsync an individual file from a shell script, for
example after writing a log entry which needs to be safely persisted. Doing
so with a loadable builtin is much less expensive than spawning an external
command just to call fsync(2).

The sync command in GNU coreutils can be run without arguments to call
sync(2), or with filename arguments to open and fsync each of them. Extend
the sync loadable builtin to support similar usage.

For each given file, try to open O_WRONLY and then O_RDONLY if that fails,
e.g. because of permissions. On most OSes, fsync(2) works fine with a
read-only file descriptor, but on AIX and Cygwin write access is required,
so we attempt that first.

Signed-off-by: Chris Webb <chris@arachsys.com>
---
 examples/loadables/sync.c | 52 +++++++++++++++++++++++++++++++++------
 1 file changed, 45 insertions(+), 7 deletions(-)

diff --git a/examples/loadables/sync.c b/examples/loadables/sync.c
index 4fbeee1..b256df1 100644
--- a/examples/loadables/sync.c
+++ b/examples/loadables/sync.c
@@ -24,22 +24,60 @@
 #include <unistd.h>
 #endif
 
+#include <errno.h>
+#include <fcntl.h>
+
 #include "builtins.h"
 #include "shell.h"
-#include "bashgetopt.h"
+#include "common.h"
+
+#if !defined (errno)
+extern int errno;
+#endif
 
 int
 sync_builtin (list)
      WORD_LIST *list;
 {
-  sync();
-  return (EXECUTION_SUCCESS);
+  int fd, result = EXECUTION_SUCCESS;
+
+  if (!list)
+    sync();
+  else if (!strcmp (list->word->word, "--"))
+    list = list->next;
+
+  while (list)
+    {
+      fd = open (list->word->word, O_WRONLY);
+      if (fd < 0)
+        fd = open (list->word->word, O_RDONLY);
+      if (fd < 0)
+        {
+          file_error (list->word->word);
+          result = EXECUTION_FAILURE;
+        }
+      else
+        {
+          if (fsync (fd) < 0)
+            {
+              builtin_error ("cannot sync file `%s': %s", list->word->word, 
strerror (errno));
+              result = EXECUTION_FAILURE;
+            }
+          close (fd);
+        }
+      list = list->next;
+    }
+  return result;
 }
 
 char *sync_doc[] = {
-       "Sync disks.",
-       ""
-       "Force completion of pending disk writes",
+       "Sync disks or specified files.",
+       "",
+       "Force completion of pending disk writes.  If one or more files are",
+       "specified, only force completion of pending writes to those files.",
+       "",
+       "Exit Status:",
+       "Returns success unless any specified files could not be synced.",
        (char *)NULL
 };
 
@@ -48,6 +86,6 @@ struct builtin sync_struct = {
        sync_builtin,           /* function implementing the builtin */
        BUILTIN_ENABLED,        /* initial flags for builtin */
        sync_doc,               /* array of long documentation strings. */
-       "sync",                 /* usage synopsis; becomes short_doc */
+       "sync [file ...]",      /* usage synopsis; becomes short_doc */
        0                       /* reserved for internal use */
 };



reply via email to

[Prev in Thread] Current Thread [Next in Thread]