Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / vol / volscan-main.c
1 /*
2 * Copyright 2013-2014, Sine Nomine Associates
3 * All Rights Reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
17 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <afsconfig.h>
30 #include <afs/param.h>
31
32 #include <roken.h>
33 #include <ctype.h>
34 #include <afs/cmd.h>
35 #include <afs/afsint.h>
36 #include <rx/rx_queue.h>
37 #include "nfs.h"
38 #include "ihandle.h"
39 #include "lock.h"
40 #include "vnode.h" /* for vSmall, vLarge */
41 #include "vol-info.h"
42
43 #ifndef AFS_NT40_ENV
44 #include "AFS_component_version_number.c"
45 #endif
46
47 static const char *progname = "volscan";
48
49 /* All columns names as a single string. */
50 #define c(x) #x " "
51 static char *ColumnNames = VOLSCAN_COLUMNS;
52 #undef c
53 #undef VOLSCAN_COLUMNS
54
55 /* Command line options */
56 typedef enum {
57 P_CHECKOUT,
58 P_PART,
59 P_VOLUMEID,
60 P_TYPE,
61 P_FIND,
62 P_MASK,
63 P_OUTPUT,
64 P_DELIM,
65 P_NOHEADING,
66 P_NOMAGIC,
67 } volscan_parm_t;
68
69 /**
70 * Process command line options and start scanning
71 *
72 * @param[in] as command syntax object
73 * @param[in] arock opaque object; not used
74 *
75 * @return error code
76 * @retval 0 success
77 * @retvol 1 failure
78 */
79 static int
80 VolScan(struct cmd_syndesc *as, void *arock)
81 {
82 int code;
83 struct cmd_item *ti;
84 VolumeId volumeId = 0;
85 char *partNameOrId = NULL;
86 int i;
87 struct VolInfoOpt *opt;
88
89 code = volinfo_Init(progname);
90 if (code) {
91 return code;
92 }
93 code = volinfo_Options(&opt);
94 if (code) {
95 return code;
96 }
97
98 opt->dumpInfo = 0; /* volscan mode */
99 if (as->parms[P_CHECKOUT].items) {
100 opt->checkout = 1;
101 }
102 if ((ti = as->parms[P_PART].items)) {
103 partNameOrId = ti->data;
104 }
105 if ((ti = as->parms[P_VOLUMEID].items)) {
106 volumeId = strtoul(ti->data, NULL, 10);
107 }
108 if (as->parms[P_NOHEADING].items) {
109 opt->printHeading = 0;
110 } else {
111 opt->printHeading = 1;
112 }
113 if (as->parms[P_NOMAGIC].items) {
114 opt->checkMagic = 0;
115 }
116 if ((ti = as->parms[P_DELIM].items)) {
117 strncpy(opt->columnDelim, ti->data, 15);
118 opt->columnDelim[15] = '\0';
119 }
120
121 /* Limit types of volumes to scan. */
122 if (!as->parms[P_TYPE].items) {
123 opt->scanVolType = (SCAN_RW | SCAN_RO | SCAN_BK);
124 } else {
125 opt->scanVolType = 0;
126 for (ti = as->parms[P_TYPE].items; ti; ti = ti->next) {
127 if (strcmp(ti->data, "rw") == 0) {
128 opt->scanVolType |= SCAN_RW;
129 } else if (strcmp(ti->data, "ro") == 0) {
130 opt->scanVolType |= SCAN_RO;
131 } else if (strcmp(ti->data, "bk") == 0) {
132 opt->scanVolType |= SCAN_BK;
133 } else {
134 fprintf(stderr, "%s: Unknown -type value: %s\n", progname,
135 ti->data);
136 return 1;
137 }
138 }
139 }
140
141 /* Limit types of vnodes to find (plus access entries) */
142 if (!as->parms[P_FIND].items) {
143 opt->findVnType = (FIND_FILE | FIND_DIR | FIND_MOUNT | FIND_SYMLINK);
144 } else {
145 opt->findVnType = 0;
146 for (ti = as->parms[P_FIND].items; ti; ti = ti->next) {
147 if (strcmp(ti->data, "file") == 0) {
148 opt->findVnType |= FIND_FILE;
149 } else if (strcmp(ti->data, "dir") == 0) {
150 opt->findVnType |= FIND_DIR;
151 } else if (strcmp(ti->data, "mount") == 0) {
152 opt->findVnType |= FIND_MOUNT;
153 } else if (strcmp(ti->data, "symlink") == 0) {
154 opt->findVnType |= FIND_SYMLINK;
155 } else if (strcmp(ti->data, "acl") == 0) {
156 opt->findVnType |= FIND_ACL;
157 } else {
158 fprintf(stderr, "%s: Unknown -find value: %s\n", progname,
159 ti->data);
160 return 1;
161 }
162 }
163 }
164
165 /* Show vnodes matching one of the mode masks */
166 for (i = 0, ti = as->parms[P_MASK].items; ti; i++, ti = ti->next) {
167 if (i >= (sizeof(opt->modeMask) / sizeof(*opt->modeMask))) {
168 fprintf(stderr, "Too many -mask values\n");
169 return -1;
170 }
171 opt->modeMask[i] = strtol(ti->data, NULL, 8);
172 if (!opt->modeMask[i]) {
173 fprintf(stderr, "Invalid -mask value: %s\n", ti->data);
174 return 1;
175 }
176 }
177
178 /* Set which columns to be printed. */
179 if (!as->parms[P_OUTPUT].items) {
180 volinfo_AddOutputColumn("host");
181 volinfo_AddOutputColumn("desc");
182 volinfo_AddOutputColumn("fid");
183 volinfo_AddOutputColumn("dv");
184 if (opt->findVnType & FIND_ACL) {
185 volinfo_AddOutputColumn("aid");
186 volinfo_AddOutputColumn("arights");
187 }
188 volinfo_AddOutputColumn("path");
189 } else {
190 for (ti = as->parms[P_OUTPUT].items; ti; ti = ti->next) {
191 if (volinfo_AddOutputColumn(ti->data) != 0) {;
192 fprintf(stderr, "%s: Unknown -output value: %s\n", progname,
193 ti->data);
194 return 1;
195 }
196 }
197 }
198
199 if (opt->findVnType & FIND_DIR) {
200 volinfo_AddVnodeHandler(vLarge, volinfo_PrintVnodeDetails, NULL);
201 }
202 if (opt->findVnType & (FIND_FILE | FIND_MOUNT | FIND_SYMLINK)) {
203 volinfo_AddVnodeHandler(vSmall, volinfo_PrintVnodeDetails, NULL);
204 }
205 if (opt->findVnType & FIND_ACL) {
206 volinfo_AddVnodeHandler(vLarge, volinfo_ScanAcl, NULL);
207 }
208
209 code = volinfo_ScanPartitions(opt, partNameOrId, volumeId);
210 if (opt) {
211 free(opt);
212 }
213 return code;
214 }
215 /**
216 * volscan program entry
217 */
218 int
219 main(int argc, char **argv)
220 {
221 afs_int32 code;
222 struct cmd_syndesc *ts;
223
224 ts = cmd_CreateSyntax(NULL, VolScan, NULL, 0,
225 "Print volume vnode information");
226
227 cmd_AddParmAtOffset(ts, P_CHECKOUT, "-checkout", CMD_FLAG, CMD_OPTIONAL,
228 "Checkout volumes from running fileserver");
229 cmd_AddParmAtOffset(ts, P_PART, "-partition", CMD_SINGLE, CMD_OPTIONAL,
230 "AFS partition name or id (default current partition)");
231 cmd_AddParmAtOffset(ts, P_VOLUMEID, "-volumeid", CMD_SINGLE, CMD_OPTIONAL,
232 "Volume id (-partition required)");
233 cmd_AddParmAtOffset(ts, P_TYPE, "-type", CMD_LIST, CMD_OPTIONAL,
234 "Volume types: rw, ro, bk");
235 cmd_AddParmAtOffset(ts, P_FIND, "-find", CMD_LIST, CMD_OPTIONAL,
236 "Objects to find: file, dir, mount, symlink, acl");
237 cmd_AddParmAtOffset(ts, P_MASK, "-mask", CMD_LIST, CMD_OPTIONAL,
238 "Unix mode mask (example: 06000)");
239 cmd_AddParmAtOffset(ts, P_OUTPUT, "-output", CMD_LIST, CMD_OPTIONAL,
240 ColumnNames);
241 cmd_AddParmAtOffset(ts, P_DELIM, "-delim", CMD_SINGLE, CMD_OPTIONAL,
242 "Output field delimiter");
243 cmd_AddParmAtOffset(ts, P_NOHEADING, "-noheading", CMD_FLAG, CMD_OPTIONAL,
244 "Do not print the heading line");
245 cmd_AddParmAtOffset(ts, P_NOMAGIC, "-ignore-magic", CMD_FLAG, CMD_OPTIONAL,
246 "Skip directory vnode magic checks when looking up paths.");
247
248 code = cmd_Dispatch(argc, argv);
249 return code;
250 }