Make the dm_bulkall test output match that of the dm_bulkattr test
[xfstests-dev.git] / dmapi / src / suite2 / src / test_bulkall.c
1 /*
2  * This code was written by Peter Lawthers, and placed in the public
3  * domain for use by DMAPI implementors and app writers.
4  *
5  * Standard disclaimer:
6  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
7  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
8  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
10  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
11  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
12  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
15  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
16  * SUCH DAMAGE.
17  *
18  * October 1, 2003: Dean Roehrich
19  *  - Adapted to test dm_get_bulkall, from migfind.c.
20  */
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <limits.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <sys/stat.h>
27
28 #include <lib/hsm.h>
29
30 #include <getopt.h>
31
32
33 extern char     *optarg;
34 extern int       optind, optopt, opterr;
35 char            *Progname;
36
37 extern void     err_msg(char *, ...);
38 extern void     errno_msg(char *, ...);
39
40 int             setup_dmapi(dm_sessid_t *);
41 int             scan_fs(dm_sessid_t, void *, size_t, dm_attrname_t*, size_t,
42                         int, int);
43 void            usage(char *);
44
45 void
46 usage(
47         char *prog)
48 {
49         fprintf(stderr, "Usage: %s ", prog);
50         fprintf(stderr, " <-a attrname> [-b bufsz] [-v] [-q]");
51         fprintf(stderr, " filesystem\n");
52 }
53
54 #define V_PRINT         0x01
55 #define V_VERBOSE       0x02
56
57 int
58 main(
59         int     argc, 
60         char    *argv[])
61 {
62         
63         int              c;
64         int              error;
65         char            *fsname;
66         dm_sessid_t      sid;
67         void            *fs_hanp;
68         size_t           fs_hlen;
69         dm_attrname_t   dmattr;
70         size_t          bufsz = 65536;
71         dm_size_t       ret;
72         int             extras = 0;
73         int             verbose = V_PRINT;
74
75         Progname = argv[0];
76         memset(&dmattr, 0, sizeof(dmattr));
77
78         while ((c = getopt(argc, argv, "a:b:evq")) != EOF) {
79                 switch (c) {
80                 case 'a':
81                         if (strlen(optarg) > (DM_ATTR_NAME_SIZE-1)){
82                                 printf("Arg for -a too long\n");
83                                 exit(1);
84                         }
85                         strcpy((char*)dmattr.an_chars, optarg);
86                         break;
87                 case 'b':
88                         bufsz = atoi(optarg);
89                         break;
90                 case 'e':
91                         extras++;
92                         break;
93                 case 'v':
94                         verbose |= V_VERBOSE;
95                         break;
96                 case 'q':
97                         verbose &= ~V_PRINT;
98                         break;
99                 case '?':
100                 default:
101                         usage(Progname);
102                         exit(1);
103                 }
104         }
105         if (optind >= argc) {
106                 usage(Progname);
107                 exit(1);
108         }
109         if (dmattr.an_chars[0] == '\0') {
110                 usage(Progname);
111                 exit(1);
112         }
113         fsname = argv[optind];
114
115         /*
116          * Now we have our filesystem name and possibly a size threshold
117          * to look for. Init the dmapi, and get a filesystem handle so
118          * we can scan the filesystem
119          */
120         error = setup_dmapi(&sid);
121         if (error) 
122                 exit(1);
123         
124         if (dm_path_to_fshandle(fsname, &fs_hanp, &fs_hlen) == -1) {
125                 errno_msg("Can't get filesystem handle");
126                 exit(1);
127         }
128
129
130         if( dm_get_config(fs_hanp, fs_hlen, DM_CONFIG_BULKALL, &ret) ||
131            (ret != DM_TRUE)) {
132                 printf("Kernel does not have dm_get_bulkall\n");
133                 exit(1);
134         }
135
136         /*
137          * Get the attributes of all files in the filesystem
138          */
139         error = scan_fs(sid, fs_hanp, fs_hlen, &dmattr, bufsz, extras, verbose);
140         if (error) 
141                 exit(1);
142         
143
144         /*
145          * We're done, so we can shut down our session.
146          */
147         if (dm_destroy_session(sid) == -1) {
148                 errno_msg("Can't close session");
149                 exit(1);
150         }
151
152         return(0);
153
154 }
155
156 void
157 my_print_victim(
158         void            *hanp,
159         size_t          hlen,
160         dm_xstat_t      *xbuf,
161         dm_stat_t       *sbuf,
162         int             extras,
163         int             verbose)
164 {
165         u_int            attrlen;
166         char            *attrval;
167
168         if (hlen > HANDLE_LEN) {
169                 if (verbose & V_PRINT)
170                         printf("-- invalid length --\n");
171         }
172         else {
173                 char handle_str[HANDLE_STR];
174                 if (verbose & V_PRINT) {
175                         printf("%d\t", hlen);
176                         hantoa(hanp, hlen, handle_str);
177                         printf("%s ", handle_str);
178                         if (extras) {
179                                 printf("size=%lld ",
180                                        (int64_t)sbuf->dt_size);
181                                 printf("ino=%lld ",
182                                        (int64_t)sbuf->dt_ino);
183                         }
184                 }
185
186                 attrval = DM_GET_VALUE(xbuf,
187                                   dx_attrdata, char*);
188                 attrlen = DM_GET_LEN(xbuf,
189                                   dx_attrdata);
190                 /* Hmmm, a hole in the dmapi spec.
191                  * No way to have a null pointer
192                  * for the value.  No way to
193                  * distinguish between a zero-length
194                  * attribute value and not finding
195                  * the attribute in the first place.
196                  *
197                  * Punt.  Since I cannot get a null
198                  * pointer for the value, let's look
199                  * at the length.  If it's zero,
200                  * we'll say the attribute was
201                  * not found.
202                  */
203                 if (verbose & V_PRINT) {
204                         if (attrlen) {
205                                 if (isalpha(attrval[0]) )
206                                         printf("(%s)\n", attrval);
207                                 else
208                                         printf("<len=%d>\n", attrlen);
209                         }
210                         else {
211                                 printf("<none>\n");
212                         }
213                 }
214         }
215 }
216
217 /*
218  * Get the attributes for all the files in a filesystem in bulk,
219  * including the specified dmattr,
220  * and print out the handles and dmattr values.
221  */
222 int
223 scan_fs(
224         dm_sessid_t      sid, 
225         void            *fs_hanp, 
226         size_t           fs_hlen, 
227         dm_attrname_t   *dmattr,
228         size_t          buflen,
229         int             extras,
230         int             verbose)
231 {
232         u_int            mask;                  /* attributes to scan for */
233         dm_xstat_t      *dm_xstatbuf, *xbuf;    /* attributes buffer */
234         dm_stat_t       *sbuf;
235         dm_attrloc_t     locp;                  /* opaque location in fs */
236         size_t           rlenp;                 /* ret length of stat info */
237         void            *hanp;                  /* file handle */
238         size_t           hlen;                  /* file handle */
239         int              more;                  /* loop terminator */
240         int              error; 
241
242 #ifdef  VERITAS_21
243         if (buflen > 65536)
244                 buflen= 65536;
245 #endif
246         dm_xstatbuf = (dm_xstat_t *)calloc(1, buflen);
247         if (dm_xstatbuf == NULL)  {
248                 err_msg("Can't get memory for stat buffer");
249                 return(1);
250         }
251
252
253         /*
254          * Initialize the offset opaque offset cookie that
255          * we use in successive calls to dm_get_bulkattr()
256          */
257         error = dm_init_attrloc(sid, fs_hanp, fs_hlen, DM_NO_TOKEN, &locp);
258         if (error == -1) {
259                 errno_msg("%s/%d: Can't initialize offset cookie (%d)", __FILE__, __LINE__, errno);
260                 free(dm_xstatbuf);
261                 return(1);
262         }
263
264         /*
265          * Set our stat mask so that we'll only get the normal stat(2)
266          * info and the file's handle
267          */
268         mask = DM_AT_HANDLE | DM_AT_STAT;
269         do {
270                 more = dm_get_bulkall(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
271                                       mask, dmattr, &locp, buflen,
272                                       dm_xstatbuf, &rlenp);
273                 if (verbose & V_VERBOSE)
274                         fprintf(stderr, "BULKALL more=%d, rlen=%d\n", more, rlenp);
275                 if (more == -1) {
276                         errno_msg("%s/%d: Can't get bulkall for filesystem", __FILE__, __LINE__, errno);
277                         break;
278                 }
279
280                 /*
281                  * Walk through the stat buffer and pull out files 
282                  * that are of interest
283                  *
284                  * The stat buffer is variable length, so we must
285                  * use the DM_STEP_TO_NEXT macro to access each individual
286                  * dm_xstat_t structure in the returned buffer.
287                  */
288                 xbuf = dm_xstatbuf;
289                 while (xbuf != NULL) {
290                         sbuf = &xbuf->dx_statinfo;
291                         if (S_ISREG(sbuf->dt_mode)) {
292                                 hanp = DM_GET_VALUE(sbuf, dt_handle, void *);
293                                 hlen = DM_GET_LEN(sbuf, dt_handle);
294
295                                 my_print_victim(hanp, hlen, xbuf, sbuf,
296                                                 extras, verbose);
297                         }
298                         /* The sbuf has the offset to the next xbuf */
299                         xbuf = DM_STEP_TO_NEXT(sbuf, dm_xstat_t *);
300                 }
301         } while (more == 1);
302
303         free(dm_xstatbuf);
304         if (more == -1) 
305                 return(1);
306
307         return(0);
308 }
309