Fixed bug 2111 - error in 'hammer snaprm'
--QTprm0S8XgL7H0Dt
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Hi,
I found an error when using 'hammer snaprm'. This error has been
reported as bug 2111.
Attached is the fix for this bug that is also attached to the ticket.
Regards,
Sven
--QTprm0S8XgL7H0Dt
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="0001-fixed-snaprm-command-to-avoid-removing-PFS-symlinks.patch"
From ba0cbce8b6fdb2fcbb02e14aaf9e7d536dd72d55 Mon Sep 17 00:00:00 2001
From: Sven Gaerner <sgaerner@gmx.net>
Date: Tue, 9 Aug 2011 16:39:14 +0200
Subject: [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--