+
+/* Given file name 'file_name', fsyncs the directory in which it is contained.
+ * Returns 0 if successful, otherwise a positive errno value. */
+int
+fsync_parent_dir(const char *file_name)
+{
+ int error = 0;
+ char *dir;
+ int fd;
+
+ dir = dir_name(file_name);
+ fd = open(dir, O_RDONLY);
+ if (fd >= 0) {
+ if (fsync(fd)) {
+ if (errno == EINVAL || errno == EROFS) {
+ /* This directory does not support synchronization. Not
+ * really an error. */
+ } else {
+ error = errno;
+ VLOG_ERR("%s: fsync failed (%s)", dir, strerror(error));
+ }
+ }
+ close(fd);
+ } else {
+ error = errno;
+ VLOG_ERR("%s: open failed (%s)", dir, strerror(error));
+ }
+ free(dir);
+
+ return error;
+}
+
+/* Obtains the modification time of the file named 'file_name' to the greatest
+ * supported precision. If successful, stores the mtime in '*mtime' and
+ * returns 0. On error, returns a positive errno value and stores zeros in
+ * '*mtime'. */
+int
+get_mtime(const char *file_name, struct timespec *mtime)
+{
+ struct stat s;
+
+ if (!stat(file_name, &s)) {
+ mtime->tv_sec = s.st_mtime;
+
+#if HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
+ mtime->tv_nsec = s.st_mtim.tv_nsec;
+#elif HAVE_STRUCT_STAT_ST_MTIMENSEC
+ mtime->tv_nsec = s.st_mtimensec;
+#else
+ mtime->tv_nsec = 0;
+#endif
+
+ return 0;
+ } else {
+ mtime->tv_sec = mtime->tv_nsec = 0;
+ return errno;
+ }
+}
+