summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libmount/src/fs.c6
-rw-r--r--libmount/src/libmount.sym2
-rw-r--r--libmount/src/tab_update.c104
-rw-r--r--tests/expected/libmount/update-fstab-replace24
-rwxr-xr-xtests/ts/libmount/update12
5 files changed, 148 insertions, 0 deletions
diff --git a/libmount/src/fs.c b/libmount/src/fs.c
index bcf250597..b6b3d12b8 100644
--- a/libmount/src/fs.c
+++ b/libmount/src/fs.c
@@ -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)
diff --git a/libmount/src/libmount.sym b/libmount/src/libmount.sym
index f72a8f836..053783a72 100644
--- a/libmount/src/libmount.sym
+++ b/libmount/src/libmount.sym
@@ -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;
diff --git a/libmount/src/tab_update.c b/libmount/src/tab_update.c
index b83c1dd37..64d813183 100644
--- a/libmount/src/tab_update.c
+++ b/libmount/src/tab_update.c
@@ -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
index 000000000..dc8d1dfbc
--- /dev/null
+++ b/tests/expected/libmount/update-fstab-replace
@@ -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
diff --git a/tests/ts/libmount/update b/tests/ts/libmount/update
index 3a989dddb..6d4bce81c 100755
--- a/tests/ts/libmount/update
+++ b/tests/ts/libmount/update
@@ -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