| 53 |
53 |
static void snapshot_ls(const char *path);
|
| 54 |
54 |
static void snapshot_del(int fsfd, hammer_tid_t tid);
|
| 55 |
55 |
static char *dirpart(const char *path);
|
|
56 |
static void snapshot_snaprm_by_tid(char **av, int ac, int fsfd);
|
| 56 |
57 |
|
| 57 |
58 |
/*
|
| 58 |
59 |
* hammer snap <path> [<note>]
|
| ... | ... | |
| 200 |
201 |
}
|
| 201 |
202 |
|
| 202 |
203 |
/*
|
| 203 |
|
* hammer snaprm <path> ...
|
| 204 |
|
* hammer snaprm <transid> ...
|
| 205 |
|
* hammer snaprm <filesystem> <transid> ...
|
|
204 |
* hammer snaprm <snapshot path> [<snapshot path> ...]
|
|
205 |
* hammer snaprm <transid> [<transid> ...]
|
|
206 |
* hammer snaprm <filesystem> <transid> [<transid> ...]
|
| 206 |
207 |
*/
|
| 207 |
208 |
void
|
| 208 |
209 |
hammer_cmd_snaprm(char **av, int ac)
|
| 209 |
210 |
{
|
| 210 |
211 |
struct stat st;
|
| 211 |
|
char linkbuf[1024];
|
|
212 |
char linkbuf[1024] = { 0 };
|
| 212 |
213 |
intmax_t tid;
|
| 213 |
214 |
int fsfd = -1;
|
| 214 |
|
int i;
|
|
215 |
int i = 0;
|
| 215 |
216 |
char *dirpath;
|
| 216 |
217 |
char *ptr;
|
|
218 |
uint8_t remove_symlinks = 0;
|
| 217 |
219 |
|
| 218 |
|
for (i = 0; i < ac; ++i) {
|
| 219 |
|
if (lstat(av[i], &st) < 0) {
|
| 220 |
|
tid = strtoull(av[i], &ptr, 16);
|
| 221 |
|
if (*ptr) {
|
| 222 |
|
err(2, "hammer snaprm: not a file or tid: %s",
|
| 223 |
|
av[i]);
|
| 224 |
|
/* not reached */
|
|
220 |
// leave if no arg
|
|
221 |
if(ac == 0) {
|
|
222 |
err(EINVAL, "hammer snaprm: at least one argument is "
|
|
223 |
"required");
|
|
224 |
/* not reached */
|
|
225 |
}
|
|
226 |
|
|
227 |
do {
|
|
228 |
// inspect arguments
|
|
229 |
if (lstat(av[i], &st) == 0) {
|
|
230 |
// argument is either a link or a path, get
|
|
231 |
// associated PFS
|
|
232 |
// Call: hammer snaprm <filesystem> <transid> [<transid> ...]
|
|
233 |
if(S_ISDIR(st.st_mode)) {
|
|
234 |
if(remove_symlinks) {
|
|
235 |
err(EINVAL,
|
|
236 |
"hammer snaprm: invalid argument "
|
|
237 |
"passed, snapshot symlink "
|
|
238 |
"expected");
|
|
239 |
/* not reached */
|
|
240 |
}
|
|
241 |
assert(fsfd == -1);
|
|
242 |
assert(i == 0);
|
|
243 |
fsfd = open(av[0], O_RDONLY);
|
|
244 |
if(fsfd >= 0) {
|
|
245 |
// skip first argument
|
|
246 |
snapshot_snaprm_by_tid(av + 1, ac - 1, fsfd);
|
|
247 |
}
|
| 225 |
248 |
}
|
| 226 |
|
if (fsfd < 0)
|
| 227 |
|
fsfd = open(".", O_RDONLY);
|
| 228 |
|
snapshot_del(fsfd, tid);
|
| 229 |
|
} else if (S_ISDIR(st.st_mode)) {
|
| 230 |
|
if (fsfd >= 0)
|
| 231 |
|
close(fsfd);
|
| 232 |
|
fsfd = open(av[i], O_RDONLY);
|
| 233 |
|
if (fsfd < 0) {
|
| 234 |
|
err(2, "hammer snaprm: cannot open dir %s",
|
| 235 |
|
av[i]);
|
| 236 |
|
/* not reached */
|
|
249 |
else if(S_ISLNK(st.st_mode)) {
|
|
250 |
// check if link points to a version or to a PFS
|
|
251 |
if (readlink(av[i], linkbuf, sizeof(linkbuf) - 1) < 0) {
|
|
252 |
err(ENOENT, "hammer snaprm: cannot read softlink: "
|
|
253 |
"%s", av[i]);
|
|
254 |
/* not reached */
|
|
255 |
}
|
|
256 |
|
|
257 |
// snapshot link looks like /path/to/pfs/@@0x0000000123456789
|
|
258 |
// PFS link looks like /path/to/@@-1:00001
|
|
259 |
|
|
260 |
// Call: hammer snaprm <filesystem> <transid> [<transid> ...]
|
|
261 |
// Call: hammer snaprm <snapshot path> [<snapshot path> ...]
|
|
262 |
dirpath = strrchr(linkbuf, '@');
|
|
263 |
if((dirpath != NULL) &&
|
|
264 |
(dirpath > linkbuf) &&
|
|
265 |
(*(--dirpath) == '@')) {
|
|
266 |
// dirpath points to link target without path
|
|
267 |
// skip leading @@
|
|
268 |
dirpath += 2;
|
|
269 |
tid = strtoull(dirpath, &ptr, 16);
|
|
270 |
if(*ptr) {
|
|
271 |
// Call: hammer snaprm <filesystem> <transid> [...]
|
|
272 |
if(remove_symlinks) {
|
|
273 |
err(ENOENT,
|
|
274 |
"hammer snaprm: invalid argument passed, "
|
|
275 |
"expect snapshot symlink");
|
|
276 |
/* not reached */
|
|
277 |
}
|
|
278 |
|
|
279 |
assert(fsfd == -1);
|
|
280 |
assert(i == 0);
|
|
281 |
// remove snapshot, at least one transid is required
|
|
282 |
if(ac == 1) {
|
|
283 |
err(EINVAL, "hammer snaprm: at least on "
|
|
284 |
"transid is required");
|
|
285 |
/* not reached */
|
|
286 |
}
|
|
287 |
fsfd = open(av[0], O_RDONLY);
|
|
288 |
if(fsfd >= 0) {
|
|
289 |
// skip first argument
|
|
290 |
snapshot_snaprm_by_tid(av + 1, ac - 1, fsfd);
|
|
291 |
}
|
|
292 |
}
|
|
293 |
else {
|
|
294 |
// Call: hammer snaprm <snapshot path> [...]
|
|
295 |
// remove symlink and snapshot
|
|
296 |
printf("Deleting snapshot 0x%016jx %s\n",
|
|
297 |
tid, av[i]);
|
|
298 |
fsfd = open(av[i], O_RDONLY);
|
|
299 |
if(fsfd >= 0) {
|
|
300 |
snapshot_del(fsfd, tid);
|
|
301 |
remove(av[0]);
|
|
302 |
}
|
|
303 |
// adjust flag and counter to remove more
|
|
304 |
// snapshots by symlink
|
|
305 |
if((ac > 1) && (i < (ac - 1))) {
|
|
306 |
++i;
|
|
307 |
remove_symlinks = 1;
|
|
308 |
}
|
|
309 |
else {
|
|
310 |
remove_symlinks = 0;
|
|
311 |
}
|
|
312 |
}
|
|
313 |
}
|
| 237 |
314 |
}
|
| 238 |
|
} else if (S_ISLNK(st.st_mode)) {
|
| 239 |
|
dirpath = dirpart(av[i]);
|
| 240 |
|
bzero(linkbuf, sizeof(linkbuf));
|
| 241 |
|
if (readlink(av[i], linkbuf, sizeof(linkbuf) - 1) < 0) {
|
| 242 |
|
err(2, "hammer snaprm: cannot read softlink: "
|
| 243 |
|
"%s", av[i]);
|
|
315 |
else {
|
|
316 |
err(EINVAL, "hammer snaprm: invalid parameter passed");
|
| 244 |
317 |
/* not reached */
|
| 245 |
318 |
}
|
| 246 |
|
if (linkbuf[0] == '/') {
|
| 247 |
|
free(dirpath);
|
| 248 |
|
dirpath = dirpart(linkbuf);
|
| 249 |
|
} else {
|
| 250 |
|
asprintf(&ptr, "%s/%s", dirpath, linkbuf);
|
| 251 |
|
free(dirpath);
|
| 252 |
|
dirpath = dirpart(ptr);
|
| 253 |
|
}
|
|
319 |
}
|
|
320 |
else {
|
|
321 |
// Call: hammer snaprm <transid> [<transid> ...]
|
| 254 |
322 |
|
| 255 |
|
if (fsfd >= 0)
|
| 256 |
|
close(fsfd);
|
| 257 |
|
fsfd = open(dirpath, O_RDONLY);
|
| 258 |
|
if (fsfd < 0) {
|
| 259 |
|
err(2, "hammer snaprm: cannot open dir %s",
|
| 260 |
|
dirpath);
|
|
323 |
// handle list of transids
|
|
324 |
if(remove_symlinks) {
|
|
325 |
err(EINVAL, "hammer snaprm: invalid argument passed, "
|
|
326 |
"expect snapshot symlink");
|
| 261 |
327 |
/* not reached */
|
| 262 |
328 |
}
|
| 263 |
329 |
|
| 264 |
|
if ((ptr = strrchr(linkbuf, '@')) &&
|
| 265 |
|
ptr > linkbuf && ptr[-1] == '@') {
|
| 266 |
|
tid = strtoull(ptr + 1, NULL, 16);
|
| 267 |
|
snapshot_del(fsfd, tid);
|
|
330 |
assert(fsfd == -1);
|
|
331 |
assert(i == 0);
|
|
332 |
fsfd = open(".", O_RDONLY);
|
|
333 |
if(fsfd >= 0) {
|
|
334 |
snapshot_snaprm_by_tid(av, ac, fsfd);
|
| 268 |
335 |
}
|
| 269 |
|
remove(av[i]);
|
| 270 |
|
free(dirpath);
|
| 271 |
|
} else {
|
| 272 |
|
err(2, "hammer snaprm: not directory or snapshot "
|
| 273 |
|
"softlink: %s", av[i]);
|
| 274 |
|
/* not reached */
|
| 275 |
336 |
}
|
| 276 |
|
}
|
| 277 |
|
if (fsfd >= 0)
|
|
337 |
} while(remove_symlinks);
|
|
338 |
|
|
339 |
if(fsfd >= 0) {
|
| 278 |
340 |
close(fsfd);
|
|
341 |
}
|
| 279 |
342 |
}
|
| 280 |
343 |
|
| 281 |
344 |
/*
|
| ... | ... | |
| 565 |
628 |
"hammer snaplo <path> [<note>]\t\tcreate snapshot & link, points to\n"
|
| 566 |
629 |
"\t\t\t\t\ttarget dir\n"
|
| 567 |
630 |
"hammer snapq <dir> [<note>]\t\tcreate snapshot, output path to stdout\n"
|
| 568 |
|
"hammer snaprm <path> ...\t\tdelete snapshots; filesystem is CWD\n"
|
| 569 |
|
"hammer snaprm <transid> ...\t\tdelete snapshots\n"
|
| 570 |
|
"hammer snaprm <filesystem> <transid> ...\tdelete snapshots\n"
|
|
631 |
"hammer snaprm <symlink> ...\t\tdelete snapshots by symlink\n"
|
|
632 |
"hammer snaprm <transid> ...\t\tdelete snapshots by ID for CWD\n"
|
|
633 |
"hammer snaprm <PFS> <transid> ...\tdelete snapshots by ID on PFS\n"
|
| 571 |
634 |
"hammer snapls [<path> ...]\t\tlist available snapshots\n"
|
| 572 |
635 |
"\n"
|
| 573 |
636 |
"NOTE: Snapshots are created in filesystem meta-data, any directory\n"
|
| ... | ... | |
| 611 |
674 |
res[ptr - path] = 0;
|
| 612 |
675 |
return(res);
|
| 613 |
676 |
}
|
|
677 |
|
|
678 |
/**
|
|
679 |
* Remove all snapshots that are passed as arguments.
|
|
680 |
*
|
|
681 |
* Expect each argument to be a transid.
|
|
682 |
*/
|
|
683 |
static
|
|
684 |
void
|
|
685 |
snapshot_snaprm_by_tid(char **av, int ac, int fsfd)
|
|
686 |
{
|
|
687 |
int i;
|
|
688 |
intmax_t tid;
|
|
689 |
char *ptr;
|
|
690 |
|
|
691 |
assert(fsfd >= 0);
|
|
692 |
assert(ac > 0);
|
|
693 |
|
|
694 |
for(i = 0; i < ac; ++i) {
|
|
695 |
tid = strtoull(av[i], &ptr, 16);
|
|
696 |
if(*ptr) {
|
|
697 |
// conversion failed
|
|
698 |
if(fsfd >= 0) {
|
|
699 |
close(fsfd);
|
|
700 |
}
|
|
701 |
err(ENOENT, "hammer snaprm: not a file or tid: %s",
|
|
702 |
av[i]);
|
|
703 |
/* not reached */
|
|
704 |
}
|
|
705 |
printf("Deleting snapshot 0x%016jx\n", tid);
|
|
706 |
snapshot_del(fsfd, tid);
|
|
707 |
}
|
|
708 |
}
|
| 614 |
|
-
|