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