Import Upstream version 1.8.5
[hcoop/debian/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 = malloc((sizeof(struct tokenInfo) * count));
563 for (code = index = index2 = 0; (!code) && (index < count); index++) {
564 tp = tokenInfoP + index;
565 code = ktc_ListTokens(index2, &index2, &tp->service);
566 if (!code) {
567 code =
568 ktc_GetToken(&tp->service, &tp->token,
569 sizeof(struct ktc_token), &tp->client);
570 if (!code) {
571 tp->deleted = (!strcmp(celln, tp->client.cell) ? 1 : 0);
572 if (tp->deleted)
573 cnt = 1;
574 }
575 }
576 }
577 if ((code = ktc_ForgetAllTokens())) {
578 printf("uss_fs_UnlogToken: could not discard tickets, code %d\n",
579 code);
580 exit(1);
581 }
582 for (index = 0; index < count; index++) {
583 tp = tokenInfoP + index;
584 if (!(tp->deleted)) {
585 code = ktc_SetToken(&tp->service, &tp->token, &tp->client, 0);
586 if (code) {
587 printf
588 ("uss_fs_UnlogToken: Couldn't re-register token, code = %d\n",
589 code);
590 }
591 }
592 }
593 return 0;
594 }