Project

General

Profile

Bug #2111 ยป 0001-fixed-snaprm-command-to-avoid-removing-PFS-symlinks.patch

xbit, 08/10/2011 11:26 AM

View differences:

sbin/hammer/cmd_snapshot.c
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>]
......
}
/*
* 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);
}
}
/*
......
"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"
......
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-1/1)