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