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: releng/10.3/usr.sbin/snapinfo/snapinfo.c 241015 2012-09-27 23:31:19Z mdf $ 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> 37241015Smdf#include <stdint.h> 38148197Smarks#include <stdio.h> 39148197Smarks#include <stdlib.h> 40148197Smarks#include <string.h> 41148197Smarks#include <unistd.h> 42148197Smarks 43227260Sedstatic void find_inum(char *path); 44227260Sedstatic void usage(void); 45227260Sedstatic int compare_function(const char *, const struct stat *, 46227260Sed int, struct FTW *); 47227260Sedstatic int find_snapshot(struct statfs *sfs); 48148197Smarks 49227260Sedstatic int verbose; 50227260Sedstatic int cont_search; 51227260Sedstatic uint32_t inode; 52148197Smarks 53148197Smarksint 54148197Smarksmain(int argc, char **argv) 55148197Smarks{ 56148197Smarks char *path; 57148197Smarks struct stat st; 58148197Smarks struct statfs *mntbuf; 59148197Smarks int all = 0, ch, done = 0, fscount, n; 60148197Smarks 61148197Smarks while ((ch = getopt(argc, argv, "adv")) != -1) { 62148197Smarks switch (ch) { 63148197Smarks case 'a': 64148197Smarks all++; 65148197Smarks break; 66148197Smarks case 'd': 67148197Smarks /* continue to search when matching inode is found 68148197Smarks * this feature is not documented */ 69148197Smarks cont_search++; 70148197Smarks break; 71148197Smarks case 'v': 72148197Smarks verbose++; 73148197Smarks break; 74148197Smarks default: 75148197Smarks usage(); 76148197Smarks } 77148197Smarks } 78148197Smarks 79148197Smarks argc -= optind; 80148197Smarks argv += optind; 81148197Smarks 82148197Smarks if ((all == 0 && argc != 1) || (all == 1 && argc > 0)) 83148197Smarks usage(); 84148197Smarks 85148197Smarks if (!all) { 86167633Spjd char resolved[PATH_MAX]; 87167633Spjd 88148197Smarks path = *argv; 89167633Spjd /* 90167633Spjd * mount(8) use realpath(3) before mounting file system, 91167633Spjd * so let's do the same with the given path. 92167633Spjd */ 93167633Spjd if (realpath(path, resolved) == NULL || /* can create full path */ 94167633Spjd stat(resolved, &st) == -1 || /* is it stat'able */ 95167633Spjd !S_ISDIR(st.st_mode)) { /* is it a directory */ 96148197Smarks usage(); 97167633Spjd } 98167633Spjd path = resolved; 99148197Smarks } 100148197Smarks 101148197Smarks fscount = getmntinfo(&mntbuf, MNT_WAIT); 102148197Smarks for (n = 0; n < fscount; n++) { 103148197Smarks if (!strncmp(mntbuf[n].f_fstypename, "ufs", 3)) { 104167626Spjd if (all || strcmp(path, mntbuf[n].f_mntonname) == 0) { 105167626Spjd find_snapshot(&mntbuf[n]); 106167626Spjd done++; 107167626Spjd } 108148197Smarks } 109148197Smarks } 110148197Smarks 111167626Spjd if (done == 0) 112148197Smarks usage(); 113148197Smarks 114148197Smarks return (0); 115148197Smarks} 116148197Smarks 117227260Sedstatic int 118167626Spjdfind_snapshot(struct statfs *sfs) 119148197Smarks{ 120148197Smarks struct uufsd disk; 121148197Smarks int j, snapcount = 0; 122148197Smarks 123167626Spjd if (ufs_disk_fillout(&disk, sfs->f_mntfromname) == -1) 124148197Smarks perror("ufs_disk_fillout"); 125148197Smarks 126148197Smarks if (verbose) 127148197Smarks printf("%s mounted on %s\n", disk.d_name, disk.d_fs.fs_fsmnt); 128148197Smarks 129148197Smarks for (j = 0; j < FSMAXSNAP; j++) { 130148197Smarks if (disk.d_fs.fs_snapinum[j]) { 131148197Smarks inode = disk.d_fs.fs_snapinum[j]; 132167626Spjd find_inum(sfs->f_mntonname); 133148197Smarks snapcount++; 134148197Smarks } 135148197Smarks } 136148197Smarks 137148197Smarks if (!snapcount && verbose) 138148197Smarks printf("\tno snapshots found\n"); 139148197Smarks 140148197Smarks return 0; 141148197Smarks} 142148197Smarks 143227260Sedstatic int 144148197Smarkscompare_function(const char *path, const struct stat *st, int flags, 145201388Sed struct FTW * ftwv __unused) 146148197Smarks{ 147148197Smarks 148148197Smarks if (flags == FTW_F && st->st_ino == inode) { 149148197Smarks if (verbose) 150148197Smarks printf("\tsnapshot "); 151148197Smarks printf("%s", path); 152148197Smarks if (verbose) 153241015Smdf printf(" (inode %ju)", (uintmax_t)st->st_ino); 154148197Smarks printf("\n"); 155148197Smarks if (!cont_search) 156148197Smarks return (EEXIST); 157148197Smarks } 158148197Smarks 159148197Smarks return (0); 160148197Smarks} 161148197Smarks 162227260Sedstatic void 163148197Smarksfind_inum(char *path) 164148197Smarks{ 165148197Smarks int ret; 166148197Smarks 167148197Smarks ret = nftw(path, compare_function, 1, FTW_PHYS|FTW_MOUNT); 168148197Smarks if (ret != EEXIST && ret != 0) { 169148197Smarks perror("ftw"); 170148197Smarks exit(ret); 171148197Smarks } 172148197Smarks} 173148197Smarks 174227260Sedstatic void 175148197Smarksusage(void) 176148197Smarks{ 177148197Smarks 178148197Smarks printf("usage: snapinfo [-v] -a\n"); 179148197Smarks printf(" snapinfo [-v] mountpoint\n"); 180148197Smarks exit(1); 181148197Smarks} 182