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