functionality-test-suite-20020114
[openafs.git] / src / tests / fs_lib.c
1 /*
2  * Copyright (c) 1998 - 2001 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  * 
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 
17  * 3. Neither the name of the Institute nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  * 
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <fcntl.h>
44 #include <unistd.h>
45 #include <dirent.h>
46 #include <errno.h>
47 #include <netinet/in.h>
48 #include <afs/stds.h>
49 #include <afs/vice.h>
50 #include <afs/venus.h>
51 #include <afs/afsint.h>
52 #include <afs/auth.h>
53 #include <afs/cellconfig.h>
54 #include <afs/cmd.h>
55
56 enum { PIOCTL_MAXSIZE = 2000 };
57
58 struct VenusFid {
59   afs_int32 Cell;
60   struct AFSFid Fid;
61 };
62
63 /*
64  * fs_getfid, the the `fid' that `path' points on. 
65  */
66
67 int
68 fs_getfid(char *path, struct VenusFid *fid)
69 {
70     struct ViceIoctl a_params;
71
72     if (path == NULL || fid == NULL)
73         return EINVAL;
74
75     a_params.in_size=0;
76     a_params.out_size=sizeof(struct VenusFid);
77     a_params.in=NULL;
78     a_params.out=(void*) fid;
79     
80     if(pioctl(path,VIOCGETFID,&a_params,1) == -1)
81         return errno;
82
83     return 0;
84 }
85
86 /*
87  * Do nothing
88  */
89
90 int
91 fs_nop(void)
92 {
93     struct ViceIoctl a_params;
94
95     a_params.in_size=0;
96     a_params.out_size=0;
97     a_params.in=NULL;
98     a_params.out=NULL;
99     
100     if (pioctl(NULL,VIOCNOP,&a_params,1) == -1) 
101         return errno;
102
103     return 0;
104 }
105
106 /*
107  * Get the `cell' that the `path' ends up in
108  */
109
110 int
111 fs_getfilecellname(char *path, char *cell, size_t len)
112 {
113     struct ViceIoctl a_params;
114
115     a_params.in_size=0;
116     a_params.out_size=len;
117     a_params.in=NULL;
118     a_params.out=cell;
119     
120     if (pioctl(path,VIOC_FILE_CELL_NAME,&a_params,1) == -1) 
121         return errno;
122
123     return 0;
124 }
125
126 /*
127  * set the level of crypt
128  */
129
130 #ifdef VIOC_SETRXKCRYPT
131 int
132 fs_setcrypt (u_int32_t n)
133 {
134     struct ViceIoctl    a_params;
135
136     a_params.in_size  = sizeof(n);
137     a_params.out_size = 0;
138     a_params.in       = (char *)&n;
139     a_params.out      = NULL;
140
141     if (pioctl (NULL, VIOC_SETRXKCRYPT, &a_params, 0) == -1)
142         return errno;
143
144     return 0;
145 }
146 #endif
147
148 /*
149  * get currernt level of crypt
150  */
151
152 #ifdef VIOC_GETRXKCRYPT
153 int
154 fs_getcrypt (u_int32_t *level)
155 {
156     struct ViceIoctl    a_params;
157
158     a_params.in_size  = 0;
159     a_params.out_size = sizeof(*level);
160     a_params.in       = NULL;
161     a_params.out      = (char *) level;
162
163     if (pioctl (NULL, VIOC_GETRXKCRYPT, &a_params, 0) == -1) 
164         return errno;
165     
166     return 0;
167 }
168 #endif
169
170 /*
171  * get and set the connect-mode
172  */
173
174 #ifdef VIOCCONNECTMODE
175 int
176 fs_connect(int32_t type, int32_t *flags)
177 {
178     struct ViceIoctl   a_params;
179
180     a_params.in_size = sizeof(type);
181     a_params.out_size = sizeof (int32_t);
182     a_params.in = (char *) &type;
183     a_params.out = (char *) flags;
184
185     if (pioctl (NULL, VIOCCONNECTMODE, &a_params, 0) == -1)
186         return errno;
187
188     return 0;
189 }
190 #endif
191
192 /*
193  *
194  */
195
196 #ifdef VIOC_FPRIOSTATUS
197 int
198 fs_setfprio(struct VenusFid fid, int16_t prio)
199 {
200     struct ViceIoctl   a_params;
201     struct vioc_fprio  fprio;
202
203     fprio.cmd = FPRIO_SET;
204     fprio.Cell = fid.Cell;
205     fprio.Volume = fid.fid.Volume;
206     fprio.Vnode = fid.fid.Vnode;
207     fprio.Unique = fid.fid.Unique;
208     fprio.prio = prio;
209
210     a_params.in_size = sizeof(fprio);
211     a_params.out_size = 0;
212     a_params.in = (char *) &fprio;
213     a_params.out = NULL;
214
215     if (pioctl (NULL, VIOC_FPRIOSTATUS , &a_params, 0) == -1)
216         return errno;
217
218     return 0;
219 }
220 #endif
221
222 #ifdef VIOC_FPRIOSTATUS
223 int
224 fs_getfprio(struct VenusFid fid, int16_t *prio)
225 {
226     struct ViceIoctl   a_params;
227     struct vioc_fprio  fprio;
228
229     fprio.cmd = FPRIO_GET;
230     fprio.Cell = fid.Cell;
231     fprio.Volume = fid.fid.Volume;
232     fprio.Vnode = fid.fid.Vnode;
233     fprio.Unique = fid.fid.Unique;
234
235     a_params.in_size = sizeof(fprio);
236     a_params.out_size = sizeof(*prio);
237     a_params.in = (char *) &fprio;
238     a_params.out = (char *) prio;
239
240     if (pioctl (NULL, VIOC_FPRIOSTATUS , &a_params, 0) == -1)
241         return errno;
242
243     return 0;
244 }
245 #endif
246
247 #ifdef VIOC_FPRIOSTATUS
248 int
249 fs_setmaxfprio(int16_t maxprio)
250 {
251     struct ViceIoctl   a_params;
252     struct vioc_fprio  fprio;
253
254     fprio.cmd = FPRIO_SETMAX;
255     fprio.prio = maxprio;
256
257     a_params.in_size = sizeof(fprio);
258     a_params.out_size = 0;
259     a_params.in = (char *) &fprio;
260     a_params.out = NULL;
261
262     if (pioctl (NULL, VIOC_FPRIOSTATUS , &a_params, 0) == -1)
263         return errno;
264
265     return 0;
266 }
267 #endif
268
269 #ifdef VIOC_FPRIOSTATUS
270 int
271 fs_getmaxfprio(int16_t *maxprio)
272 {
273     struct ViceIoctl   a_params;
274     struct vioc_fprio  fprio;
275
276     fprio.cmd = FPRIO_GETMAX;
277
278     a_params.in_size = sizeof(fprio);
279     a_params.out_size = sizeof(*maxprio);
280     a_params.in = (char *) &fprio;
281     a_params.out = (char *) maxprio;
282
283     if (pioctl (NULL, VIOC_FPRIOSTATUS , &a_params, 0) == -1)
284         return errno;
285
286     return 0;
287 }
288 #endif
289
290 /*
291  *
292  */
293
294 #ifdef VIOCGETCACHEPARAMS
295 int
296 fs_getfilecachestats(u_int32_t *max_bytes,
297                      u_int32_t *used_bytes,
298                      u_int32_t *max_vnodes,
299                      u_int32_t *used_vnodes)
300 {
301     u_int32_t parms[16];
302     struct ViceIoctl a_params;
303
304     a_params.in_size  = 0;
305     a_params.out_size = sizeof(parms);
306     a_params.in       = NULL;
307     a_params.out      = (char *) parms;
308
309     memset (parms, 0, sizeof(parms));
310
311     if (pioctl (NULL, VIOCGETCACHEPARAMS , &a_params, 0) == -1)
312         return errno;
313
314     /* param[0] and param[1] send maxbytes and usedbytes in kbytes */
315
316     if (max_vnodes)
317         *max_vnodes = parms[2];
318     if (used_vnodes)
319         *used_vnodes = parms[3];
320     if (max_bytes)
321         *max_bytes = parms[4];
322     if (used_bytes)
323         *used_bytes = parms[5];
324
325     return 0;
326 }
327 #endif
328
329 /*
330  *
331  */
332
333 #ifdef VIOC_AVIATOR
334 int
335 fs_getaviatorstats(u_int32_t *max_workers,
336                    u_int32_t *used_workers)
337 {
338     u_int32_t parms[16];
339     struct ViceIoctl a_params;
340
341     a_params.in_size = 0;
342     a_params.out_size = sizeof(parms);
343     a_params.in = NULL;
344     a_params.out = (char *) parms;
345
346     if (pioctl (NULL, VIOC_AVIATOR , &a_params, 0) == -1)
347         return errno;
348
349     if (max_workers)
350         *max_workers = parms[0];
351     if (used_workers)
352         *used_workers = parms[1];
353
354     return 0;
355 }
356 #endif
357
358 /*
359  *
360  */
361
362 #ifdef VIOC_GCPAGS
363 int
364 fs_gcpags(void)
365 {
366     struct ViceIoctl a_params;
367
368     a_params.in_size  = 0;
369     a_params.out_size = 0;
370     a_params.in       = NULL;
371     a_params.out      = NULL;
372
373
374     if (pioctl(NULL, VIOC_GCPAGS, &a_params, 0) != 0)
375         return errno;
376     
377     return 0;
378 }
379 #endif
380
381 /*
382  *
383  */
384
385 #ifdef VIOC_CALCULATE_CACHE
386 int
387 fs_calculate_cache(u_int32_t *calculated,
388                    u_int32_t *usedbytes)
389 {
390     u_int32_t parms[16];
391     struct ViceIoctl a_params;
392
393     a_params.in_size = 0;
394     a_params.out_size = sizeof(parms);
395     a_params.in = NULL;
396     a_params.out = (char *) parms;
397
398     if (pioctl (NULL, VIOC_CALCULATE_CACHE , &a_params, 0) == -1)
399         return errno;
400
401     if (calculated)
402         *calculated = parms[0];
403     if (usedbytes)
404         *usedbytes = parms[1];
405
406     return 0;
407 }
408 #endif
409
410 /*
411  *
412  */
413
414 #ifdef VIOC_BREAKCALLBACK
415 int
416 fs_invalidate (const char *path)
417 {
418     struct ViceIoctl   a_params;
419
420     a_params.in_size  = 0;
421     a_params.out_size = 0;
422     a_params.in       = NULL;
423     a_params.out      = NULL;
424     
425     if (pioctl ((char *)path, VIOC_BREAKCALLBACK, &a_params, 0) < 0)
426         return errno;
427     else
428         return 0;
429 }
430 #endif
431
432 /*
433  * Get/set debug levels with pioctl_cmd.
434  *
435  * inflags == -1 -> don't change
436  * outflags == NULL -> don't return
437  */
438
439 static int
440 debug (int pioctl_cmd, int inflags, int *outflags, char *pathname)
441 {
442     struct ViceIoctl   a_params;
443
444     int32_t rinflags = inflags;
445     int32_t routflags;
446
447     if (inflags != -1) {
448         a_params.in_size = sizeof(rinflags);
449         a_params.in = (char *) &rinflags;
450     } else {
451         a_params.in_size = 0;
452         a_params.in = NULL;
453     }
454         
455     if (outflags) {
456         a_params.out_size = sizeof(routflags);
457         a_params.out = (char *)  &routflags;
458     } else {
459         a_params.out_size = 0;
460         a_params.out = NULL;
461     }
462
463     if (pioctl (pathname, pioctl_cmd, &a_params, 0) == -1)
464         return errno;
465     
466     if (outflags)
467         *outflags = routflags;
468
469     return 0;
470 }
471
472 /*
473  * xfs_debug
474  */
475
476 #ifdef VIOC_XFSDEBUG
477 int
478 xfs_debug(int inflags, int *outflags)
479 {
480     return debug (VIOC_XFSDEBUG, inflags, outflags, NULL);
481 }
482 #endif
483
484 /*
485  * xfs_debug_print
486  */
487
488 #ifdef VIOC_XFSDEBUG_PRINT
489 int
490 xfs_debug_print(int inflags, char *pathname)
491 {
492     return debug (VIOC_XFSDEBUG_PRINT, inflags, NULL, pathname);
493 }
494 #endif
495
496 /*
497  * arla_debug
498  */
499
500 #ifdef VIOC_ARLADEBUG
501 int
502 arla_debug (int inflags, int *outflags)
503 {
504     return debug (VIOC_ARLADEBUG, inflags, outflags, NULL);
505 }
506 #endif
507
508 /*
509  * checkservers
510  *
511  *   flags is the same flags as in CKSERV flags
512  *
513  */
514
515 int
516 fs_checkservers(char *cell, int32_t flags, u_int32_t *hosts, int numhosts)
517 {
518     struct ViceIoctl a_params;
519     char *in = NULL;
520     int ret;
521     size_t insize;
522
523     if (cell != NULL) {
524         insize = strlen(cell) + sizeof(int32_t) + 1;
525         in = malloc (insize);
526         if (in == NULL)
527             errx (1, "malloc");
528
529         memcpy (in, &flags, sizeof(flags));
530
531         memcpy (in + sizeof(int32_t), cell, strlen(cell));
532         in[sizeof(int32_t) + strlen(cell)] = '\0';
533         
534         a_params.in_size = insize;
535         a_params.in = in;
536     } else {
537         a_params.in_size = sizeof(flags);
538         a_params.in = (caddr_t )&flags;
539     }
540
541     a_params.out_size = numhosts * sizeof(u_int32_t);
542     a_params.out = (caddr_t)hosts;
543
544     ret = 0;
545
546     if (pioctl (NULL, VIOCCKSERV, &a_params, 0) == -1)
547         ret = errno;
548     
549     if (in)
550         free(in);
551
552     return ret;
553 }
554
555 /*
556  * check validity of cached volume information
557  */
558
559 int
560 fs_checkvolumes (void)
561 {
562     struct ViceIoctl a_params;
563
564     a_params.in       = NULL;
565     a_params.in_size  = 0;
566     a_params.out      = NULL;
567     a_params.out_size = 0;
568
569     if (pioctl (NULL, VIOCCKBACK, &a_params, 0) < 0)
570         return errno;
571     else
572         return 0;
573 }
574
575 /*
576  * set current sysname to `sys'
577  */
578
579 int
580 fs_set_sysname (const char *sys)
581 {
582     struct ViceIoctl a_params;
583     int32_t set = 1;
584
585     a_params.in_size  = sizeof(set) + strlen(sys) + 1;
586     a_params.in       = malloc(a_params.in_size);
587     if (a_params.in == NULL)
588         return ENOMEM;
589     a_params.out      = NULL;
590     a_params.out_size = 0;
591     memcpy (a_params.in, &set, sizeof(set));
592     strcpy (a_params.in + sizeof(set), sys);
593
594     if(pioctl (NULL, VIOC_AFS_SYSNAME, &a_params, 1) < 0)
595         return errno;
596     else
597         return 0;
598 }
599
600 /*
601  *
602  */
603
604 int
605 fs_setcache(int lv, int hv, int lb, int hb)
606 {
607     struct ViceIoctl a_params;
608     u_int32_t s[4];
609
610     s[0] = lv;
611     s[1] = hv;
612     s[2] = lb;
613     s[3] = hb;
614
615     a_params.in_size  = ((hv == 0) ? 1 : 4) * sizeof(u_int32_t);
616     a_params.out_size = 0;
617     a_params.in       = (void *)s;
618     a_params.out      = NULL;
619
620     if (pioctl(NULL, VIOCSETCACHESIZE, &a_params, 0) < 0)
621         return errno;
622     else
623         return 0;
624 }
625
626 /*
627  * return the local cell in `cell' (of size `cell_sz').
628  */
629
630 int
631 fs_wscell (char *cell, size_t cell_sz)
632 {
633     struct ViceIoctl a_params;
634
635     a_params.in_size  = 0;
636     a_params.in       = NULL;
637     a_params.out_size = cell_sz;
638     a_params.out      = cell;
639
640     if (pioctl (NULL, VIOC_GET_WS_CELL, &a_params, 0) < 0)
641         return errno;
642     return 0;
643 }
644
645 /*
646  * Flush the contents of the volume pointed to by `path'.
647  */
648
649 int
650 fs_flushvolume (const char *path)
651 {
652     struct ViceIoctl a_params;
653
654     a_params.in_size  = 0;
655     a_params.out_size = 0;
656     a_params.in       = NULL;
657     a_params.out      = NULL;
658
659     if (pioctl ((char *)path, VIOC_FLUSHVOLUME, &a_params, 0) < 0)
660         return errno;
661     else
662         return 0;
663 }
664
665 /*
666  * Flush the file `path' from the cache.
667  */
668
669 int
670 fs_flush (const char *path)
671 {
672     struct ViceIoctl a_params;
673
674     a_params.in_size  = 0;
675     a_params.out_size = 0;
676     a_params.in       = NULL;
677     a_params.out      = NULL;
678
679     if (pioctl ((char *)path, VIOCFLUSH, &a_params, 0) < 0)
680         return errno;
681     else
682         return 0;
683 }
684
685 /*
686  *
687  */
688
689 int
690 fs_venuslog (void)
691 {
692     struct ViceIoctl a_params;
693     int32_t status = 0;   /* XXX not really right, but anyway */
694
695     a_params.in_size  = sizeof(int32_t);
696     a_params.out_size = 0;
697     a_params.in       = (caddr_t) &status;
698     a_params.out      = NULL;
699
700     if (pioctl (NULL, VIOC_VENUSLOG, &a_params, 0) < 0)
701         return errno;
702     else
703         return 0;
704 }
705
706 /*
707  * Get status for `cell' and put the flags in `flags'.
708  */
709
710 int
711 fs_getcellstatus (char *cellname, u_int32_t *flags)
712 {
713     struct ViceIoctl a_params;
714
715     a_params.in_size  = strlen (cellname) + 1;
716     a_params.out_size = sizeof (u_int32_t);
717     a_params.in       = cellname;
718     a_params.out      = (caddr_t) flags;
719
720     if (pioctl (NULL, VIOC_GETCELLSTATUS, &a_params, 0) < 0)
721         return errno;
722     else
723         return 0;
724 }
725
726 /*
727  * Separate `path' into directory and last component and call
728  * pioctl with `pioctl_cmd'.
729  */
730
731 static int
732 internal_mp (const char *path, int pioctl_cmd, char **res)
733 {
734     struct ViceIoctl    a_params;
735     char               *last;
736     char               *path_bkp;
737     int                 error;
738
739     path_bkp = strdup (path);
740     if (path_bkp == NULL) {
741         printf ("fs: Out of memory\n");
742         return ENOMEM;
743     }
744
745     a_params.out = malloc (PIOCTL_MAXSIZE);
746     if (a_params.out == NULL) {
747         printf ("fs: Out of memory\n");
748         free (path_bkp);
749         return ENOMEM;
750     }
751
752     /* If path contains more than the filename alone - split it */
753
754     last = strrchr (path_bkp, '/');
755     if (last != NULL) {
756         *last = '\0';
757         a_params.in = last + 1;
758     } else
759         a_params.in = (char *)path;
760
761     a_params.in_size = strlen (a_params.in) + 1;
762     a_params.out_size = PIOCTL_MAXSIZE;
763
764     error = pioctl (last ? path_bkp : "." ,
765                       pioctl_cmd, &a_params, 1);
766     if (error < 0) {
767         error = errno;
768         free (path_bkp);
769         free (a_params.out);
770         return error;
771     }
772
773     if (res != NULL)
774         *res = a_params.out;
775     else
776         free (a_params.out);
777     free (path_bkp);
778     return 0;
779 }
780
781 int
782 fs_lsmount (const char *path)
783 {
784     char *res;
785     int error = internal_mp (path, VIOC_AFS_STAT_MT_PT, &res);
786
787     if (error == 0) {
788         printf ("'%s' is a mount point for volume '%s'\n", path, res);
789         free (res);
790     }
791     return error;
792 }
793
794 int
795 fs_rmmount (const char *path)
796 {
797     return internal_mp (path, VIOC_AFS_DELETE_MT_PT, NULL);
798 }
799
800 int
801 fs_incompat_renumber (int *ret)
802 {
803     struct ViceIoctl a_params;
804     unsigned char buf[1024];
805
806     a_params.in_size  = 0;
807     a_params.out_size = sizeof(buf);
808     a_params.in       = 0;
809     a_params.out      = (caddr_t) buf;
810
811     /* getcrypt or getinitparams */
812     if (pioctl (NULL, _VICEIOCTL(49), &a_params, 0) < 0) {
813         if (errno == EINVAL) {
814
815             /* not openafs or old openafs */
816
817             a_params.in_size  = 0;
818             a_params.out_size = 4;
819             a_params.in       = 0;
820             a_params.out      = (caddr_t) buf;
821             
822             if (pioctl (NULL, _VICEIOCTL(49), &a_params, 0) < 0) {
823                 if (errno == EINVAL) {
824                     
825                     a_params.in_size  = 0;
826                     a_params.out_size = 4;
827                     a_params.in       = 0;
828                     a_params.out      = (caddr_t) buf;
829                     
830                     /* might be new interface */
831
832                     if (pioctl (NULL, _VICEIOCTL(55), &a_params, 0) < 0)
833                         return errno; /* dunno */
834                     
835                     *ret = 1;
836                     return 0;
837                 } else {
838                     return errno;
839                 }
840             }
841             *ret = 0;
842             return 0;
843         } else
844             return errno;
845     }
846     *ret = 1;
847     return 0;
848 }