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