gcc-warnings-cleanup-20030701
[openafs.git] / src / uss / uss_fs.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  *      Implementation of the AFS system operations exported by the
12  *      Cache Manager.
13  */
14
15 /*
16  * --------------------- Required definitions ---------------------
17  */
18 #include <afsconfig.h>
19 #include <afs/param.h>
20
21 RCSID("$Header$");
22
23 #include "uss_fs.h"             /*Interface to this module*/
24 #include <sys/types.h>
25 #include <errno.h>
26 #include <sys/socket.h>
27 #ifdef  AFS_SUN5_ENV
28 #include <sys/ioccom.h>
29 #endif
30 #include <netinet/in.h>
31
32 #ifdef HAVE_STRING_H
33 #include <string.h>
34 #else
35 #ifdef HAVE_STRINGS_H
36 #include <strings.h>
37 #endif
38 #endif
39
40 #include <afs/venus.h>
41 #include "uss_common.h"
42
43
44 /*
45  * ---------------------- Private definitions ---------------------
46  */
47 #undef USS_FS_DB
48
49
50 /*
51  * ------------------------ Private globals -----------------------
52  */
53 static struct ViceIoctl blob;             /*Param-passing area*/
54 static struct ViceIoctl *blobP = &blob;   /*Ptr to above*/
55
56
57 /*------------------------------------------------------------------------
58  * static InAFS
59  *
60  * Description:
61  *      Is the given pathname in AFS?
62  *
63  * Arguments:
64  *      a_path : Pathname to examine.
65  *
66  * Returns:
67  *      0 if the pathname is NOT in AFS,
68  *      1 if it is.
69  *
70  * Environment:
71  *      Nothing interesting.
72  *
73  * Side Effects:
74  *      As advertised.
75  *------------------------------------------------------------------------*/
76
77 static int InAFS(a_path)
78     register char *a_path;
79
80 { /*InAFS*/
81
82     static char rn[] = "uss_fs:InAFS";
83     register afs_int32 code;
84
85     blob.in       = NULL;
86     blob.in_size  = 0;
87     blob.out_size = USS_FS_MAX_SIZE;
88     blob.out      = uss_fs_OutBuff;
89
90     code = pioctl(a_path, VIOC_FILE_CELL_NAME, blobP, 1);
91     if (code) {
92         if ((errno == EINVAL) || (errno == ENOENT))
93             return(0);
94     }
95     return(1);
96
97 } /*InAFS*/
98
99
100 /*------------------------------------------------------------------------
101  * static ParentAndComponent
102  *
103  * Description:
104  *      Calculate the parent directory of the given pathname, along
105  *      with the final component.
106  *
107  * Arguments:
108  *      char *a_path         : Pathname to ancestorize.
109  *      char *a_parentBuff   : Ptr to parent buffer to use.
110  *      char **a_componentPP : Ptr to the final component.
111  *      
112  *
113  * Returns:
114  *      Ptr to the buffer containing the parent dir name.
115  *
116  * Environment:
117  *      Nothing interesting.
118  *
119  * Side Effects:
120  *      As advertised.
121  *------------------------------------------------------------------------*/
122
123 static char *ParentAndComponent(a_path, a_parentBuff, a_componentPP)
124     char *a_path;
125     char *a_parentBuff;
126     char **a_componentPP;
127
128 { /*ParentAndComponent*/
129
130     static char rn[] = "uss_fs:Parent";
131     char *rightSlashP;
132
133     /*
134      * Copy over the original pathname, then find the location of the
135      * rightmost slash.  If there is one, we chop off the string at
136      * point.  Otherwise, it is a single pathname component whose
137      * parent must be the current working directory.  In this case,
138      * we cheat and return ``.''.
139      */
140     strcpy(a_parentBuff, a_path);
141     rightSlashP = (char *) strrchr(a_parentBuff, '/');
142     if (rightSlashP) {
143         *rightSlashP = 0;
144         *a_componentPP = rightSlashP+1;
145     }
146     else {
147         strcpy(a_parentBuff, ".");
148         *a_componentPP = a_path;
149     }
150
151     return(a_parentBuff);
152
153 } /*ParentAndComponent*/
154
155
156 /*------------------------------------------------------------------------
157  * static CarefulPioctl
158  *
159  * Description:
160  *      Execute a pioctl(), but be careful to refresh the Cache Manager's
161  *      volume mapping in case we get an ENODEV the first time.
162  *
163  * Arguments:
164  *      char *a_path              : pioctl() pathname argument.
165  *      int a_opcode              : pioctl() opcode.
166  *      struct ViceIoctl *a_blobP : pioctl() blob pointer.
167  *      int a_sl                  : pioctl() symlink info.
168  *
169  * Returns:
170  *      Whatever the pioctl() returned, either the after the first
171  *      call if we didn't get an ENODEV, or the results of the second
172  *      call if we did.
173  *
174  * Environment:
175  *      Nothing interesting.
176  *
177  * Side Effects:
178  *      As advertised.
179  *------------------------------------------------------------------------*/
180
181 static int CarefulPioctl(a_path, a_opcode, a_blobP, a_sl)
182     char *a_path;
183     int a_opcode;
184     struct ViceIoctl *a_blobP;
185     int a_sl;
186
187 { /*CarefulPioctl*/
188
189     static char rn[] = "uss_fs:CarefulPioctl";
190     register afs_int32 code;
191
192     /*
193      * Call the pioctl() the first time, return if things worked
194      * out ``normally''.
195      */
196 #ifdef USS_FS_DB
197     printf("%s: First pioctl call\n", rn);
198 #endif /* USS_FS_DB */
199     code = pioctl(a_path, a_opcode, a_blobP, a_sl);
200 #ifdef USS_FS_DB
201     if (code)
202         printf("%s: First pioctl call fails, errno is %d\n",
203                rn, errno);
204 #endif /* USS_FS_DB */
205     if ((code == 0) || (code && (errno != ENODEV)))
206         return(code);
207
208     /*
209      * Hmm, it's possible out volume mappings are stale.  Let's
210      * bring them up to date, then try again.
211      */
212 #ifdef USS_FS_DB
213     printf("%s: First pioctl got a NODEV\n", rn);
214 #endif /* USS_FS_DB */
215     code = uss_fs_CkBackups();
216     code = pioctl(a_path, a_opcode, a_blobP, a_sl);
217     return(code);
218
219 } /*CarefulPioctl*/
220
221
222 /*------------------------------------------------------------------------
223  * EXPORTED uss_fs_GetACL
224  *
225  * Environment:
226  *      Nothing interesting.
227  *
228  * Side Effects:
229  *      As advertised.
230  *------------------------------------------------------------------------*/
231
232 afs_int32 uss_fs_GetACL(a_dirPath, a_aclBuff, a_aclBuffBytes)
233     char *a_dirPath;
234     char *a_aclBuff;
235     afs_int32 a_aclBuffBytes;
236
237 { /*uss_fs_GetACL*/
238
239     static char rn[] = "uss_fs_GetACL"; /*Routine name*/
240     register afs_int32 code;                    /*pioctl() result*/
241
242     blob.in       = NULL;
243     blob.in_size  = 0;
244     blob.out      = a_aclBuff;
245     blob.out_size = a_aclBuffBytes;
246
247 #ifdef USS_FS_DB
248     printf("%s: in 0x%x (%d bytes), out 0x%x, (%d bytes)\n",
249            rn, blob.in, blob.in_size, blob.out, blob.out_size);
250 #endif /* USS_FS_DB */
251
252     code = CarefulPioctl(a_dirPath, VIOCGETAL, blobP, 1);
253
254 #ifdef USS_FS_DB
255     if (code)
256         printf("%s: pioctl() failed, errno %d\n", rn, errno);
257 #endif /* USS_FS_DB */
258
259     return(code);
260
261 } /*uss_fs_GetACL*/
262
263
264 /*------------------------------------------------------------------------
265  * EXPORTED uss_fs_SetACL
266  *
267  * Environment:
268  *      Nothing interesting.
269  *
270  * Side Effects:
271  *      As advertised.
272  *------------------------------------------------------------------------*/
273
274 afs_int32 uss_fs_SetACL(a_dirPath, a_aclBuff, a_aclBuffBytes)
275     char *a_dirPath;
276     char *a_aclBuff;
277     afs_int32 a_aclBuffBytes;
278
279 { /*uss_fs_SetACL*/
280
281     static char rn[] = "uss_fs_SetACL"; /*Routine name*/
282     register afs_int32 code;                    /*pioctl() result*/
283
284     blob.in       = a_aclBuff;
285     blob.in_size  = a_aclBuffBytes;
286     blob.out      = NULL;
287     blob.out_size = 0;
288
289 #ifdef USS_FS_DB
290     printf("%s: in 0x%x (%d bytes), out 0x%x, (%d bytes)\n",
291            rn, blob.in, blob.in_size, blob.out, blob.out_size);
292     printf("%s: ACL value for dir '%s' is '%s'\n",
293            rn, a_dirPath, a_aclBuff);
294 #endif /* USS_FS_DB */
295
296     code = CarefulPioctl(a_dirPath, VIOCSETAL, blobP, 1);
297
298 #ifdef USS_FS_DB
299     if (code)
300         printf("%s: pioctl() failed, errno %d", rn, errno);
301 #endif /* USS_FS_DB */
302
303     return(code);
304
305 } /*uss_fs_SetACL*/
306
307
308 /*------------------------------------------------------------------------
309  * EXPORTED uss_fs_GetVolStat
310  *
311  * Environment:
312  *      Nothing interesting.
313  *
314  * Side Effects:
315  *      As advertised.
316  *------------------------------------------------------------------------*/
317
318 afs_int32 uss_fs_GetVolStat(a_mountpoint, a_volStatBuff, a_volStatBuffBytes)
319     char *a_mountpoint;
320     char *a_volStatBuff;
321     afs_int32 a_volStatBuffBytes;
322
323 { /*uss_fs_GetVolStat*/
324
325     static char rn[] = "uss_fs_GetVolStat";     /*Routine name*/
326     register afs_int32 code;                            /*pioctl() result*/
327
328     blob.in       = NULL;
329     blob.in_size  = 0;
330     blob.out      = a_volStatBuff;
331     blob.out_size = a_volStatBuffBytes;
332
333 #ifdef USS_FS_DB
334     printf("%s: in 0x%x (%d bytes), out 0x%x, (%d bytes)\n",
335            rn, blob.in, blob.in_size, blob.out, blob.out_size);
336 #endif /* USS_FS_DB */
337
338     code = CarefulPioctl(a_mountpoint, VIOCGETVOLSTAT, blobP, 1);
339
340 #ifdef USS_FS_DB
341     if (code)
342         printf("%s: pioctl() failed, errno %d", rn, errno);
343 #endif /* USS_FS_DB */
344
345     return(code);
346
347 } /*uss_fs_GetVolStat*/
348
349
350 /*------------------------------------------------------------------------
351  * EXPORTED uss_fs_SetVolStat
352  *
353  * Environment:
354  *      Nothing interesting.
355  *
356  * Side Effects:
357  *      As advertised.
358  *------------------------------------------------------------------------*/
359
360 afs_int32 uss_fs_SetVolStat(a_mountpoint, a_volStatBuff, a_volStatBuffBytes)
361     char *a_mountpoint;
362     char *a_volStatBuff;
363     afs_int32 a_volStatBuffBytes;
364
365 { /*uss_fs_SetVolStat*/
366
367     static char rn[] = "uss_fs_SetVolStat";     /*Routine name*/
368     register afs_int32 code;                            /*pioctl() result*/
369
370     blob.in       = a_volStatBuff;
371     blob.in_size  = a_volStatBuffBytes;
372     blob.out      = a_volStatBuff;
373     blob.out_size = USS_FS_MAX_SIZE;
374
375 #ifdef USS_FS_DB
376     printf("%s: in 0x%x (%d bytes), out 0x%x, (%d bytes)\n",
377            rn, blob.in, blob.in_size, blob.out, blob.out_size);
378 #endif /* USS_FS_DB */
379
380     code = CarefulPioctl(a_mountpoint, VIOCSETVOLSTAT, blobP, 1);
381
382 #ifdef USS_FS_DB
383     if (code)
384         printf("%s: pioctl() failed, errno %d", rn, errno);
385 #endif /* USS_FS_DB */
386
387     return(code);
388
389 } /*uss_fs_SetVolStat*/
390
391
392 /*------------------------------------------------------------------------
393  * EXPORTED uss_fs_CkBackups
394  *
395  * Environment:
396  *      We are NOT careful here, since it's OK to get ENODEVs.
397  *
398  * Side Effects:
399  *      As advertised.
400  *------------------------------------------------------------------------*/
401
402 afs_int32 uss_fs_CkBackups()
403
404 { /*uss_fs_CkBackups*/
405
406     static char rn[] = "uss_fs_CkBackups";      /*Routine name*/
407     register afs_int32 code;                            /*pioctl() result*/
408
409     blob.in       = NULL;
410     blob.in_size  = 0;
411     blob.out      = NULL;
412     blob.out_size = 0;
413     
414 #ifdef USS_FS_DB
415     printf("%s: in 0x%x (%d bytes), out 0x%x, (%d bytes)\n",
416            rn, blob.in, blob.in_size, blob.out, blob.out_size);
417 #endif /* USS_FS_DB */
418
419     code = pioctl(NULL, /*No pathname needed here*/
420                   VIOCCKBACK,   /*CheckBackups*/
421                   &blob,                /*Params*/
422                   1);           /*Symlink disposition*/
423 #ifdef USS_FS_DB
424     if (code)
425         printf("%s: pioctl() failed, errno %d", rn, errno);
426 #endif /* USS_FS_DB */
427
428     return(code);
429
430 } /*uss_fs_CkBackups*/
431
432
433 /*------------------------------------------------------------------------
434  * EXPORTED uss_fs_MkMountPoint
435  *
436  * Environment:
437  *      Uses uss_fs_OutBuff to construct the mountpoint contents.
438  *
439  * Side Effects:
440  *      As advertised.
441  *------------------------------------------------------------------------*/
442
443 afs_int32 uss_fs_MkMountPoint(a_volname, a_cellname, a_rw, a_mountpoint)
444     char *a_volname;
445     char *a_cellname;
446     afs_int32 a_rw;
447     char *a_mountpoint;
448
449 { /*uss_fs_MkMountPoint*/
450     extern int local_Cell;
451     static char rn[] = "uss_fs_MkMountPoint";   /*Routine name*/
452     register afs_int32 code;                            /*pioctl() result*/
453     char *tp;                                   /*Temporary*/
454
455 #ifdef USS_FS_DB
456     printf("%s: a_volname='%s', a_cellname='%s', a_rw=%d, a_mountpoint='%s'\n",
457            rn, a_volname, a_cellname, a_rw, a_mountpoint);
458 #endif /* USS_FS_DB */
459
460     /*
461      * Make sure the parent directory is in AFS.
462      */
463     if (!InAFS(ParentAndComponent(a_mountpoint, uss_fs_OutBuff, &tp))) {
464         printf("%s: Mountpoints must be created within AFS\n", rn);
465         return(-1);
466     }
467
468     /*
469      * Build the contents of the mountpoint we'll create.  It's safe to
470      * use the uss_fs_OutBuff for this construction.  Note: the last
471      * char, by convention, is a dot.
472      */
473     if (local_Cell) {
474         sprintf(uss_fs_OutBuff, "%s%s.",
475                 (a_rw ? "%" : "#"),
476                 a_volname);
477     } else {
478         sprintf(uss_fs_OutBuff, "%s%s:%s.",
479                 (a_rw ? "%" : "#"),
480                 a_cellname,
481                 a_volname);
482     }
483
484     /*
485      * Now, create the symlink with the above value.
486      */
487     code = symlink(uss_fs_OutBuff, a_mountpoint);
488     if (code) {
489 #ifdef USS_FS_DB
490         printf("%s: Mountpoint creation (symlink) failed, errno is %d\n",
491                rn, errno);
492 #endif /* USS_FS_DB */
493         return(-1);
494     }
495
496 } /*uss_fs_MkMountPoint*/
497
498
499 /*------------------------------------------------------------------------
500  * EXPORTED uss_fs_RmMountPoint
501  *
502  * Environment:
503  *      Nothing interesting.
504  *
505  * Side Effects:
506  *      As advertised.
507  *------------------------------------------------------------------------*/
508
509 afs_int32 uss_fs_RmMountPoint(a_mountpoint)
510     char *a_mountpoint;
511
512 { /*uss_fs_RmMountPoint*/
513
514     static char rn[] = "uss_fs_RmMountPoint";   /*Routine name*/
515     register afs_int32 code;                            /*pioctl() result*/
516     char *parentDirP;                           /*Ptr to parent*/
517     char *componentP;                           /*Ptr to last component*/
518
519     /*
520      * Get the parent & final component names.
521      */
522     parentDirP = ParentAndComponent(a_mountpoint,
523                                     uss_fs_InBuff,
524                                     &componentP);
525
526     blob.in       = componentP;
527     blob.in_size  = strlen(componentP) + 1;
528     blob.out      = uss_fs_OutBuff;
529     blob.out_size = USS_FS_MAX_SIZE;
530
531 #ifdef USS_FS_DB
532     printf("%s: AFS_STAT_MT_PT, in 0x%x (%d bytes), out 0x%x, (%d bytes)\n",
533            rn, blob.in, blob.in_size, blob.out, blob.out_size);
534 #endif /* USS_FS_DB */
535
536     code = CarefulPioctl(parentDirP, VIOC_AFS_STAT_MT_PT, blobP, 1);
537     if (code) {
538 #ifdef USS_FS_DB
539         printf("%s: STAT_MT_PT pioctl() failed, errno %d", rn, errno);
540 #endif /* USS_FS_DB */
541         if (errno == EINVAL)
542             printf("%s: '%s' is not a mountpoint\n",
543                    rn, a_mountpoint);
544         return(code);
545     }
546
547     /*
548      * Now that we know we have a proper mountpoint, nuke it.
549      */
550     blob.in       = componentP;
551     blob.in_size  = strlen(componentP) + 1;
552     blob.out      = NULL;
553     blob.out_size = 0;
554
555     if (!uss_DryRun) {
556 #ifdef USS_FS_DB
557         printf("%s: AFS_DELETE_MT_PT, in 0x%x (%d bytes), out 0x%x, (%d bytes)\n",
558                rn, blob.in, blob.in_size, blob.out, blob.out_size);
559 #endif /* USS_FS_DB */
560
561         code = pioctl(parentDirP, VIOC_AFS_DELETE_MT_PT, blobP, 1);
562         if (code) {
563 #ifdef USS_FS_DB
564             printf("%s: DELETE_MT_PT pioctl() failed, errno %d", rn, errno);
565 #endif /* USS_FS_DB */
566         } 
567     } else
568         printf("\t[Dry run - mount point '%s' NOT removed]\n", componentP);
569
570     return(code);
571
572 } /*uss_fs_RmMountPoint*/
573
574
575 #include <afs/auth.h>
576 struct tokenInfo {
577     struct ktc_token  token;
578     struct ktc_principal service;
579     struct ktc_principal client;
580     int deleted;
581 };
582
583 /*
584  * Build a list of tokens, delete the bad ones (the ones to remove from the 
585  * permissions list,) destroy all tokens, and then re-register the good ones.
586  * Ugly, but it works.
587  */
588 uss_fs_UnlogToken(celln)
589     char *celln;
590 {
591     unsigned count = 0, index, index2;
592     afs_int32 code = 0, cnt=0;
593     struct ktc_principal serviceName;
594     struct tokenInfo *tokenInfoP, *tp;
595
596     do {
597         code = ktc_ListTokens(count, &count, &serviceName);
598         cnt++;
599     } while(!code);
600     count = cnt - 1;
601     tokenInfoP = (struct tokenInfo *)malloc((sizeof(struct tokenInfo)*count));
602     for (code = index = index2= 0; (!code) && (index < count); index++) {
603         tp = tokenInfoP+index;
604         code = ktc_ListTokens(index2, &index2, &tp->service);
605         if (!code) {
606             code = ktc_GetToken(&tp->service, &tp->token, sizeof(struct ktc_token),
607                                 &tp->client);
608             if (!code) {
609                 tp->deleted = (!strcmp(celln, tp->client.cell) ? 1 : 0);
610                 if (tp->deleted)
611                     cnt = 1;
612             }
613         }
614     }
615     if (code = ktc_ForgetAllTokens ()) {
616         printf("uss_fs_UnlogToken: could not discard tickets, code %d\n", code);
617         exit(1);
618     }
619     for (code = index = 0; index < count ; index++) {
620         tp = tokenInfoP+index;
621         if (!(tp->deleted)) {
622             code = ktc_SetToken(&tp->service, &tp->token, &tp->client, 0);
623             if (code) {
624                 printf("uss_fs_UnlogToken: Couldn't re-register token, code = %d\n",
625                         code);
626             }
627         }
628     }
629     return 0;
630 }
631
632