c6df92c1c2056d0c85e413a7f426d895c708a5de
[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(afs_uint32 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(afs_uint32 * 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(afs_int32 type, afs_int32 * flags)
177 {
178     struct ViceIoctl a_params;
179
180     a_params.in_size = sizeof(type);
181     a_params.out_size = sizeof(afs_int32);
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(afs_uint32 * max_bytes, afs_uint32 * used_bytes,
297                      afs_uint32 * max_vnodes, afs_uint32 * used_vnodes)
298 {
299     afs_uint32 parms[16];
300     struct ViceIoctl a_params;
301
302     a_params.in_size = 0;
303     a_params.out_size = sizeof(parms);
304     a_params.in = NULL;
305     a_params.out = (char *)parms;
306
307     memset(parms, 0, sizeof(parms));
308
309     if (pioctl(NULL, VIOCGETCACHEPARAMS, &a_params, 0) == -1)
310         return errno;
311
312     /* param[0] and param[1] send maxbytes and usedbytes in kbytes */
313
314     if (max_vnodes)
315         *max_vnodes = parms[2];
316     if (used_vnodes)
317         *used_vnodes = parms[3];
318     if (max_bytes)
319         *max_bytes = parms[4];
320     if (used_bytes)
321         *used_bytes = parms[5];
322
323     return 0;
324 }
325 #endif
326
327 /*
328  *
329  */
330
331 #ifdef VIOC_AVIATOR
332 int
333 fs_getaviatorstats(afs_uint32 * max_workers, afs_uint32 * used_workers)
334 {
335     afs_uint32 parms[16];
336     struct ViceIoctl a_params;
337
338     a_params.in_size = 0;
339     a_params.out_size = sizeof(parms);
340     a_params.in = NULL;
341     a_params.out = (char *)parms;
342
343     if (pioctl(NULL, VIOC_AVIATOR, &a_params, 0) == -1)
344         return errno;
345
346     if (max_workers)
347         *max_workers = parms[0];
348     if (used_workers)
349         *used_workers = parms[1];
350
351     return 0;
352 }
353 #endif
354
355 /*
356  *
357  */
358
359 #ifdef VIOC_GCPAGS
360 int
361 fs_gcpags(void)
362 {
363     struct ViceIoctl a_params;
364
365     a_params.in_size = 0;
366     a_params.out_size = 0;
367     a_params.in = NULL;
368     a_params.out = NULL;
369
370
371     if (pioctl(NULL, VIOC_GCPAGS, &a_params, 0) != 0)
372         return errno;
373
374     return 0;
375 }
376 #endif
377
378 /*
379  *
380  */
381
382 #ifdef VIOC_CALCULATE_CACHE
383 int
384 fs_calculate_cache(afs_uint32 * calculated, afs_uint32 * usedbytes)
385 {
386     afs_uint32 parms[16];
387     struct ViceIoctl a_params;
388
389     a_params.in_size = 0;
390     a_params.out_size = sizeof(parms);
391     a_params.in = NULL;
392     a_params.out = (char *)parms;
393
394     if (pioctl(NULL, VIOC_CALCULATE_CACHE, &a_params, 0) == -1)
395         return errno;
396
397     if (calculated)
398         *calculated = parms[0];
399     if (usedbytes)
400         *usedbytes = parms[1];
401
402     return 0;
403 }
404 #endif
405
406 /*
407  *
408  */
409
410 #ifdef VIOC_BREAKCALLBACK
411 int
412 fs_invalidate(const char *path)
413 {
414     struct ViceIoctl a_params;
415
416     a_params.in_size = 0;
417     a_params.out_size = 0;
418     a_params.in = NULL;
419     a_params.out = NULL;
420
421     if (pioctl((char *)path, VIOC_BREAKCALLBACK, &a_params, 0) < 0)
422         return errno;
423     else
424         return 0;
425 }
426 #endif
427
428 /*
429  * Get/set debug levels with pioctl_cmd.
430  *
431  * inflags == -1 -> don't change
432  * outflags == NULL -> don't return
433  */
434
435 static int
436 debug(int pioctl_cmd, int inflags, int *outflags, char *pathname)
437 {
438     struct ViceIoctl a_params;
439
440     afs_int32 rinflags = inflags;
441     afs_int32 routflags;
442
443     if (inflags != -1) {
444         a_params.in_size = sizeof(rinflags);
445         a_params.in = (char *)&rinflags;
446     } else {
447         a_params.in_size = 0;
448         a_params.in = NULL;
449     }
450
451     if (outflags) {
452         a_params.out_size = sizeof(routflags);
453         a_params.out = (char *)&routflags;
454     } else {
455         a_params.out_size = 0;
456         a_params.out = NULL;
457     }
458
459     if (pioctl(pathname, pioctl_cmd, &a_params, 0) == -1)
460         return errno;
461
462     if (outflags)
463         *outflags = routflags;
464
465     return 0;
466 }
467
468 /*
469  * xfs_debug
470  */
471
472 #ifdef VIOC_XFSDEBUG
473 int
474 xfs_debug(int inflags, int *outflags)
475 {
476     return debug(VIOC_XFSDEBUG, inflags, outflags, NULL);
477 }
478 #endif
479
480 /*
481  * xfs_debug_print
482  */
483
484 #ifdef VIOC_XFSDEBUG_PRINT
485 int
486 xfs_debug_print(int inflags, char *pathname)
487 {
488     return debug(VIOC_XFSDEBUG_PRINT, inflags, NULL, pathname);
489 }
490 #endif
491
492 /*
493  * arla_debug
494  */
495
496 #ifdef VIOC_ARLADEBUG
497 int
498 arla_debug(int inflags, int *outflags)
499 {
500     return debug(VIOC_ARLADEBUG, inflags, outflags, NULL);
501 }
502 #endif
503
504 /*
505  * checkservers
506  *
507  *   flags is the same flags as in CKSERV flags
508  *
509  */
510
511 int
512 fs_checkservers(char *cell, afs_int32 flags, afs_uint32 * hosts, int numhosts)
513 {
514     struct ViceIoctl a_params;
515     char *in = NULL;
516     int ret;
517     size_t insize;
518
519     if (cell != NULL) {
520         insize = strlen(cell) + sizeof(afs_int32) + 1;
521         in = malloc(insize);
522         if (in == NULL)
523             errx(1, "malloc");
524
525         memcpy(in, &flags, sizeof(flags));
526
527         memcpy(in + sizeof(afs_int32), cell, strlen(cell));
528         in[sizeof(afs_int32) + strlen(cell)] = '\0';
529
530         a_params.in_size = insize;
531         a_params.in = in;
532     } else {
533         a_params.in_size = sizeof(flags);
534         a_params.in = (caddr_t) & flags;
535     }
536
537     a_params.out_size = numhosts * sizeof(afs_uint32);
538     a_params.out = (caddr_t) hosts;
539
540     ret = 0;
541
542     if (pioctl(NULL, VIOCCKSERV, &a_params, 0) == -1)
543         ret = errno;
544
545     if (in)
546         free(in);
547
548     return ret;
549 }
550
551 /*
552  * check validity of cached volume information
553  */
554
555 int
556 fs_checkvolumes(void)
557 {
558     struct ViceIoctl a_params;
559
560     a_params.in = NULL;
561     a_params.in_size = 0;
562     a_params.out = NULL;
563     a_params.out_size = 0;
564
565     if (pioctl(NULL, VIOCCKBACK, &a_params, 0) < 0)
566         return errno;
567     else
568         return 0;
569 }
570
571 /*
572  * set current sysname to `sys'
573  */
574
575 int
576 fs_set_sysname(const char *sys)
577 {
578     struct ViceIoctl a_params;
579     afs_int32 set = 1;
580
581     a_params.in_size = sizeof(set) + strlen(sys) + 1;
582     a_params.in = malloc(a_params.in_size);
583     if (a_params.in == NULL)
584         return ENOMEM;
585     a_params.out = NULL;
586     a_params.out_size = 0;
587     memcpy(a_params.in, &set, sizeof(set));
588     strcpy(a_params.in + sizeof(set), sys);
589
590     if (pioctl(NULL, VIOC_AFS_SYSNAME, &a_params, 1) < 0)
591         return errno;
592     else
593         return 0;
594 }
595
596 /*
597  *
598  */
599
600 int
601 fs_setcache(int lv, int hv, int lb, int hb)
602 {
603     struct ViceIoctl a_params;
604     afs_uint32 s[4];
605
606     s[0] = lv;
607     s[1] = hv;
608     s[2] = lb;
609     s[3] = hb;
610
611     a_params.in_size = ((hv == 0) ? 1 : 4) * sizeof(afs_uint32);
612     a_params.out_size = 0;
613     a_params.in = (void *)s;
614     a_params.out = NULL;
615
616     if (pioctl(NULL, VIOCSETCACHESIZE, &a_params, 0) < 0)
617         return errno;
618     else
619         return 0;
620 }
621
622 /*
623  * return the local cell in `cell' (of size `cell_sz').
624  */
625
626 int
627 fs_wscell(char *cell, size_t cell_sz)
628 {
629     struct ViceIoctl a_params;
630
631     a_params.in_size = 0;
632     a_params.in = NULL;
633     a_params.out_size = cell_sz;
634     a_params.out = cell;
635
636     if (pioctl(NULL, VIOC_GET_WS_CELL, &a_params, 0) < 0)
637         return errno;
638     return 0;
639 }
640
641 /*
642  * Flush the contents of the volume pointed to by `path'.
643  */
644
645 int
646 fs_flushvolume(const char *path)
647 {
648     struct ViceIoctl a_params;
649
650     a_params.in_size = 0;
651     a_params.out_size = 0;
652     a_params.in = NULL;
653     a_params.out = NULL;
654
655     if (pioctl((char *)path, VIOC_FLUSHVOLUME, &a_params, 0) < 0)
656         return errno;
657     else
658         return 0;
659 }
660
661 /*
662  * Flush the file `path' from the cache.
663  */
664
665 int
666 fs_flush(const char *path)
667 {
668     struct ViceIoctl a_params;
669
670     a_params.in_size = 0;
671     a_params.out_size = 0;
672     a_params.in = NULL;
673     a_params.out = NULL;
674
675     if (pioctl((char *)path, VIOCFLUSH, &a_params, 0) < 0)
676         return errno;
677     else
678         return 0;
679 }
680
681 /*
682  *
683  */
684
685 int
686 fs_venuslog(void)
687 {
688     struct ViceIoctl a_params;
689     afs_int32 status = 0;       /* XXX not really right, but anyway */
690
691     a_params.in_size = sizeof(afs_int32);
692     a_params.out_size = 0;
693     a_params.in = (caddr_t) & status;
694     a_params.out = NULL;
695
696     if (pioctl(NULL, VIOC_VENUSLOG, &a_params, 0) < 0)
697         return errno;
698     else
699         return 0;
700 }
701
702 /*
703  * Get status for `cell' and put the flags in `flags'.
704  */
705
706 int
707 fs_getcellstatus(char *cellname, afs_uint32 * flags)
708 {
709     struct ViceIoctl a_params;
710
711     a_params.in_size = strlen(cellname) + 1;
712     a_params.out_size = sizeof(afs_uint32);
713     a_params.in = cellname;
714     a_params.out = (caddr_t) flags;
715
716     if (pioctl(NULL, VIOC_GETCELLSTATUS, &a_params, 0) < 0)
717         return errno;
718     else
719         return 0;
720 }
721
722 /*
723  * Separate `path' into directory and last component and call
724  * pioctl with `pioctl_cmd'.
725  */
726
727 static int
728 internal_mp(const char *path, int pioctl_cmd, char **res)
729 {
730     struct ViceIoctl a_params;
731     char *last;
732     char *path_bkp;
733     int error;
734
735     path_bkp = strdup(path);
736     if (path_bkp == NULL) {
737         printf("fs: Out of memory\n");
738         return ENOMEM;
739     }
740
741     a_params.out = malloc(PIOCTL_MAXSIZE);
742     if (a_params.out == NULL) {
743         printf("fs: Out of memory\n");
744         free(path_bkp);
745         return ENOMEM;
746     }
747
748     /* If path contains more than the filename alone - split it */
749
750     last = strrchr(path_bkp, '/');
751     if (last != NULL) {
752         *last = '\0';
753         a_params.in = last + 1;
754     } else
755         a_params.in = (char *)path;
756
757     a_params.in_size = strlen(a_params.in) + 1;
758     a_params.out_size = PIOCTL_MAXSIZE;
759
760     error = pioctl(last ? path_bkp : ".", pioctl_cmd, &a_params, 1);
761     if (error < 0) {
762         error = errno;
763         free(path_bkp);
764         free(a_params.out);
765         return error;
766     }
767
768     if (res != NULL)
769         *res = a_params.out;
770     else
771         free(a_params.out);
772     free(path_bkp);
773     return 0;
774 }
775
776 int
777 fs_lsmount(const char *path)
778 {
779     char *res;
780     int error = internal_mp(path, VIOC_AFS_STAT_MT_PT, &res);
781
782     if (error == 0) {
783         printf("'%s' is a mount point for volume '%s'\n", path, res);
784         free(res);
785     }
786     return error;
787 }
788
789 int
790 fs_rmmount(const char *path)
791 {
792     return internal_mp(path, VIOC_AFS_DELETE_MT_PT, NULL);
793 }
794
795 int
796 fs_incompat_renumber(int *ret)
797 {
798     struct ViceIoctl a_params;
799     unsigned char buf[1024];
800
801     a_params.in_size = 0;
802     a_params.out_size = sizeof(buf);
803     a_params.in = 0;
804     a_params.out = (caddr_t) buf;
805
806     /* getcrypt or getinitparams */
807     if (pioctl(NULL, _VICEIOCTL(49), &a_params, 0) < 0) {
808         if (errno == EINVAL) {
809
810             /* not openafs or old openafs */
811
812             a_params.in_size = 0;
813             a_params.out_size = 4;
814             a_params.in = 0;
815             a_params.out = (caddr_t) buf;
816
817             if (pioctl(NULL, _VICEIOCTL(49), &a_params, 0) < 0) {
818                 if (errno == EINVAL) {
819
820                     a_params.in_size = 0;
821                     a_params.out_size = 4;
822                     a_params.in = 0;
823                     a_params.out = (caddr_t) buf;
824
825                     /* might be new interface */
826
827                     if (pioctl(NULL, _VICEIOCTL(55), &a_params, 0) < 0)
828                         return errno;   /* dunno */
829
830                     *ret = 1;
831                     return 0;
832                 } else {
833                     return errno;
834                 }
835             }
836             *ret = 0;
837             return 0;
838         } else
839             return errno;
840     }
841     *ret = 1;
842     return 0;
843 }