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