xref: /freebsd/usr.sbin/snapinfo/snapinfo.c (revision 87569f75a91f298c52a71823c04d41cf53c88889)
1 /*-
2  * Copyright (c) 2005 Mark Santcroos <marks@freebsd.org>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  * $FreeBSD$
25  *
26  */
27 
28 #include <sys/param.h>
29 #include <sys/mount.h>
30 
31 #include <ufs/ufs/dinode.h>
32 #include <ufs/ffs/fs.h>
33 
34 #include <errno.h>
35 #include <ftw.h>
36 #include <libufs.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41 
42 void	find_inum(char *path);
43 void	usage(void);
44 int	compare_function(const char *, const struct stat *, int, struct FTW *);
45 int	find_snapshot(char *path);
46 
47 int verbose;
48 int cont_search;
49 uint32_t inode;
50 
51 int
52 main(int argc, char **argv)
53 {
54 	char *path;
55 	struct stat st;
56 	struct statfs *mntbuf;
57 	int all = 0, ch, done = 0, fscount, n;
58 
59 	while ((ch = getopt(argc, argv, "adv")) != -1) {
60 		switch (ch) {
61 		case 'a':
62 			all++;
63 			break;
64 		case 'd':
65 			/* continue to search when matching inode is found
66 			 * this feature is not documented */
67 			cont_search++;
68 			break;
69 		case 'v':
70 			verbose++;
71 			break;
72 		default:
73 			usage();
74 		}
75 	}
76 
77 	argc -= optind;
78 	argv += optind;
79 
80 	if ((all == 0 && argc != 1) || (all == 1 && argc > 0))
81 		usage();
82 
83 	if (!all) {
84 		path = *argv;
85 
86 		if (strrchr(path, '/') == NULL ||	/* is absolute path */
87 		    (stat(path, &st) == -1) || 		/* is it stat'able */
88 		    !(st.st_mode & S_IFDIR))  		/* is it a directory */
89 			usage();
90 	}
91 
92 	fscount = getmntinfo(&mntbuf, MNT_WAIT);
93 	for (n = 0; n < fscount; n++) {
94 		if (!strncmp(mntbuf[n].f_fstypename, "ufs", 3)) {
95 			if (all)
96 				path = mntbuf[n].f_mntonname;
97 			else if (strcmp(path, mntbuf[n].f_mntonname))
98 				continue;
99 
100 			find_snapshot(path);
101 			done++;
102 		}
103 	}
104 
105 	if (!done)
106 		usage();
107 
108 	return (0);
109 }
110 
111 int
112 find_snapshot(char *path)
113 {
114 	struct uufsd disk;
115 	int j, snapcount = 0;
116 
117 	if (ufs_disk_fillout(&disk, path) == -1)
118 		perror("ufs_disk_fillout");
119 
120 	if (verbose)
121 		printf("%s mounted on %s\n", disk.d_name, disk.d_fs.fs_fsmnt);
122 
123 	for (j = 0; j < FSMAXSNAP; j++) {
124 		if (disk.d_fs.fs_snapinum[j]) {
125 			inode = disk.d_fs.fs_snapinum[j];
126 			find_inum(path);
127 			snapcount++;
128 		}
129 	}
130 
131 	if (!snapcount && verbose)
132 		printf("\tno snapshots found\n");
133 
134 	return 0;
135 }
136 
137 int
138 compare_function(const char *path, const struct stat *st, int flags,
139 struct FTW * ftwv)
140 {
141 
142 	if (flags == FTW_F && st->st_ino == inode) {
143 		if (verbose)
144 			printf("\tsnapshot ");
145 		printf("%s", path);
146 		if (verbose)
147 			printf(" (inode %d)", st->st_ino);
148 		printf("\n");
149 		if (!cont_search)
150 			return (EEXIST);
151 	}
152 
153 	return (0);
154 }
155 
156 void
157 find_inum(char *path)
158 {
159 	int ret;
160 
161 	ret = nftw(path, compare_function, 1, FTW_PHYS|FTW_MOUNT);
162 	if (ret != EEXIST && ret != 0) {
163 		perror("ftw");
164 		exit(ret);
165 	}
166 }
167 
168 void
169 usage(void)
170 {
171 
172 	printf("usage: snapinfo [-v] -a\n");
173 	printf("       snapinfo [-v] mountpoint\n");
174 	exit(1);
175 }
176