diff options
author | Ondrej Oprala | 2013-06-14 13:00:49 +0200 |
---|---|---|
committer | Karel Zak | 2013-07-03 11:21:33 +0200 |
commit | d22f2822ed873bac1dbb28aa5fd5351f3a27b2b8 (patch) | |
tree | 2da585531305fbafa471160b3ff5f6a19bead17e | |
parent | libmount: add functions to handle comments in fs tables (diff) | |
download | kernel-qcow2-util-linux-d22f2822ed873bac1dbb28aa5fd5351f3a27b2b8.tar.gz kernel-qcow2-util-linux-d22f2822ed873bac1dbb28aa5fd5351f3a27b2b8.tar.xz kernel-qcow2-util-linux-d22f2822ed873bac1dbb28aa5fd5351f3a27b2b8.zip |
libmount: add functions to safely replace a fs table
Signed-off-by: Ondrej Oprala <ooprala@redhat.com>
-rw-r--r-- | libmount/src/fs.c | 6 | ||||
-rw-r--r-- | libmount/src/libmount.sym | 2 | ||||
-rw-r--r-- | libmount/src/tab_update.c | 104 | ||||
-rw-r--r-- | tests/expected/libmount/update-fstab-replace | 24 | ||||
-rwxr-xr-x | tests/ts/libmount/update | 12 |
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 |