]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: add functions to safely replace a fs table
authorOndrej Oprala <ooprala@redhat.com>
Fri, 14 Jun 2013 11:00:49 +0000 (13:00 +0200)
committerKarel Zak <kzak@redhat.com>
Wed, 3 Jul 2013 09:21:33 +0000 (11:21 +0200)
Signed-off-by: Ondrej Oprala <ooprala@redhat.com>
libmount/src/fs.c
libmount/src/libmount.sym
libmount/src/tab_update.c
tests/expected/libmount/update-fstab-replace [new file with mode: 0644]
tests/ts/libmount/update

index bcf250597c0fbf13433fabfc19071d0bf4e93b61..b6b3d12b83f7546c4a6737b4ddc900ac3a980eb9 100644 (file)
@@ -1300,6 +1300,10 @@ const char *mnt_fs_get_comment(struct libmnt_fs *fs)
  * @fs: fstab entry pointer
  * @comm: comment string
  *
+ * Note that the comment has to be terminated by '\n' (new line), otherwise
+ * whole filesystem entry will be written as a comment to the tabfile (e.g.
+ * fstab).
+ *
  * Returns: 0 on success or <0 in case of error.
  */
 int mnt_fs_set_comment(struct libmnt_fs *fs, const char *comm)
@@ -1324,6 +1328,8 @@ int mnt_fs_set_comment(struct libmnt_fs *fs, const char *comm)
  * mnt_fs_append_comment:
  * @fs: fstab entry pointer
  *
+ * See also mnt_fs_set_comment().
+ *
  * Returns: 0 on success or <0 in case of error.
  */
 int mnt_fs_append_comment(struct libmnt_fs *fs, const char *comm)
index f72a8f83694f2a8b6e2bc85a7c2b8110f2f96750..053783a72701169a9612801c0a0851761676f318 100644 (file)
@@ -267,6 +267,8 @@ global:
        mnt_table_enable_comments;
        mnt_table_get_intro_comment;
        mnt_table_get_tailing_comment;
+       mnt_table_replace_file;
        mnt_table_set_intro_comment;
        mnt_table_set_tailing_comment;
+       mnt_table_write_file;
 } MOUNT_2.23;
index b83c1dd37abc64a0318cdf581033c46714298aab..64d813183c6bccfc4cfe36cdb6fe91b7fd505b96 100644 (file)
@@ -579,6 +579,87 @@ leave:
        return rc;
 }
 
+/**
+ * mnt_table_write_file
+ * @tb: parsed file (e.g. fstab)
+ * @file: target
+ *
+ * This function writes @tb to @file.
+ *
+ * Returns: 0 on success, negative number on error.
+ */
+int mnt_table_write_file(struct libmnt_table *tb, FILE *file)
+{
+       int rc = 0;
+       struct libmnt_iter itr;
+       struct libmnt_fs *fs;
+
+       if (tb->comms && mnt_table_get_intro_comment(tb))
+               fputs(mnt_table_get_intro_comment(tb), file);
+
+       mnt_reset_iter(&itr, MNT_ITER_FORWARD);
+       while(mnt_table_next_fs(tb, &itr, &fs) == 0) {
+               rc = fprintf_mtab_fs(file, fs);
+               if (rc)
+                       return rc;
+       }
+       if (tb->comms && mnt_table_get_tailing_comment(tb))
+               fputs(mnt_table_get_tailing_comment(tb), file);
+
+       if (fflush(file) != 0)
+               rc = -errno;
+
+       DBG(TAB, mnt_debug_h(tb, "write file done [rc=%d]", rc));
+       return rc;
+}
+
+/**
+ * mnt_table_replace_file
+ * @tb: parsed file (e.g. fstab)
+ * @filename: target
+ *
+ * This function repaces @file by the new content from @tb.
+ *
+ * Returns: 0 on success, negative number on error.
+ */
+int mnt_table_replace_file(struct libmnt_table *tb, const char *filename)
+{
+       int fd, rc = 0;
+       FILE *f;
+       char *uq = NULL;
+
+       DBG(TAB, mnt_debug_h(tb, "%s: replacing", filename));
+
+       fd = mnt_open_uniq_filename(filename, &uq);
+       if (fd < 0)
+               return fd;      /* error */
+
+       f = fdopen(fd, "w" UL_CLOEXECSTR);
+       if (f) {
+               struct stat st;
+
+               mnt_table_write_file(tb, f);
+
+               rc = fchmod(fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) ? -errno : 0;
+
+               if (!rc && stat(filename, &st) == 0)
+                       /* Copy uid/gid from the present file before renaming. */
+                       rc = fchown(fd, st.st_uid, st.st_gid) ? -errno : 0;
+
+               fclose(f);
+               if (!rc)
+                       rename(uq, filename);
+       } else {
+               rc = -errno;
+               close(fd);
+       }
+
+       unlink(uq);
+       free(uq);
+
+       DBG(TAB, mnt_debug_h(tb, "replace done [rc=%d]", rc));
+       return rc;
+}
 static int add_file_entry(struct libmnt_table *tb, struct libmnt_update *upd)
 {
        struct libmnt_fs *fs;
@@ -866,6 +947,28 @@ static int test_remount(struct libmnt_test *ts, int argc, char *argv[])
        return rc;
 }
 
+static int test_replace(struct libmnt_test *ts, int argc, char *argv[])
+{
+       struct libmnt_fs *fs = mnt_new_fs();
+       struct libmnt_table *tb = mnt_new_table();
+       int rc;
+
+       if (argc < 3)
+               return -1;
+
+       mnt_table_enable_comments(tb, TRUE);
+       mnt_table_parse_fstab(tb, NULL);
+
+       mnt_fs_set_source(fs, argv[1]);
+       mnt_fs_set_target(fs, argv[2]);
+       mnt_fs_append_comment(fs, "# this is new filesystem\n");
+       mnt_table_add_fs(tb, fs);
+
+       rc = mnt_table_replace_file(tb, mnt_get_fstab_path());
+       mnt_free_table(tb);
+       return rc;
+}
+
 int main(int argc, char *argv[])
 {
        struct libmnt_test tss[] = {
@@ -873,6 +976,7 @@ int main(int argc, char *argv[])
        { "--remove", test_remove,  "<target>                      MS_REMOUNT mtab change" },
        { "--move",   test_move,    "<old_target>  <target>        MS_MOVE mtab change" },
        { "--remount",test_remount, "<target>  <options>           MS_REMOUNT mtab change" },
+       { "--replace",test_replace, "<src> <target>                Add a line to LIBMOUNT_FSTAB and replace the original file" },
        { NULL }
        };
 
diff --git a/tests/expected/libmount/update-fstab-replace b/tests/expected/libmount/update-fstab-replace
new file mode 100644 (file)
index 0000000..dc8d1df
--- /dev/null
@@ -0,0 +1,24 @@
+#
+ # this is a leading comment
+#
+
+# this comments belongs to the first fs
+UUID=d3a8f783-df75-4dc8-9163-975a891052c0 / ext3 noatime,defaults 1 1
+UUID=fef7ccb3-821c-4de8-88dc-71472be5946f /boot ext3 noatime,defaults 1 2
+
+# 3rd fs comment + newline padding
+
+UUID=1f2aa318-9c34-462e-8d29-260819ffd657 swap swap defaults 0 0
+tmpfs /dev/shm tmpfs defaults 0 0
+devpts /dev/pts devpts gid=5,mode=620 0 0
+sysfs /sys sysfs defaults 0 0
+proc /proc proc defaults 0 0
+# this is comment
+/dev/mapper/foo /home/foo ext4 noatime,defaults 0 0
+foo.com:/mnt/share /mnt/remote nfs noauto 0 0
+//bar.com/gogogo /mnt/gogogo cifs user=SRGROUP/baby,noauto 0 0
+/dev/foo /any/foo/ auto defaults 0 0
+# this is new filesystem
+LABEL=foo /mnt/foo none rw 0 0
+
+#this is a trailing comment
index 3a989dddb8b0b6482bab10d152ed3c59202ec395..6d4bce81ce5d1f4dd8c400970b8b18639a45de3d 100755 (executable)
@@ -93,4 +93,16 @@ ts_valgrind $TESTPROG --remove /proc
 cp $LIBMOUNT_UTAB $TS_OUTPUT   # save the mtab aside
 ts_finalize_subtest            # checks the mtab
 
+#
+# fstab - replace
+#
+export LIBMOUNT_FSTAB=$TS_OUTPUT.fstab
+rm -f $LIBMOUNT_FSTAB
+cp "$TS_SELF/files/fstab.comment" $LIBMOUNT_FSTAB
+
+ts_init_subtest "fstab-replace"
+ts_valgrind $TESTPROG --replace "LABEL=foo" "/mnt/foo"
+cp $LIBMOUNT_FSTAB $TS_OUTPUT  # save the fstab aside
+ts_finalize_subtest            #checks the fstab
+
 ts_finalize