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 } 182