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