1148197Smarks/*- 2148197Smarks * Copyright (c) 2005 Mark Santcroos <marks@freebsd.org> 3148197Smarks * 4148197Smarks * Redistribution and use in source and binary forms, with or without 5148197Smarks * modification, are permitted provided that the following conditions 6148197Smarks * are met: 7148197Smarks * 1. Redistributions of source code must retain the above copyright 8148197Smarks * notice, this list of conditions and the following disclaimer. 9148197Smarks * 2. Redistributions in binary form must reproduce the above copyright 10148197Smarks * notice, this list of conditions and the following disclaimer in the 11148197Smarks * documentation and/or other materials provided with the distribution. 12148197Smarks * 13148197Smarks * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14148197Smarks * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15148197Smarks * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16148197Smarks * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17148197Smarks * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18148197Smarks * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19148197Smarks * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20148197Smarks * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21148197Smarks * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22148197Smarks * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23148197Smarks * 24148197Smarks * $FreeBSD$ 25148197Smarks * 26148197Smarks */ 27148197Smarks 28148197Smarks#include <sys/param.h> 29148197Smarks#include <sys/mount.h> 30148197Smarks 31148197Smarks#include <ufs/ufs/dinode.h> 32148197Smarks#include <ufs/ffs/fs.h> 33148197Smarks 34148197Smarks#include <errno.h> 35148197Smarks#include <ftw.h> 36148197Smarks#include <libufs.h> 37148197Smarks#include <stdio.h> 38148197Smarks#include <stdlib.h> 39148197Smarks#include <string.h> 40148197Smarks#include <unistd.h> 41148197Smarks 42148197Smarksvoid find_inum(char *path); 43148197Smarksvoid usage(void); 44148197Smarksint compare_function(const char *, const struct stat *, int, struct FTW *); 45167626Spjdint find_snapshot(struct statfs *sfs); 46148197Smarks 47148197Smarksint verbose; 48148197Smarksint cont_search; 49148197Smarksuint32_t inode; 50148197Smarks 51148197Smarksint 52148197Smarksmain(int argc, char **argv) 53148197Smarks{ 54148197Smarks char *path; 55148197Smarks struct stat st; 56148197Smarks struct statfs *mntbuf; 57148197Smarks int all = 0, ch, done = 0, fscount, n; 58148197Smarks 59148197Smarks while ((ch = getopt(argc, argv, "adv")) != -1) { 60148197Smarks switch (ch) { 61148197Smarks case 'a': 62148197Smarks all++; 63148197Smarks break; 64148197Smarks case 'd': 65148197Smarks /* continue to search when matching inode is found 66148197Smarks * this feature is not documented */ 67148197Smarks cont_search++; 68148197Smarks break; 69148197Smarks case 'v': 70148197Smarks verbose++; 71148197Smarks break; 72148197Smarks default: 73148197Smarks usage(); 74148197Smarks } 75148197Smarks } 76148197Smarks 77148197Smarks argc -= optind; 78148197Smarks argv += optind; 79148197Smarks 80148197Smarks if ((all == 0 && argc != 1) || (all == 1 && argc > 0)) 81148197Smarks usage(); 82148197Smarks 83148197Smarks if (!all) { 84167633Spjd char resolved[PATH_MAX]; 85167633Spjd 86148197Smarks path = *argv; 87167633Spjd /* 88167633Spjd * mount(8) use realpath(3) before mounting file system, 89167633Spjd * so let's do the same with the given path. 90167633Spjd */ 91167633Spjd if (realpath(path, resolved) == NULL || /* can create full path */ 92167633Spjd stat(resolved, &st) == -1 || /* is it stat'able */ 93167633Spjd !S_ISDIR(st.st_mode)) { /* is it a directory */ 94148197Smarks usage(); 95167633Spjd } 96167633Spjd path = resolved; 97148197Smarks } 98148197Smarks 99148197Smarks fscount = getmntinfo(&mntbuf, MNT_WAIT); 100148197Smarks for (n = 0; n < fscount; n++) { 101148197Smarks if (!strncmp(mntbuf[n].f_fstypename, "ufs", 3)) { 102167626Spjd if (all || strcmp(path, mntbuf[n].f_mntonname) == 0) { 103167626Spjd find_snapshot(&mntbuf[n]); 104167626Spjd done++; 105167626Spjd } 106148197Smarks } 107148197Smarks } 108148197Smarks 109167626Spjd if (done == 0) 110148197Smarks usage(); 111148197Smarks 112148197Smarks return (0); 113148197Smarks} 114148197Smarks 115148197Smarksint 116167626Spjdfind_snapshot(struct statfs *sfs) 117148197Smarks{ 118148197Smarks struct uufsd disk; 119148197Smarks int j, snapcount = 0; 120148197Smarks 121167626Spjd if (ufs_disk_fillout(&disk, sfs->f_mntfromname) == -1) 122148197Smarks perror("ufs_disk_fillout"); 123148197Smarks 124148197Smarks if (verbose) 125148197Smarks printf("%s mounted on %s\n", disk.d_name, disk.d_fs.fs_fsmnt); 126148197Smarks 127148197Smarks for (j = 0; j < FSMAXSNAP; j++) { 128148197Smarks if (disk.d_fs.fs_snapinum[j]) { 129148197Smarks inode = disk.d_fs.fs_snapinum[j]; 130167626Spjd find_inum(sfs->f_mntonname); 131148197Smarks snapcount++; 132148197Smarks } 133148197Smarks } 134148197Smarks 135148197Smarks if (!snapcount && verbose) 136148197Smarks printf("\tno snapshots found\n"); 137148197Smarks 138148197Smarks return 0; 139148197Smarks} 140148197Smarks 141148197Smarksint 142148197Smarkscompare_function(const char *path, const struct stat *st, int flags, 143201388Sed struct FTW * ftwv __unused) 144148197Smarks{ 145148197Smarks 146148197Smarks if (flags == FTW_F && st->st_ino == inode) { 147148197Smarks if (verbose) 148148197Smarks printf("\tsnapshot "); 149148197Smarks printf("%s", path); 150148197Smarks if (verbose) 151148197Smarks printf(" (inode %d)", st->st_ino); 152148197Smarks printf("\n"); 153148197Smarks if (!cont_search) 154148197Smarks return (EEXIST); 155148197Smarks } 156148197Smarks 157148197Smarks return (0); 158148197Smarks} 159148197Smarks 160148197Smarksvoid 161148197Smarksfind_inum(char *path) 162148197Smarks{ 163148197Smarks int ret; 164148197Smarks 165148197Smarks ret = nftw(path, compare_function, 1, FTW_PHYS|FTW_MOUNT); 166148197Smarks if (ret != EEXIST && ret != 0) { 167148197Smarks perror("ftw"); 168148197Smarks exit(ret); 169148197Smarks } 170148197Smarks} 171148197Smarks 172148197Smarksvoid 173148197Smarksusage(void) 174148197Smarks{ 175148197Smarks 176148197Smarks printf("usage: snapinfo [-v] -a\n"); 177148197Smarks printf(" snapinfo [-v] mountpoint\n"); 178148197Smarks exit(1); 179148197Smarks} 180