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