]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - usr.sbin/snapinfo/snapinfo.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / usr.sbin / snapinfo / snapinfo.c
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 <stdint.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <unistd.h>
42
43 static void     find_inum(char *path);
44 static void     usage(void);
45 static int      compare_function(const char *, const struct stat *,
46                     int, struct FTW *);
47 static int      find_snapshot(struct statfs *sfs);
48
49 static int      verbose;
50 static int      cont_search;
51 static uint32_t inode;
52
53 int
54 main(int argc, char **argv)
55 {
56         char *path;
57         struct stat st;
58         struct statfs *mntbuf;
59         int all = 0, ch, done = 0, fscount, n;
60
61         while ((ch = getopt(argc, argv, "adv")) != -1) {
62                 switch (ch) {
63                 case 'a':
64                         all++;
65                         break;
66                 case 'd':
67                         /* continue to search when matching inode is found 
68                          * this feature is not documented */
69                         cont_search++;
70                         break;
71                 case 'v':
72                         verbose++;
73                         break;
74                 default:
75                         usage();
76                 }
77         }
78
79         argc -= optind;
80         argv += optind;
81
82         if ((all == 0 && argc != 1) || (all == 1 && argc > 0))
83                 usage();
84
85         if (!all) {
86                 char resolved[PATH_MAX];
87
88                 path = *argv;
89                 /*
90                  * mount(8) use realpath(3) before mounting file system,
91                  * so let's do the same with the given path.
92                  */
93                 if (realpath(path, resolved) == NULL || /* can create full path */
94                     stat(resolved, &st) == -1 ||        /* is it stat'able */
95                     !S_ISDIR(st.st_mode)) {             /* is it a directory */
96                         usage();
97                 }
98                 path = resolved;
99         }
100
101         fscount = getmntinfo(&mntbuf, MNT_WAIT);
102         for (n = 0; n < fscount; n++) {
103                 if (!strncmp(mntbuf[n].f_fstypename, "ufs", 3)) {
104                         if (all || strcmp(path, mntbuf[n].f_mntonname) == 0) {
105                                 find_snapshot(&mntbuf[n]);
106                                 done++;
107                         }
108                 }
109         }
110
111         if (done == 0)
112                 usage();
113
114         return (0);
115 }
116
117 static int
118 find_snapshot(struct statfs *sfs)
119 {
120         struct uufsd disk;
121         int j, snapcount = 0;
122
123         if (ufs_disk_fillout(&disk, sfs->f_mntfromname) == -1)
124                 perror("ufs_disk_fillout");
125
126         if (verbose)
127                 printf("%s mounted on %s\n", disk.d_name, disk.d_fs.fs_fsmnt);
128
129         for (j = 0; j < FSMAXSNAP; j++) {
130                 if (disk.d_fs.fs_snapinum[j]) {
131                         inode = disk.d_fs.fs_snapinum[j];
132                         find_inum(sfs->f_mntonname);
133                         snapcount++;
134                 }
135         }
136
137         if (!snapcount && verbose)
138                 printf("\tno snapshots found\n");
139                                 
140         return 0;
141 }
142
143 static int
144 compare_function(const char *path, const struct stat *st, int flags,
145     struct FTW * ftwv __unused)
146 {
147
148         if (flags == FTW_F && st->st_ino == inode) {
149                 if (verbose)
150                         printf("\tsnapshot ");
151                 printf("%s", path);
152                 if (verbose)
153                         printf(" (inode %ju)", (uintmax_t)st->st_ino);
154                 printf("\n");
155                 if (!cont_search)
156                         return (EEXIST);
157         }
158
159         return (0);
160 }
161
162 static void
163 find_inum(char *path)
164 {
165         int ret;
166
167         ret = nftw(path, compare_function, 1, FTW_PHYS|FTW_MOUNT);
168         if (ret != EEXIST && ret != 0) {
169                 perror("ftw");
170                 exit(ret);
171         }
172 }
173
174 static void
175 usage(void)
176 {
177
178         printf("usage: snapinfo [-v] -a\n");
179         printf("       snapinfo [-v] mountpoint\n");
180         exit(1);
181 }