Fix build failure.
[xfstests-dev.git] / dmapi / src / suite2 / src / test_hole.c
1 /*
2  * Copyright (c) 2000-2001 Silicon Graphics, Inc.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it would be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write the Free Software Foundation,
16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18
19 #include <sys/types.h>
20 #include <sys/stat.h>
21
22 #include <lib/hsm.h>
23 #include <lib/errtest.h>
24
25 #include <getopt.h>
26 #include <string.h>
27
28
29 /*---------------------------------------------------------------------------
30
31 Test program used to test the DMAPI function dm_punch_hole().  The
32 command line is:
33
34         test_hole [-v] [-s sid] pathname
35
36 where 
37    ls_path
38       is the path to a specific copy of ls, important only for its size
39    pathname 
40       is the path to the test filesystem
41    sid
42       is the session ID whose events you you are interested in.
43
44 ----------------------------------------------------------------------------*/
45
46 #ifndef linux
47 extern  char    *sys_errlist[];
48 #endif
49 extern  int     optind;
50 extern  char    *optarg;
51
52 char    *Progname;
53
54
55 static void
56 usage(void)
57 {
58         fprintf(stderr, "usage:\t%s [-v] [-s sid] ls_path directoryname\n",
59                 Progname);
60         exit(1);
61 }
62
63
64 int
65 main(
66         int     argc, 
67         char    **argv)
68 {
69         dm_sessid_t     sid = DM_NO_SESSION;
70         char            *pathname = NULL;
71         char            *ls_path = NULL;
72         dm_off_t        offset = 0;
73         dm_off_t        ex_off = 0;
74         dm_extent_t     extent[20];
75         u_int           nelem;
76         dm_size_t       length = 0;
77         void            *hanp;
78         size_t          hlen;
79         dm_token_t      test_token;
80         char            *name;
81         int             opt;
82         int             Vflag = 0;
83         char            filename[128];
84         char            command[128];
85         dm_off_t        roff;
86         dm_size_t       rlen;
87         dm_off_t        blocksize = 5; 
88         void            *test_vp;
89         struct stat    buf;
90         struct stat    checkbuf;
91
92
93         if (Progname = strrchr(argv[0], '/')) {
94                 Progname++;
95         } else {
96                 Progname = argv[0];
97         }
98
99         /* Crack and validate the command line options. */
100
101         while ((opt = getopt(argc, argv, "vs:")) != EOF) {
102                 switch (opt) {
103                 case 'v':
104                         Vflag++;
105                         break;
106                 case 's':
107                         sid = atol(optarg);
108                         break;
109                 case '?':
110                         usage();
111                 }
112         }
113         if (optind + 2 != argc)
114                 usage();
115         ls_path = argv[optind];
116         pathname = argv[optind+1];
117
118         if (dm_init_service(&name) == -1)  {
119                 fprintf(stdout, "Can't initialize the DMAPI\n");
120                 exit(1);
121         }
122         if (sid == DM_NO_SESSION)
123                 find_test_session(&sid);
124
125         /* Get the directory handle. */
126
127         if (dm_path_to_handle(pathname, &hanp, &hlen)) {
128                 fprintf(stdout, 
129                      "ERROR: can't get handle for directory %s\n", pathname);
130                 exit(1);
131         }
132         
133         printf("Hole test beginning...\n");
134         sprintf(filename, "%s/VeryLongUnlikelyFilename.HOLETEST", pathname);
135         sprintf(command, "cp %s %s \n", ls_path, filename); 
136         system(command);
137
138         if (dm_path_to_handle(filename, &hanp, &hlen)) {
139           fprintf(stdout, "can't get handle for %s\n; aborting test",
140                   filename);
141           
142           sprintf(command, "rm %s \n", filename); 
143           system(command);
144           fprintf(stdout, "\tHole test aborted.\n");
145           
146           dm_handle_free(hanp, hlen);
147           exit(1);
148         }
149    
150         /*   ## Get the block size using a length-1 probe. ##   */
151         dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, 1, 0,
152                       &blocksize, &rlen);
153         
154         if (blocksize==0) {
155           fprintf(stdout, "Error: block size appears to be 0!\n");
156           
157           sprintf(command, "rm %s \n", filename); 
158           system(command);
159           fprintf(stdout, "\tHole test aborted.\n");
160           
161           dm_handle_free(hanp, hlen);
162           exit(1);
163         }
164
165         /* Check that dm_probe_hole returns an extent from the next
166          * highest multiple of the block size, to the end of the file
167          */
168         for (offset = 0; offset < 29604; offset++) { 
169           if (dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, offset, length,
170                             &roff, &rlen)) {
171             fprintf(stdout, "dm_probe_hole failed on pass %lld (%s)\n",
172                     (long long)offset, ERR_NAME);
173           }
174           else {
175             if (rlen != 0) {
176                 fprintf(stdout, 
177                         "Error: hole did not extend to end of file!\n");
178             }
179             if (blocksize*(roff/blocksize) != roff) {
180                 fprintf(stdout,
181                         "Error: offset not a multiple of block size!\n");
182             }
183           }
184         }
185         
186         /* Be sure dm_punch_hole doesn't change the time stamp, 
187          * and verify that dm_get_allocinfo shows a hole
188          * followed by an extent to the end of the file.
189          */
190         for(offset = 28672; offset > 0; offset-=blocksize) {
191           if (stat(filename, &buf)){
192             fprintf(stdout, 
193                     "Error: unable to stat the test file; %s (1st)\n", 
194                     filename);
195             continue;
196           }
197           if (dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, offset, length,
198                             &roff, &rlen)) {
199             fprintf(stdout, "dm_probe_hole failed, %s\n",
200                     ERR_NAME);
201             continue;
202           }
203           if (roff != offset) {
204             fprintf(stdout, 
205                     "Error: presumed offset was not %lld.\n",
206                     (long long)(roff));
207           }
208           if (dm_punch_hole(sid, hanp, hlen, DM_NO_TOKEN,
209                             roff, length)) {
210             fprintf(stdout, "dm_punch_hole failed, %s\n",
211                     ERR_NAME);
212             continue;
213           }
214           if (stat(filename, &checkbuf)){
215             fprintf(stdout, 
216                     "Error: unable to stat the test file. (2nd)\n");
217             continue;
218           }
219           else {
220             /* COMPARE BUF AND CHECKBUF! */
221 #ifdef linux
222             if ((buf.st_atime == checkbuf.st_atime) &&
223                 (buf.st_mtime == checkbuf.st_mtime) &&
224                 (buf.st_ctime == checkbuf.st_ctime))
225 #else
226             if ((buf.st_atim.tv_sec == checkbuf.st_atim.tv_sec) &&
227                 (buf.st_atim.tv_nsec == checkbuf.st_atim.tv_nsec) &&
228                 (buf.st_mtim.tv_sec == checkbuf.st_mtim.tv_sec) &&
229                 (buf.st_mtim.tv_nsec == checkbuf.st_mtim.tv_nsec) &&
230                 (buf.st_ctim.tv_sec == checkbuf.st_ctim.tv_sec) &&
231                 (buf.st_ctim.tv_nsec == checkbuf.st_ctim.tv_nsec))
232 #endif
233            {
234               if (Vflag) {
235                 fprintf(stdout, 
236                         "\tTime stamp unchanged by hole from offset %lld.\n",
237                         (long long)(offset));
238               }
239             }
240             else {
241               fprintf(stdout,
242                       "Error: punch_hole changed file's time stamp.\n");
243             }
244             ex_off=0;
245             if ((dm_get_allocinfo(sid, hanp, hlen, DM_NO_TOKEN, 
246                                   &ex_off, 1, extent, &nelem) == 1) &&
247                 (extent->ex_type == DM_EXTENT_RES) &&
248                 (dm_get_allocinfo(sid, hanp, hlen, DM_NO_TOKEN,
249                                   &ex_off, 1, extent, &nelem) == 0) &&
250                 (extent->ex_type == DM_EXTENT_HOLE)) {
251               if (extent->ex_offset == roff){
252                 if (Vflag) {
253                   fprintf(stdout, "\tVerified hole at %lld\n", 
254                           (long long)(extent->ex_offset));
255                 }
256               }
257               else {
258                 fprintf(stdout, "\tError: get_allocinfo found hole at %lld\n",
259                         (long long)(extent->ex_offset));
260               }
261             }
262             else {
263                 fprintf(stdout, "\tError: get_allocinfo did not find an "
264                         "extent followed by a hole!\n");
265             }
266           }
267         }
268         /*------------------------*\
269         |*  ## Errno subtests ##  *|
270         \*------------------------*/
271         fprintf(stdout, "\t(beginning errno subtests...)\n");
272         /*---------------------------------------------------------*/
273         ERRTEST(E2BIG,
274                 "probe (from past EOF)",
275                 dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, 30000, length,
276                               &roff, &rlen))
277         /*---------------------------------------------------------*/
278 #if 0
279         PROBLEM: No error is produced.  
280         off+len >= filesize should produce E2BIG...
281
282         ERRTEST(E2BIG,
283                 "probe (to past EOF)",
284                 dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, 15000, 150000,
285                               &roff, &rlen))
286 #endif
287         /*---------------------------------------------------------*/
288         SHAREDTEST("probe", hanp, hlen, test_token, 
289                  dm_probe_hole(sid, hanp, hlen, test_token, 
290                                0, 0, &roff, &rlen)) 
291         /*---------------------------------------------------------*/
292         EXCLTEST("punch", hanp, hlen, test_token, 
293                    dm_punch_hole(sid, hanp, hlen, test_token, 0, 0)) 
294         /*---------------------------------------------------------*/
295         ERRTEST(EAGAIN,
296                 "punch",
297                 dm_punch_hole(sid, hanp, hlen, DM_NO_TOKEN,
298                               1, length))       
299         /*---------------------------------------------------------*/
300         if ((test_vp = handle_clone(hanp, hlen)) == NULL) {
301           fprintf(stderr, 
302                   "Cannot create a test handle (%s); skipping EBADF test\n",
303                   ERR_NAME);
304         }
305         else {
306          ((char *) test_vp)[hlen/2]++;
307           ERRTEST(EBADF,
308                   "probe",
309                   dm_probe_hole(sid, test_vp, hlen, DM_NO_TOKEN,
310                                 offset, length,
311                                 &roff, &rlen))
312           ERRTEST(EBADF,
313                   "punch",
314                   dm_punch_hole(sid, test_vp, hlen, DM_NO_TOKEN,
315                                 offset, length))
316         }
317         dm_handle_free(test_vp, hlen);
318         /*---------------------------------------------------------*/
319         ERRTEST(EFAULT,
320                 "probe (null handle)",
321                 dm_probe_hole(sid, 0, hlen, DM_NO_TOKEN, offset, length,
322                                 &roff, &rlen))
323         ERRTEST(EFAULT,
324                 "probe (bad rlen)",
325                 dm_probe_hole(sid, 0, hlen, DM_NO_TOKEN, offset, length,
326                                 &roff, (dm_size_t*)(-1000)))
327         ERRTEST(EFAULT,
328                 "probe (bad roff)",
329                 dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, offset, length,
330                                 (dm_off_t*)(-1000), &rlen))
331         /*---------------------------------------------------------*/
332         ERRTEST(EFAULT,
333                 "punch",
334                 dm_punch_hole(sid, 0, hlen, DM_NO_TOKEN, offset, length))
335         /*---------------------------------------------------------*/
336         ERRTEST(EINVAL,
337                 "probe (bad session)",
338                 dm_probe_hole(-100, hanp, hlen, DM_NO_TOKEN, offset, length,
339                                 &roff, &rlen))
340         /*---------------------------------------------------------*/
341         ERRTEST(EINVAL, 
342                 "probe (bad token)",
343                 dm_probe_hole(sid, hanp, hlen, 0, offset, length,
344                                 &roff, &rlen))
345         /*---------------------------------------------------------*/
346         ERRTEST(EINVAL, 
347                 "probe (bad token 2)",
348                 dm_probe_hole(sid, hanp, hlen, 0, offset, length,
349                                 &roff, &rlen))
350         /*---------------------------------------------------------*/
351         fprintf(stdout, "\t(errno subtests complete)\n");
352                 
353
354         sprintf(command, "rm %s \n", filename); 
355         system(command);
356         printf("Hole test complete.\n");
357
358         dm_handle_free(hanp, hlen);
359         exit(0);
360 }
361