Add DMAPI tests for dm_get_bulkall and dm_get_bulkattr
[xfstests-dev.git] / dmapi / src / suite2 / src / test_bulkattr.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 2, 2003: Dean Roehrich
19  *  - Adapted to test dm_get_bulkattr + dm_get_dmattr, 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 extern char     *optarg;
33 extern int       optind, optopt, opterr;
34 char            *Progname;
35
36 extern void     print_victim(void *, size_t, dm_off_t);
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*,
42                         size_t, 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]");
51         fprintf(stderr, " [-q] filesystem\n");
52 }
53
54 #define V_PRINT         0x01
55 #define V_VERBOSE       0x02
56
57
58 int
59 main(
60         int     argc, 
61         char    *argv[])
62 {
63         
64         int              c;
65         int              error;
66         char            *fsname;
67         dm_sessid_t      sid;
68         void            *fs_hanp;
69         size_t           fs_hlen;
70         dm_attrname_t   dmattr;
71         size_t          bufsz = 65536;
72         dm_attrname_t   *dmattrp = NULL;
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:vq")) != 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                         dmattrp = &dmattr;
87                         break;
88                 case 'b':
89                         bufsz = atoi(optarg);
90                         break;
91                 case 'v':
92                         verbose |= V_VERBOSE;
93                         break;
94
95                 case 'q':
96                         verbose &= ~V_PRINT;
97                         break;
98
99                 case '?':
100                 default:
101                         usage(Progname);
102                         exit(1);
103                 }
104         }
105         if (optind >= argc) {
106                 usage(Progname);
107                 exit(1);
108         }
109
110         fsname = argv[optind];
111
112         /*
113          * Now we have our filesystem name and possibly a size threshold
114          * to look for. Init the dmapi, and get a filesystem handle so
115          * we can scan the filesystem
116          */
117         error = setup_dmapi(&sid);
118         if (error) 
119                 exit(1);
120         
121         if (dm_path_to_fshandle(fsname, &fs_hanp, &fs_hlen) == -1) {
122                 errno_msg("Can't get filesystem handle");
123                 exit(1);
124         }
125
126
127
128         /*
129          * Get the attributes of all files in the filesystem
130          */
131         error = scan_fs(sid, fs_hanp, fs_hlen, dmattrp, bufsz, verbose);
132         if (error) 
133                 exit(1);
134         
135
136         /*
137          * We're done, so we can shut down our session.
138          */
139         if (dm_destroy_session(sid) == -1) {
140                 errno_msg("Can't close session");
141                 exit(1);
142         }
143
144         return(0);
145
146 }
147
148 void
149 my_print_victim(
150         dm_sessid_t     sid,
151         void            *hanp,
152         size_t          hlen,
153         dm_attrname_t   *dm_attrp,
154         int             verbose)
155 {
156         size_t  rlen;
157         size_t  buflen = 10000;
158         char    buf[buflen];
159
160         if (hlen > HANDLE_LEN) {
161                 if (verbose & V_PRINT)
162                         printf("-- invalid length --\n");
163         }
164         else {
165                 char handle_str[HANDLE_STR];
166                 if (verbose & V_PRINT) {
167                         printf("%d\t", hlen);
168                         hantoa(hanp, hlen, handle_str);
169                         printf("%s ", handle_str);
170                 }
171
172                 if (dm_get_dmattr(sid, hanp, hlen, DM_NO_TOKEN, dm_attrp,
173                                   buflen, (char*)buf, &rlen)) {
174                         if (verbose & V_PRINT) {
175                                 if( errno == E2BIG ){
176                                         printf("E2BIG\n");
177                                 }
178                                 else if (errno == ENOMEM){
179                                         printf("ENOMEM\n");
180                                 }
181                                 else {
182                                         printf("<none>\n");
183                                 }
184                         }
185                 }
186                 else if (verbose & V_PRINT) {
187                         if( isalpha(buf[0]) )
188                                 printf("(%s)\n", buf);
189                         else
190                                 printf("<len=%d>\n",rlen);
191                 }
192         }
193 }
194
195 /*
196  * Get the attributes for all the files in a filesystem in bulk,
197  * and print out the handles and sizes of any that meet our target
198  * criteria.
199  *
200  * We are not interested in file names; if we were, then we would 
201  * have to do a dm_get_dirattrs() on each directroy, then use 
202  * dm_handle_to_path() to get the pathname. 
203  */
204 int
205 scan_fs(
206         dm_sessid_t      sid, 
207         void            *fs_hanp, 
208         size_t           fs_hlen, 
209         dm_attrname_t   *dmattrp,
210         size_t          buflen,
211         int             verbose)
212 {
213         u_int            mask;                  /* attributes to scan for */
214         dm_stat_t       *dm_statbuf, *sbuf;     /* attributes buffer */
215         dm_attrloc_t     locp;                  /* opaque location in fs */
216         size_t           rlenp;                 /* ret length of stat info */
217         void            *hanp;                  /* file handle */
218         size_t           hlen;                  /* file handle */
219         int              more;                  /* loop terminator */
220         int              error; 
221
222
223 #ifdef  VERITAS_21
224         if (buflen > 65536)
225                 buflen = 65536;
226 #endif
227         dm_statbuf = (dm_stat_t *)calloc(1, buflen);
228         if (dm_statbuf == NULL)  {
229                 err_msg("Can't get memory for stat buffer");
230                 return(1);
231         }
232
233
234         /*
235          * Initialize the offset opaque offset cookie that
236          * we use in successive calls to dm_get_bulkattr()
237          */
238         error = dm_init_attrloc(sid, fs_hanp, fs_hlen, DM_NO_TOKEN, &locp);
239         if (error == -1) {
240                 errno_msg("%s/%d: Can't initialize offset cookie (%d)", __FILE__, __LINE__, errno);
241                 free(dm_statbuf);
242                 return(1);
243         }
244
245         /*
246          * Set our stat mask so that we'll only get the normal stat(2)
247          * info and the file's handle
248          */
249         mask = DM_AT_HANDLE | DM_AT_STAT;
250         do {
251                 more = dm_get_bulkattr(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
252                                        mask, &locp, buflen, dm_statbuf, &rlenp);
253                 if (verbose & V_VERBOSE)
254                         fprintf(stderr, "BULKATTR more=%d, rlen=%d\n", more, rlenp);
255                 if (more == -1) {
256                         errno_msg("%s/%d: Can't get bulkattr for filesystem", __FILE__, __LINE__, errno);
257                         break;
258                 }
259
260                 /*
261                  * Walk through the stat buffer and pull out files 
262                  * that are of interest
263                  *
264                  * The stat buffer is variable length, so we must
265                  * use the DM_STEP_TO_NEXT macro to access each individual
266                  * dm_stat_t structure in the returned buffer.
267                  */
268                 sbuf = dm_statbuf;
269                 while (sbuf != NULL) {
270                         if (S_ISREG(sbuf->dt_mode)) {
271                                 hanp = DM_GET_VALUE(sbuf, dt_handle, void *);
272                                 hlen = DM_GET_LEN(sbuf, dt_handle);
273
274                                 if (dmattrp) {
275                                         my_print_victim(sid, hanp, hlen,
276                                                         dmattrp, verbose);
277                                 }
278                                 else if (verbose & V_PRINT){
279                                         print_victim(hanp, hlen, sbuf->dt_size);
280                                 }
281                         }
282                         sbuf = DM_STEP_TO_NEXT(sbuf, dm_stat_t *);
283                 }
284         } while (more == 1);
285
286         free(dm_statbuf);
287         if (more == -1) 
288                 return(1);
289
290         return(0);
291 }
292