0001-fixed-snaprm-command-to-avoid-removing-PFS-symlinks.patch

xbit, 08/10/2011 11:26 AM

Download (7.84 KB)

View differences:

sbin/hammer/cmd_snapshot.c
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
-