DragonFly submit List (threaded) for 2011-09
[Date Prev][
Date Next]
[Thread Prev][
Thread Next]
[
Date Index][
Thread Index]
[PATCH] fixed snaprm command to avoid removing PFS symlinks
* Calling 'hammer snaprm /pfs/some.pfs 0x0000000123456789' removed
the PFS link /pfs/some.pfs. This has been fixed.
* Re-implemented function to detect if a symlink points to a transid or
to a PSF.
* Allow passing more arguments to each call, updated the usage as well.
Each call can now remove more than one snapshot.
Signed-off-by: Sven Gaerner <sgaerner@gmx.net>
---
sbin/hammer/cmd_snapshot.c | 211 ++++++++++++++++++++++++++++++++------------
1 files changed, 153 insertions(+), 58 deletions(-)
diff --git a/sbin/hammer/cmd_snapshot.c b/sbin/hammer/cmd_snapshot.c
index 796c38b..cf65071 100644
--- a/sbin/hammer/cmd_snapshot.c
+++ b/sbin/hammer/cmd_snapshot.c
@@ -53,6 +53,7 @@ static void snapshot_add(int fd, const char *fsym, const char *tsym,
static void snapshot_ls(const char *path);
static void snapshot_del(int fsfd, hammer_tid_t tid);
static char *dirpart(const char *path);
+static void snapshot_snaprm_by_tid(char **av, int ac, int fsfd);
/*
* hammer snap <path> [<note>]
@@ -200,82 +201,144 @@ hammer_cmd_snapls(char **av, int ac)
}
/*
- * hammer snaprm <path> ...
- * hammer snaprm <transid> ...
- * hammer snaprm <filesystem> <transid> ...
+ * hammer snaprm <snapshot path> [<snapshot path> ...]
+ * hammer snaprm <transid> [<transid> ...]
+ * hammer snaprm <filesystem> <transid> [<transid> ...]
*/
void
hammer_cmd_snaprm(char **av, int ac)
{
struct stat st;
- char linkbuf[1024];
+ char linkbuf[1024] = { 0 };
intmax_t tid;
int fsfd = -1;
- int i;
+ int i = 0;
char *dirpath;
char *ptr;
+ uint8_t remove_symlinks = 0;
- for (i = 0; i < ac; ++i) {
- if (lstat(av[i], &st) < 0) {
- tid = strtoull(av[i], &ptr, 16);
- if (*ptr) {
- err(2, "hammer snaprm: not a file or tid: %s",
- av[i]);
- /* not reached */
+ // leave if no arg
+ if(ac == 0) {
+ err(EINVAL, "hammer snaprm: at least one argument is "
+ "required");
+ /* not reached */
+ }
+
+ do {
+ // inspect arguments
+ if (lstat(av[i], &st) == 0) {
+ // argument is either a link or a path, get
+ // associated PFS
+ // Call: hammer snaprm <filesystem> <transid> [<transid> ...]
+ if(S_ISDIR(st.st_mode)) {
+ if(remove_symlinks) {
+ err(EINVAL,
+ "hammer snaprm: invalid argument "
+ "passed, snapshot symlink "
+ "expected");
+ /* not reached */
+ }
+ assert(fsfd == -1);
+ assert(i == 0);
+ fsfd = open(av[0], O_RDONLY);
+ if(fsfd >= 0) {
+ // skip first argument
+ snapshot_snaprm_by_tid(av + 1, ac - 1, fsfd);
+ }
}
- if (fsfd < 0)
- fsfd = open(".", O_RDONLY);
- snapshot_del(fsfd, tid);
- } else if (S_ISDIR(st.st_mode)) {
- if (fsfd >= 0)
- close(fsfd);
- fsfd = open(av[i], O_RDONLY);
- if (fsfd < 0) {
- err(2, "hammer snaprm: cannot open dir %s",
- av[i]);
- /* not reached */
+ else if(S_ISLNK(st.st_mode)) {
+ // check if link points to a version or to a PFS
+ if (readlink(av[i], linkbuf, sizeof(linkbuf) - 1) < 0) {
+ err(ENOENT, "hammer snaprm: cannot read softlink: "
+ "%s", av[i]);
+ /* not reached */
+ }
+
+ // snapshot link looks like /path/to/pfs/@@0x0000000123456789
+ // PFS link looks like /path/to/@@-1:00001
+
+ // Call: hammer snaprm <filesystem> <transid> [<transid> ...]
+ // Call: hammer snaprm <snapshot path> [<snapshot path> ...]
+ dirpath = strrchr(linkbuf, '@');
+ if((dirpath != NULL) &&
+ (dirpath > linkbuf) &&
+ (*(--dirpath) == '@')) {
+ // dirpath points to link target without path
+ // skip leading @@
+ dirpath += 2;
+ tid = strtoull(dirpath, &ptr, 16);
+ if(*ptr) {
+ // Call: hammer snaprm <filesystem> <transid> [...]
+ if(remove_symlinks) {
+ err(ENOENT,
+ "hammer snaprm: invalid argument passed, "
+ "expect snapshot symlink");
+ /* not reached */
+ }
+
+ assert(fsfd == -1);
+ assert(i == 0);
+ // remove snapshot, at least one transid is required
+ if(ac == 1) {
+ err(EINVAL, "hammer snaprm: at least on "
+ "transid is required");
+ /* not reached */
+ }
+ fsfd = open(av[0], O_RDONLY);
+ if(fsfd >= 0) {
+ // skip first argument
+ snapshot_snaprm_by_tid(av + 1, ac - 1, fsfd);
+ }
+ }
+ else {
+ // Call: hammer snaprm <snapshot path> [...]
+ // remove symlink and snapshot
+ printf("Deleting snapshot 0x%016jx %s\n",
+ tid, av[i]);
+ fsfd = open(av[i], O_RDONLY);
+ if(fsfd >= 0) {
+ snapshot_del(fsfd, tid);
+ remove(av[0]);
+ }
+ // adjust flag and counter to remove more
+ // snapshots by symlink
+ if((ac > 1) && (i < (ac - 1))) {
+ ++i;
+ remove_symlinks = 1;
+ }
+ else {
+ remove_symlinks = 0;
+ }
+ }
+ }
}
- } else if (S_ISLNK(st.st_mode)) {
- dirpath = dirpart(av[i]);
- bzero(linkbuf, sizeof(linkbuf));
- if (readlink(av[i], linkbuf, sizeof(linkbuf) - 1) < 0) {
- err(2, "hammer snaprm: cannot read softlink: "
- "%s", av[i]);
+ else {
+ err(EINVAL, "hammer snaprm: invalid parameter passed");
/* not reached */
}
- if (linkbuf[0] == '/') {
- free(dirpath);
- dirpath = dirpart(linkbuf);
- } else {
- asprintf(&ptr, "%s/%s", dirpath, linkbuf);
- free(dirpath);
- dirpath = dirpart(ptr);
- }
+ }
+ else {
+ // Call: hammer snaprm <transid> [<transid> ...]
- if (fsfd >= 0)
- close(fsfd);
- fsfd = open(dirpath, O_RDONLY);
- if (fsfd < 0) {
- err(2, "hammer snaprm: cannot open dir %s",
- dirpath);
+ // handle list of transids
+ if(remove_symlinks) {
+ err(EINVAL, "hammer snaprm: invalid argument passed, "
+ "expect snapshot symlink");
/* not reached */
}
- if ((ptr = strrchr(linkbuf, '@')) &&
- ptr > linkbuf && ptr[-1] == '@') {
- tid = strtoull(ptr + 1, NULL, 16);
- snapshot_del(fsfd, tid);
+ assert(fsfd == -1);
+ assert(i == 0);
+ fsfd = open(".", O_RDONLY);
+ if(fsfd >= 0) {
+ snapshot_snaprm_by_tid(av, ac, fsfd);
}
- remove(av[i]);
- free(dirpath);
- } else {
- err(2, "hammer snaprm: not directory or snapshot "
- "softlink: %s", av[i]);
- /* not reached */
}
- }
- if (fsfd >= 0)
+ } while(remove_symlinks);
+
+ if(fsfd >= 0) {
close(fsfd);
+ }
}
/*
@@ -565,9 +628,9 @@ snapshot_usage(int exit_code)
"hammer snaplo <path> [<note>]\t\tcreate snapshot & link, points to\n"
"\t\t\t\t\ttarget dir\n"
"hammer snapq <dir> [<note>]\t\tcreate snapshot, output path to stdout\n"
- "hammer snaprm <path> ...\t\tdelete snapshots; filesystem is CWD\n"
- "hammer snaprm <transid> ...\t\tdelete snapshots\n"
- "hammer snaprm <filesystem> <transid> ...\tdelete snapshots\n"
+ "hammer snaprm <symlink> ...\t\tdelete snapshots by symlink\n"
+ "hammer snaprm <transid> ...\t\tdelete snapshots by ID for CWD\n"
+ "hammer snaprm <PFS> <transid> ...\tdelete snapshots by ID on PFS\n"
"hammer snapls [<path> ...]\t\tlist available snapshots\n"
"\n"
"NOTE: Snapshots are created in filesystem meta-data, any directory\n"
@@ -611,3 +674,35 @@ dirpart(const char *path)
res[ptr - path] = 0;
return(res);
}
+
+/**
+ * Remove all snapshots that are passed as arguments.
+ *
+ * Expect each argument to be a transid.
+ */
+static
+void
+snapshot_snaprm_by_tid(char **av, int ac, int fsfd)
+{
+ int i;
+ intmax_t tid;
+ char *ptr;
+
+ assert(fsfd >= 0);
+ assert(ac > 0);
+
+ for(i = 0; i < ac; ++i) {
+ tid = strtoull(av[i], &ptr, 16);
+ if(*ptr) {
+ // conversion failed
+ if(fsfd >= 0) {
+ close(fsfd);
+ }
+ err(ENOENT, "hammer snaprm: not a file or tid: %s",
+ av[i]);
+ /* not reached */
+ }
+ printf("Deleting snapshot 0x%016jx\n", tid);
+ snapshot_del(fsfd, tid);
+ }
+}
--
1.7.5.4
--QTprm0S8XgL7H0Dt--
[Date Prev][
Date Next]
[Thread Prev][
Thread Next]
[
Date Index][
Thread Index]