Print this page
6198 Let's EOL cachefs
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/svr4pkg/libinst/mntinfo.c
+++ new/usr/src/cmd/svr4pkg/libinst/mntinfo.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 + * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
25 26 */
26 27
27 28
28 29 /*
29 30 * System includes
30 31 */
31 32
32 33 #include <stdio.h>
33 34 #include <limits.h>
34 35 #include <errno.h>
35 36 #include <stdlib.h>
36 37 #include <unistd.h>
37 38 #include <libgen.h>
38 39 #include <string.h>
39 40 #include <wait.h>
40 41 #include <signal.h>
41 42 #include <malloc.h>
42 43 #include <sys/types.h>
43 44 #include <sys/mount.h>
44 45 #include <sys/stat.h>
45 46 #include <fcntl.h>
46 47 #include <sys/systeminfo.h>
47 48 #include <pkgstrct.h>
48 49 #include <pkginfo.h>
49 50 #include <locale.h>
50 51 #include <libintl.h>
51 52
52 53 #include <sys/mnttab.h>
53 54 #include <sys/mntent.h>
54 55 #include <sys/vfstab.h>
55 56
56 57 /*
57 58 * consolidation pkg command library includes
58 59 */
59 60
60 61 #include <pkglib.h>
61 62
62 63 /*
63 64 * local pkg command library includes
64 65 */
65 66
66 67 #include "install.h"
67 68 #include "libinst.h"
68 69 #include "libadm.h"
69 70 #include "messages.h"
70 71
71 72 extern char **environ;
72 73
73 74 static int match_mount; /* This holds the mount of interest. */
74 75
75 76 int fs_tab_used = 0;
76 77 int fs_tab_alloc = 0;
77 78 static int fs_list = -1;
78 79
79 80 struct fstable **fs_tab = NULL;
80 81
81 82 #define PKGDBROOT "/var/sadm"
82 83 #define MOUNT "/sbin/mount"
83 84 #define UMOUNT "/sbin/umount"
84 85
85 86 #define setmntent fopen
86 87 #define endmntent fclose
87 88 #define MOUNT_TABLE MNTTAB
88 89
89 90 /* returned by already_mounted() */
90 91 #define MNT_NOT 0
91 92 #define MNT_EXACT 1
92 93 #define MNT_AVAIL 2
93 94
94 95 /* used with is_remote_src() */
95 96 #define NOT_REMOTE 0
96 97 #define REAL_REMOTE 1
97 98 #define SELF_SERVE 2
↓ open down ↓ |
63 lines elided |
↑ open up ↑ |
98 99
99 100 /*
100 101 * Due to /etc/mnttab files containing entries for multiple nfs hosts
101 102 * HOST_NM_LN needs to be accommodating. The recommended value in the sysinfo
102 103 * man page of 257 needs to be expanded. See bugid 4076513.
103 104 * 1024 chars is defined in the mnttab.h header as the max size of an entry.
104 105 */
105 106
106 107 #define HOST_NM_LN MNT_LINE_MAX
107 108
108 -/* These cachefs definitions should be in mntent.h. Maybe some day. */
109 -#define MNTTYPE_CFS "cachefs"
110 -#define MNTOPT_BACKFSTYPE "backfstype"
111 -#define MNTTYPE_AUTO "autofs"
112 -
113 109 /*
114 110 * Utilities for getting filesystem information from the mount table.
115 111 *
116 112 * Note: vanilla SVr4 code (pkginstall/dockspace.c) used the output from
117 113 * popen() on the "/etc/mount" command. However, we need to get more
118 114 * information about mounted filesystems, so we use the C interfaces to
119 115 * the mount table, which also happens to be much faster than running
120 116 * another process. Since several of the pkg commands need access to the
121 117 * the code has been placed here, to be included in the libinst library.
122 118 */
123 119
124 120 #define ALLOC_CHUNK 30
125 121
126 122 /*
127 123 * fs_tab_ent_comp - compare fstable entries first by length in reverse
128 124 * order, then alphabetically.
129 125 */
130 126 static int
131 127 fs_tab_ent_comp(const void *e1, const void *e2)
132 128 {
133 129 struct fstable *fs1 = *((struct fstable **)e1);
134 130 struct fstable *fs2 = *((struct fstable **)e2);
135 131
136 132 if (fs1->namlen == fs2->namlen)
137 133 return (strcmp(fs1->name, fs2->name));
138 134 else
139 135 return (fs2->namlen - fs1->namlen);
140 136 }
141 137
142 138 /*
143 139 * This determines if the source of the mount is from another host. If it's
144 140 * from this host, then it might be writable. This returns NOT_REMOTE if it's
145 141 * pure local, REAL_REMOTE if it's being served from another host and
146 142 * SELF_SERVE if it's being served by the current host.
147 143 */
148 144 static int
149 145 is_remote_src(char *source)
150 146 {
151 147 static char host_name[HOST_NM_LN];
152 148 char source_host[HOST_NM_LN], *src_ptr, *src_host_ptr;
153 149 static int hn_len;
154 150
155 151 if (hn_len == 0) {
156 152 /* Find out what host this is. */
157 153 (void) sysinfo(SI_HOSTNAME, host_name, HOST_NM_LN);
158 154 hn_len = strlen(host_name);
159 155 }
160 156
161 157 if (source[0] == '/')
162 158 return (NOT_REMOTE); /* No server name, so it's local. */
163 159
164 160 if (strchr(source, ':') == NULL)
165 161 return (NOT_REMOTE); /* it's a floppy disk or something */
166 162
167 163 src_ptr = source;
168 164 src_host_ptr = source_host;
169 165
170 166 /* Scan to the end of the hostname (find the ":"). */
171 167 while (*src_ptr != ':')
172 168 *src_host_ptr++ = *src_ptr++;
173 169 *src_host_ptr = '\0';
174 170
175 171 /* Multiple hosts: failover with multiple servers; this is remote. */
176 172 if (strchr(source_host, ',') != NULL)
177 173 return (REAL_REMOTE);
178 174
179 175 if (strncmp(source, host_name, hn_len) == 0 &&
180 176 *(source+hn_len) == ':' || is_local_host(source_host))
181 177 return (SELF_SERVE); /* Exporting from itself, it's local. */
182 178
183 179 return (REAL_REMOTE);
184 180 }
185 181
186 182 /*
187 183 * This determines if an apparently writeable filesystem is really writeable
188 184 * or if it's been shared over the network with root-restrictive options.
189 185 */
190 186 static int
191 187 really_write(char *mountpt)
192 188 {
193 189 char testfile[PATH_MAX];
194 190 int fd, retval = 0;
195 191 struct stat status;
196 192
197 193 (void) snprintf(testfile, sizeof (testfile), "%s/testXXXXXX", mountpt);
198 194
199 195 if (mktemp(testfile) == NULL)
200 196 return (0); /* may as well be read-only */
201 197 /* LINTED do not use creat(); use open(path,... */
202 198 else if ((fd = creat(testfile, 0777)) == -1)
203 199 return (0); /* can't write */
204 200 else if (fstat(fd, &status) == -1)
205 201 retval = 0; /* may as well be read-only */
206 202 else if (status.st_uid != 0)
207 203 retval = 0; /* too many restrictions */
208 204 else
209 205 retval = 1;
210 206
211 207 (void) close(fd);
212 208 (void) unlink(testfile);
213 209
214 210 return (retval);
215 211 }
216 212
217 213 /* This returns the hostname portion of a remote path. */
218 214 char *
219 215 get_server_host(uint32_t n)
↓ open down ↓ |
97 lines elided |
↑ open up ↑ |
220 216 {
221 217 static char hostname[HOST_NM_LN], *host_end;
222 218
223 219 if (fs_tab_used == 0) {
224 220 return ("unknown source");
225 221 }
226 222
227 223 if (n < fs_tab_used) {
228 224 (void) strcpy(hostname, fs_tab[n]->remote_name);
229 225 if ((host_end = strchr(hostname, ':')) == NULL) {
230 - if ((strcmp(fs_tab[n]->fstype, MNTTYPE_AUTO)) == NULL)
226 + if ((strcmp(fs_tab[n]->fstype, MNTTYPE_AUTOFS)) == NULL)
231 227 return ("automounter");
232 228 else
233 229 return (fs_tab[n]->fstype);
234 230 } else {
235 231 *host_end = '\0';
236 232 return (hostname);
237 233 }
238 234 }
239 235
240 236 return ("unknown source");
241 237 }
242 238
243 239 /*
244 240 * This pulls the path out of a hostpath which may be of the form host:path
245 241 * where path is an absolute path. NOTE: If path turns out to be relative,
246 242 * this returns NULL.
247 243 */
248 244 static char *
249 245 path_part(char *hostpath)
250 246 {
251 247 char *host_end;
252 248
253 249 if ((host_end = strchr(hostpath, ':')) == NULL && hostpath[0] == '/')
254 250 return (hostpath); /* It's already legit. */
255 251
256 252 if (*(host_end+1) == '/')
257 253 return (host_end+1); /* Here's the path part. */
258 254
259 255 return (NULL);
260 256 }
261 257
262 258 /*
263 259 * This scans the filesystems already mounted to see if this remote mount is
264 260 * already in place on the server. This scans the fs_tab for a remote_name
265 261 * exactly matching the client's. It stores the current entry number
266 262 * corresponding to this mount in the static match_mount.
267 263 *
268 264 * Returns:
269 265 * MNT_NOT Couldn't find it.
270 266 * MNT_EXACT This has actually been manually mounted for us
271 267 * MNT_AVAIL This is mounted for the server, but needs to be
272 268 * loopback mounted from the client's perspective.
273 269 */
274 270 static int
275 271 already_mounted(struct vfstab *vfs, int is_local_host, char *client_path,
276 272 char *host_path)
277 273 {
278 274 int i;
279 275
280 276 match_mount = -1;
281 277
282 278 if (fs_tab_used == 0) {
283 279 return (MNT_NOT);
284 280 }
285 281
286 282 for (i = 0; i < fs_tab_used; i++) {
287 283 /*
288 284 * Determine if this has been manually mounted exactly as we
289 285 * require. Begin by finding a mount on our current
290 286 * mountpoint.
291 287 */
292 288 if (strcmp(fs_tab[i]->name, client_path) == 0) {
293 289 /*
294 290 * Now see if it is really the same mount. This isn't
295 291 * smart enough to find mounts on top of mounts, but
296 292 * assuming there is no conspiracy to fool this
297 293 * function, it will be good enough.
298 294 */
299 295 if (is_local_host &&
300 296 strcmp(fs_tab[i]->remote_name, host_path) == 0) {
301 297 match_mount = i;
302 298 return (MNT_EXACT);
303 299 }
304 300 }
305 301
306 302 /* Determine if this mount is available to the server. */
307 303 if (strcmp(fs_tab[i]->remote_name, vfs->vfs_special) == 0) {
308 304 match_mount = i;
309 305 return (MNT_AVAIL);
310 306 }
311 307 }
312 308 return (MNT_NOT);
313 309 }
314 310
315 311 /*
316 312 * This function unmounts all of the loopback mounts created for the client.
317 313 * If no client stuff is mounted, this is completely benign, it finds that
318 314 * nothing is mounted up and returns. It returns "1" for unmounted everything
319 315 * OK and "0" for failure.
320 316 */
321 317 int
322 318 unmount_client()
323 319 {
324 320 int errcode;
325 321 int exit_no;
326 322 int n;
327 323 int retcode = 1;
328 324 int status;
329 325 pid_t pid;
330 326 pid_t pid_return;
331 327
332 328 if (fs_tab_used == 0) {
333 329 return (1);
334 330 }
335 331
336 332 for (n = 0; n < fs_tab_used-1; n++) {
337 333 /* If the filesystem is mounted and this utility did it ... */
338 334 if (fs_tab[n]->cl_mounted && fs_tab[n]->srvr_map) {
339 335 char *arg[3];
340 336
341 337 /* create arglist for umount command */
342 338
343 339 arg[0] = UMOUNT;
344 340 arg[1] = fs_tab[n]->name;
345 341 arg[2] = (char *)NULL;
346 342
347 343 /* flush standard i/o before creating new process */
348 344
349 345 (void) fflush(stderr);
350 346 (void) fflush(stdout);
351 347
352 348 /*
353 349 * create new process to execute command in;
354 350 * vfork is being used to avoid duplicating the parents
355 351 * memory space - this means that the child process may
356 352 * not modify any of the parents memory including the
357 353 * standard i/o descriptors - all the child can do is
358 354 * adjust interrupts and open files as a prelude to a
359 355 * call to exec().
360 356 */
361 357
362 358 pid = vfork();
363 359 if (pid < 0) {
364 360 /* fork failed! */
365 361
366 362 logerr(WRN_BAD_FORK, errno, strerror(errno));
367 363 retcode = 0;
368 364 } else if (pid > 0) {
369 365 /*
370 366 * this is the parent process
371 367 */
372 368
373 369 status = 0;
374 370 pid_return = waitpid(pid, &status, 0);
375 371
376 372 if (pid_return != pid) {
377 373 logerr(WRN_BAD_WAIT, pid, pid_return,
378 374 (unsigned long)status, errno,
379 375 strerror(errno));
380 376 retcode = 0;
381 377 }
382 378
383 379 /*
384 380 * If the child was stopped or killed by a
385 381 * signal or exied with any code but 0, we
386 382 * assume the mount has failed.
387 383 */
388 384
389 385 if (!WIFEXITED(status) ||
390 386 (errcode = WEXITSTATUS(status))) {
391 387 retcode = 0;
392 388 logerr(WRN_FSTAB_UMOUNT,
393 389 fs_tab[n]->name, errcode);
394 390 } else {
395 391 fs_tab[n]->cl_mounted = 0;
396 392 }
397 393 } else {
398 394 /*
399 395 * this is the child process
400 396 */
401 397
402 398 int i;
403 399
404 400 /* reset any signals to default */
405 401
406 402 for (i = 0; i < NSIG; i++) {
407 403 (void) sigset(i, SIG_DFL);
408 404 }
409 405
410 406 /*
411 407 * Redirect output to /dev/null because the
412 408 * umount error message may be confusing to
413 409 * the user.
414 410 */
415 411
416 412 i = open("/dev/null", O_WRONLY);
417 413 if (i >= 0) {
418 414 dup2(2, STDERR_FILENO);
419 415 }
420 416
421 417 /* close all file descriptors except stdio */
422 418
423 419 closefrom(3);
424 420
425 421 exit_no = execve(arg[0], arg, environ);
426 422 _exit(exit_no);
427 423 }
428 424 }
429 425 }
430 426
431 427 return (retcode);
432 428 }
433 429
434 430 /*
435 431 * This function creates the necessary loopback mounts to emulate the client
436 432 * configuration with respect to the server. If this is being run on a
437 433 * standalone or the installation is actually to the local system, this call
438 434 * is benign since srvr_map won't be set anywhere. It returns "1" for mounted
439 435 * everything OK and "0" for failure.
440 436 */
441 437 int
442 438 mount_client()
443 439 {
444 440 int errcode;
445 441 int exit_no;
446 442 int n;
447 443 int retcode = 1;
448 444 int status;
449 445 pid_t pid;
450 446 pid_t pid_return;
451 447
452 448 if (fs_tab_used == 0) {
453 449 return (1);
454 450 }
455 451
456 452 for (n = fs_tab_used-1; n >= 0; n--) {
457 453 /*
458 454 * If the filesystem is mounted (meaning available) and the
459 455 * apparent filesystem can be mapped to a local filesystem
460 456 * AND the local filesystem is not the same as the target
461 457 * filesystem, mount it.
462 458 */
463 459 if (fs_tab[n]->mounted && fs_tab[n]->srvr_map) {
464 460 char *arg[6];
465 461
466 462 /* create arglist for mount command */
467 463
468 464 arg[0] = MOUNT;
469 465 arg[1] = "-F";
470 466 arg[2] = "lofs";
471 467 arg[3] = fs_tab[n]->remote_name;
472 468 arg[4] = fs_tab[n]->name;
473 469 arg[5] = (char *)NULL;
474 470
475 471 /* flush standard i/o before creating new process */
476 472
477 473 (void) fflush(stderr);
478 474 (void) fflush(stdout);
479 475
480 476 /*
481 477 * create new process to execute command in;
482 478 * vfork is being used to avoid duplicating the parents
483 479 * memory space - this means that the child process may
484 480 * not modify any of the parents memory including the
485 481 * standard i/o descriptors - all the child can do is
486 482 * adjust interrupts and open files as a prelude to a
487 483 * call to exec().
488 484 */
489 485
490 486 pid = vfork();
491 487 if (pid < 0) {
492 488 /* fork failed! */
493 489
494 490 logerr(WRN_BAD_FORK, errno, strerror(errno));
495 491 retcode = 0;
496 492 } else if (pid > 0) {
497 493 /*
498 494 * this is the parent process
499 495 */
500 496
501 497 pid_return = waitpid(pid, &status, 0);
502 498
503 499 if (pid_return != pid) {
504 500 logerr(WRN_BAD_WAIT, pid, pid_return,
505 501 (unsigned long)status, errno,
506 502 strerror(errno));
507 503 retcode = 0;
508 504 }
509 505
510 506 /*
511 507 * If the child was stopped or killed by a
512 508 * signal or exied with any code but 0, we
513 509 * assume the mount has failed.
514 510 */
515 511
516 512 if (!WIFEXITED(status) ||
517 513 (errcode = WEXITSTATUS(status))) {
518 514 retcode = 0;
519 515 fs_tab[n]->mnt_failed = 1;
520 516 logerr(WRN_FSTAB_MOUNT,
521 517 fs_tab[n]->name, errcode);
522 518 } else {
523 519 fs_tab[n]->cl_mounted = 1;
524 520 }
525 521 } else {
526 522 /*
527 523 * this is the child process
528 524 */
529 525
530 526 int i;
531 527
532 528 /* reset all signals to default */
533 529
534 530 for (i = 0; i < NSIG; i++) {
535 531 (void) sigset(i, SIG_DFL);
536 532 }
537 533
538 534 /*
539 535 * Redirect output to /dev/null because the
540 536 * mount error message may be confusing to
541 537 * the user.
542 538 */
543 539
544 540 i = open("/dev/null", O_WRONLY);
545 541 if (i >= 0) {
546 542 dup2(i, STDERR_FILENO);
547 543 }
548 544
549 545 /* close all file descriptors except stdio */
550 546
551 547 closefrom(3);
552 548
553 549 exit_no = execve(arg[0], arg, environ);
554 550 _exit(exit_no);
555 551 /*NOTREACHED*/
556 552 }
557 553 }
558 554 }
559 555 return (retcode);
560 556 }
561 557
562 558 /*
563 559 * This function maps path, on a loopback filesystem, back to the real server
564 560 * filesystem. fsys_value is the fs_tab[] entry to which the loopback'd path is
565 561 * mapped. This returns a pointer to a static area. If the result is needed
566 562 * for further processing, it should be strdup()'d or something.
567 563 */
568 564 char *
569 565 server_map(char *path, uint32_t fsys_value)
570 566 {
571 567 static char server_construction[PATH_MAX];
572 568
573 569 if (fs_tab_used == 0) {
574 570 (void) strcpy(server_construction, path);
575 571 } else if (fsys_value < fs_tab_used) {
576 572 (void) snprintf(server_construction,
577 573 sizeof (server_construction),
578 574 "%s%s", fs_tab[fsys_value]->remote_name,
579 575 path+strlen(fs_tab[fsys_value]->name));
580 576 } else {
581 577 (void) strcpy(server_construction, path);
582 578 }
583 579
584 580 return (server_construction);
585 581 }
586 582
587 583 /* This function sets up the standard parts of the fs_tab. */
588 584 static struct fstable *
589 585 fs_tab_init(char *mountp, char *fstype)
590 586 {
591 587 struct fstable *nfte;
592 588
593 589 /* Create the array if necessary. */
594 590 if (fs_list == -1) {
595 591 fs_list = ar_create(ALLOC_CHUNK,
596 592 (unsigned)sizeof (struct fstable),
597 593 "filesystem mount data");
598 594 if (fs_list == -1) {
599 595 progerr(ERR_MALLOC, "fs_list", errno, strerror(errno));
600 596 return (NULL);
601 597 }
602 598 }
603 599
604 600 /*
605 601 * Allocate an fstable entry for this mnttab entry.
606 602 */
607 603 if ((nfte = *(struct fstable **)ar_next_avail(fs_list))
608 604 == NULL) {
609 605 progerr(ERR_MALLOC, "nfte", errno, strerror(errno));
610 606 return (NULL);
611 607 }
612 608
613 609 /*
614 610 * Point fs_tab at the head of the array again, since it may have
615 611 * moved due to realloc in ar_next_avail(). If ar_next_avail() realizes
616 612 * that there is no more room to grow the array, it reallocates the
617 613 * array. Because we stored pointer to that array in fs_tab, we need
618 614 * to make sure that it is updated as well.
619 615 */
620 616 if ((fs_tab = (struct fstable **)ar_get_head(fs_list)) == NULL) {
621 617 progerr(ERR_NOTABLE, "mount", MOUNT_TABLE, strerror(errno));
622 618 return (NULL);
623 619 }
624 620
625 621 /*
626 622 * Get the length of the 'mount point' name.
627 623 */
628 624 nfte->namlen = strlen(mountp);
629 625 /*
630 626 * Allocate space for the 'mount point' name.
631 627 */
632 628 if ((nfte->name = malloc(nfte->namlen+1)) == NULL) {
633 629 progerr(ERR_MALLOC, "name", errno, strerror(errno));
634 630 return (NULL);
635 631 }
636 632 (void) strcpy(nfte->name, mountp);
637 633
638 634 if ((nfte->fstype = malloc(strlen(fstype)+1)) == NULL) {
639 635 progerr(ERR_MALLOC, "fstype", errno, strerror(errno));
640 636 return (NULL);
641 637 }
642 638 (void) strcpy(nfte->fstype, fstype);
643 639
644 640 fs_tab_used++;
645 641
646 642 return (nfte);
647 643 }
648 644
649 645 /* This function frees all memory associated with the filesystem table. */
650 646 void
651 647 fs_tab_free(void)
652 648 {
653 649 int n;
654 650
655 651 if (fs_tab_used == 0) {
656 652 return;
657 653 }
658 654
659 655 for (n = 0; n < fs_tab_used; n++) {
660 656 free(fs_tab[n]->fstype);
661 657 free(fs_tab[n]->name);
662 658 free(fs_tab[n]->remote_name);
663 659 }
664 660
665 661 ar_free(fs_list);
666 662 }
667 663
668 664 /* This function scans a string of mount options for a specific keyword. */
669 665 static int
670 666 hasopt(char *options, char *keyword)
671 667 {
672 668 char vfs_options[VFS_LINE_MAX], *optptr;
673 669
674 670 if (!options) {
675 671 (void) strcpy(vfs_options, "ro");
676 672 } else {
677 673 (void) strcpy(vfs_options, options);
678 674 }
679 675
680 676 while (optptr = strrchr(vfs_options, ',')) {
681 677 *optptr++ = '\0';
682 678
683 679 if (strcmp(optptr, keyword) == 0)
684 680 return (1);
685 681 }
686 682
687 683 /* Now deal with the remainder. */
688 684 if (strcmp(vfs_options, keyword) == 0)
689 685 return (1);
690 686
691 687 return (0);
692 688 }
693 689
694 690 /*
695 691 * This function constructs a new filesystem table (fs_tab[]) entry based on
696 692 * an /etc/mnttab entry. When it returns, the new entry has been inserted
697 693 * into fs_tab[].
698 694 */
699 695 static int
700 696 construct_mt(struct mnttab *mt)
701 697 {
702 698 struct fstable *nfte;
703 699
704 700 /*
705 701 * Initialize fstable structure and make the standard entries.
706 702 */
↓ open down ↓ |
466 lines elided |
↑ open up ↑ |
707 703 if ((nfte = fs_tab_init(mt->mnt_mountp, mt->mnt_fstype)) == NULL)
708 704 return (1);
709 705
710 706 /*
711 707 * See if this is served from another host.
712 708 * Testing the type is cheap; finding the hostname is not.
713 709 * At this point, we're using the REAL mnttab; since we're not
714 710 * allowed to mount ourself with "NFS", "NFS" must be remote.
715 711 * The automount will translate "nfs:self" to a lofs mount.
716 712 */
717 - if (strcmp(mt->mnt_fstype, MNTTYPE_AUTO) == 0 ||
713 + if (strcmp(mt->mnt_fstype, MNTTYPE_AUTOFS) == 0 ||
718 714 strcmp(mt->mnt_fstype, MNTTYPE_NFS) == 0 ||
719 715 is_remote_src(mt->mnt_special) == REAL_REMOTE)
720 716 nfte->remote = 1;
721 717 else
722 718 nfte->remote = 0;
723 719
724 720 /* It's mounted now (by definition), so we don't have to remap it. */
725 721 nfte->srvr_map = 0;
726 722 nfte->mounted = 1;
727 723
728 724 nfte->remote_name = strdup(mt->mnt_special);
729 725
730 726 /*
731 727 * This checks the mount commands which establish the most
732 728 * basic level of access. Later further tests may be
733 729 * necessary to fully qualify this. We set this bit
734 730 * preliminarily because we have access to the mount data
735 731 * now.
736 732 */
737 733 nfte->writeable = 0; /* Assume read-only. */
738 734 if (hasmntopt(mt, MNTOPT_RO) == NULL) {
739 735 nfte->writeable = 1;
740 736 if (!(nfte->remote))
741 737 /*
742 738 * There's no network involved, so this
743 739 * assessment is confirmed.
744 740 */
745 741 nfte->write_tested = 1;
746 742 } else
747 743 /* read-only is read-only */
748 744 nfte->write_tested = 1;
749 745
750 746 /* Is this coming to us from a server? */
751 747 if (nfte->remote && !(nfte->writeable))
752 748 nfte->served = 1;
753 749
754 750 return (0);
755 751 }
756 752
757 753 /*
758 754 * This function modifies an existing fs_tab[] entry. It was found mounted up
759 755 * exactly the way we would have mounted it in mount_client() only at the
760 756 * time we didn't know it was for the client. Now we do, so we're setting the
761 757 * various permissions to conform to the client view.
762 758 */
763 759 static void
764 760 mod_existing(struct vfstab *vfsent, int fstab_entry, int is_remote)
765 761 {
766 762 /*
767 763 * Establish whether the client will see this as served.
768 764 */
769 765 if (is_remote && hasopt(vfsent->vfs_mntopts, MNTOPT_RO))
770 766 fs_tab[fstab_entry]->served = 1;
771 767
772 768 fs_tab[fstab_entry]->cl_mounted = 1;
773 769 }
774 770
775 771 /*
776 772 * This function constructs a new fs_tab[] entry based on
777 773 * an /etc/vfstab entry. When it returns, the new entry has been inserted
778 774 * into fstab[].
779 775 */
780 776 static int
781 777 construct_vfs(struct vfstab *vfsent, char *client_path, char *link_name,
782 778 int is_remote, int mnt_stat)
783 779 {
784 780 int use_link;
785 781 struct fstable *nfte;
786 782
787 783 if ((nfte = fs_tab_init(client_path, vfsent->vfs_fstype)) == NULL)
788 784 return (1);
789 785
790 786 nfte->remote = (is_remote == REAL_REMOTE);
791 787
792 788 /*
793 789 * The file system mounted on the client may or may not be writeable.
794 790 * So we hand it over to fsys() to evaluate. This will have the same
795 791 * read/write attributes as the corresponding mounted filesystem.
796 792 */
797 793 use_link = 0;
798 794 if (nfte->remote) {
799 795 /*
800 796 * Deal here with mount points actually on a system remote
801 797 * from the server.
802 798 */
803 799 if (mnt_stat == MNT_NOT) {
804 800 /*
805 801 * This filesystem isn't in the current mount table
806 802 * meaning it isn't mounted, the current host can't
807 803 * write to it and there's no point to mapping it for
808 804 * the server.
809 805 */
810 806 link_name = NULL;
811 807 nfte->mounted = 0;
812 808 nfte->srvr_map = 0;
813 809 nfte->writeable = 0;
814 810 } else { /* It's MNT_AVAIL. */
815 811 /*
816 812 * This filesystem is associated with a current
817 813 * mountpoint. Since it's mounted, it needs to be
818 814 * remapped and it is writable if the real mounted
819 815 * filesystem is writeable.
820 816 */
821 817 use_link = 1;
822 818 link_name = strdup(fs_tab[match_mount]->name);
823 819 nfte->mounted = 1;
824 820 nfte->srvr_map = 1;
825 821 nfte->writeable = fs_tab[match_mount]->writeable;
826 822 nfte->write_tested = fs_tab[match_mount]->write_tested;
827 823 }
828 824 } else { /* local filesystem */
829 825 use_link = 1;
830 826 nfte->mounted = 1;
831 827 nfte->srvr_map = 1;
832 828 nfte->writeable = fs_tab[fsys(link_name)]->writeable;
833 829 nfte->write_tested = 1;
834 830 }
835 831
836 832 /*
837 833 * Now we establish whether the client will see this as served.
838 834 */
839 835 if (is_remote && hasopt(vfsent->vfs_mntopts, MNTOPT_RO))
840 836 nfte->served = 1;
841 837
842 838 if (use_link) {
843 839 nfte->remote_name = link_name;
844 840 } else {
845 841 nfte->remote_name = strdup(vfsent->vfs_special);
846 842 }
847 843
848 844 return (0);
849 845 }
850 846
851 847 /*
852 848 * get_mntinfo - get the mount table, now dynamically allocated. Returns 0 if
853 849 * no problem and 1 if there's a fatal error.
854 850 */
855 851 int
856 852 get_mntinfo(int map_client, char *vfstab_file)
857 853 {
858 854 static char *rn = "/";
859 855 FILE *pp;
860 856 struct mnttab mtbuf;
861 857 struct mnttab *mt = &mtbuf;
862 858 char *install_root;
863 859 int is_remote;
864 860
865 861 /*
866 862 * Open the mount table for the current host and establish a global
867 863 * table that holds data about current mount status.
868 864 */
869 865 if ((pp = setmntent(MOUNT_TABLE, "r")) == NULL) {
870 866 progerr(ERR_NOTABLE, "mount", MOUNT_TABLE, strerror(errno));
871 867 return (1);
872 868 }
873 869
874 870 /*
875 871 * First, review the mounted filesystems on the managing host. This
876 872 * may also be the target host but we haven't decided that for sure
877 873 * yet.
878 874 */
879 875 while (!getmntent(pp, mt))
880 876 if (construct_mt(mt))
881 877 return (1);
882 878
883 879 (void) endmntent(pp);
884 880
885 881 /*
886 882 * Now, we see if this installation is to a client. If it is, we scan
887 883 * the client's vfstab to determine what filesystems are
888 884 * inappropriate to write to. This simply adds the vfstab entries
889 885 * representing what will be remote file systems for the client.
890 886 * Everything that isn't remote to the client is already accounted
891 887 * for in the fs_tab[] so far. If the remote filesystem is really on
892 888 * this server, we will write through to the server from this client.
893 889 */
894 890 install_root = get_inst_root();
895 891 if (install_root && strcmp(install_root, "/") != 0 && map_client) {
896 892 /* OK, this is a legitimate remote client. */
897 893 struct vfstab vfsbuf;
898 894 struct vfstab *vfs = &vfsbuf;
899 895 char VFS_TABLE[PATH_MAX];
900 896
901 897 /*
902 898 * Since we use the fsys() function later, and it depends on
903 899 * an ordered list, we have to sort the list here.
904 900 */
905 901 qsort(fs_tab, fs_tab_used,
906 902 sizeof (struct fstable *), fs_tab_ent_comp);
907 903
908 904 /*
909 905 * Here's where the vfstab for the target is. If we can get
910 906 * to it, we'll scan it for what the client will see as
911 907 * remote filesystems, otherwise, we'll just skip this.
912 908 */
913 909 if (vfstab_file) {
914 910 (void) snprintf(VFS_TABLE, sizeof (VFS_TABLE), "%s",
915 911 vfstab_file);
916 912 } else {
917 913 (void) snprintf(VFS_TABLE, sizeof (VFS_TABLE), "%s%s",
918 914 install_root, VFSTAB);
919 915 }
920 916
921 917 if (access(VFS_TABLE, R_OK) == 0) {
922 918 char *link_name;
923 919
924 920 /*
925 921 * Open the vfs table for the target host.
926 922 */
927 923 if ((pp = setmntent(VFS_TABLE, "r")) == NULL) {
928 924 progerr(ERR_NOTABLE, "vfs", VFS_TABLE,
929 925 strerror(errno));
930 926 return (1);
931 927 }
932 928
933 929 /* Do this for each entry in the vfstab. */
934 930 while (!getvfsent(pp, vfs)) {
935 931 char client_mountp[PATH_MAX];
936 932 int mnt_stat;
937 933
938 934 /*
939 935 * We put it into the fs table if it's
940 936 * remote mounted (even from this server) or
941 937 * loopback mounted from the client's point
942 938 * of view.
943 939 */
944 940 if (!(is_remote =
945 941 is_remote_src(vfs->vfs_special)) &&
946 942 strcmp(vfs->vfs_fstype, MNTTYPE_LOFS) !=
947 943 0)
948 944 continue; /* not interesting */
949 945
950 946 /*
951 947 * Construct client_mountp by prepending the
952 948 * install_root to the 'mount point' name.
953 949 */
954 950 if (strcmp(vfs->vfs_mountp, "/") == 0) {
955 951 (void) strcpy(client_mountp,
↓ open down ↓ |
228 lines elided |
↑ open up ↑ |
956 952 install_root);
957 953 } else {
958 954 (void) snprintf(client_mountp,
959 955 sizeof (client_mountp), "%s%s",
960 956 install_root, vfs->vfs_mountp);
961 957 }
962 958
963 959 /*
964 960 * We also skip the entry if the vfs_special
965 961 * path and the client_path are the same.
966 - * There's no need to mount it, it's just a
967 - * cachefs optimization that mounts a
968 - * directory over itself from this server.
969 962 */
970 963 if ((is_remote == SELF_SERVE) &&
971 964 strcmp(path_part(vfs->vfs_special),
972 965 client_mountp) == 0)
973 966 continue;
974 967
975 968 /* Determine if this is already mounted. */
976 969 link_name = strdup(path_part(vfs->vfs_special));
977 970 mnt_stat = already_mounted(vfs,
978 971 (is_remote != REAL_REMOTE), client_mountp,
979 972 link_name);
980 973
981 974 if (mnt_stat == MNT_EXACT) {
982 975 mod_existing(vfs, match_mount,
983 976 is_remote);
984 977 } else { /* MNT_NOT */
985 978 if (construct_vfs(vfs, client_mountp,
986 979 link_name, is_remote, mnt_stat)) {
987 980 return (1);
988 981 }
989 982 }
990 983 }
991 984 (void) endmntent(pp);
992 985 } /* end of if(access()) */
993 986 } /* end of if(install_root) */
994 987
995 988 /* This next one may look stupid, but it can really happen. */
996 989 if (fs_tab_used <= 0) {
997 990 progerr(ERR_MNT_NOMOUNTS);
998 991 return (1);
999 992 }
1000 993
1001 994 /*
1002 995 * Now that we have the complete list of mounted (or virtually
1003 996 * mounted) filesystems, we sort the mountpoints in reverse order
1004 997 * based on the length of the 'mount point' name.
1005 998 */
1006 999 qsort(fs_tab, fs_tab_used, sizeof (struct fstable *), fs_tab_ent_comp);
1007 1000 if (strcmp(fs_tab[fs_tab_used-1]->name, rn) != 0) {
1008 1001 progerr(ERR_MNT_NOROOT, fs_tab[fs_tab_used-1]->name, rn, errno,
1009 1002 strerror(errno));
1010 1003 return (1);
1011 1004 } else {
1012 1005 return (0);
1013 1006 }
1014 1007 }
1015 1008
1016 1009 /*
1017 1010 * This function supports dryrun mode by allowing the filesystem table to be
1018 1011 * directly loaded from the continuation file.
1019 1012 */
1020 1013 int
1021 1014 load_fsentry(struct fstable *fs_entry, char *name, char *fstype,
1022 1015 char *remote_name)
1023 1016 {
1024 1017 struct fstable *nfte;
1025 1018
1026 1019 if ((nfte = fs_tab_init(name, fstype)) == NULL)
1027 1020 return (1);
1028 1021
1029 1022 /* Grab the name and fstype from the new structure. */
1030 1023 fs_entry->name = nfte->name;
1031 1024 fs_entry->fstype = nfte->fstype;
1032 1025
1033 1026 /* Copy the basic structure into place. */
1034 1027 (void) memcpy(nfte, fs_entry, sizeof (struct fstable));
1035 1028
1036 1029 /*
1037 1030 * Allocate space for the 'special' name.
1038 1031 */
1039 1032 if ((nfte->remote_name = malloc(strlen(remote_name)+1)) == NULL) {
1040 1033 progerr(ERR_MALLOC, "remote_name", errno, strerror(errno));
1041 1034 return (1);
1042 1035 }
1043 1036
1044 1037 (void) strcpy(nfte->remote_name, remote_name);
1045 1038
1046 1039 return (0);
1047 1040 }
1048 1041
1049 1042 /*
1050 1043 * Given a path, return the table index of the filesystem the file apparently
1051 1044 * resides on. This doesn't put any time into resolving filesystems that
1052 1045 * refer to other filesystems. It just returns the entry containing this
1053 1046 * path.
1054 1047 */
1055 1048 uint32_t
1056 1049 fsys(char *path)
1057 1050 {
1058 1051 register int i;
1059 1052 char real_path[PATH_MAX];
1060 1053 char path_copy[PATH_MAX];
1061 1054 char *path2use;
1062 1055 char *cp;
1063 1056 int pathlen;
1064 1057 boolean_t found = B_FALSE;
1065 1058
1066 1059 /*
1067 1060 * The loop below represents our best effort to identify real path of
1068 1061 * a file, which doesn't need to exist. realpath() returns error for
1069 1062 * nonexistent path, therefore we need to cut off trailing components
1070 1063 * of path until we get path which exists and can be resolved by
1071 1064 * realpath(). Lookup of "/dir/symlink/nonexistent-file" would fail
1072 1065 * to resolve symlink without this.
1073 1066 */
1074 1067 (void) strlcpy(path_copy, path, PATH_MAX);
1075 1068 for (cp = dirname(path_copy); strlen(cp) > 1; cp = dirname(cp)) {
1076 1069 if (realpath(cp, real_path) != NULL) {
1077 1070 found = B_TRUE;
1078 1071 break;
1079 1072 } else if (errno != ENOENT)
1080 1073 break;
1081 1074 }
1082 1075 if (found)
1083 1076 path2use = real_path;
1084 1077 else
1085 1078 /* fall back to original path in case of unexpected failure */
1086 1079 path2use = path;
1087 1080
1088 1081 pathlen = strlen(path2use);
1089 1082
1090 1083 /*
1091 1084 * The following algorithm scans the list of attached file systems
1092 1085 * for the one containing path. At this point the file names in
1093 1086 * fs_tab[] are sorted by decreasing length to facilitate the scan.
1094 1087 * The first for() scans past all the file system names too short to
1095 1088 * contain path. The second for() does the actual string comparison.
1096 1089 * It tests first to assure that the comparison is against a complete
1097 1090 * token by assuring that the end of the filesystem name aligns with
1098 1091 * the end of a token in path2use (ie: '/' or NULL) then it does a
1099 1092 * string compare. -- JST
1100 1093 */
1101 1094
1102 1095 if (fs_tab_used == 0) {
1103 1096 return (-1);
1104 1097 }
1105 1098
1106 1099 for (i = 0; i < fs_tab_used; i++)
1107 1100 if (fs_tab[i] == NULL)
1108 1101 continue;
1109 1102 else if (fs_tab[i]->namlen <= pathlen)
1110 1103 break;
1111 1104 for (; i < fs_tab_used; i++) {
1112 1105 int fs_namelen;
1113 1106 char term_char;
1114 1107
1115 1108 if (fs_tab[i] == NULL)
1116 1109 continue;
1117 1110
1118 1111 fs_namelen = fs_tab[i]->namlen;
1119 1112 term_char = path2use[fs_namelen];
1120 1113
1121 1114 /*
1122 1115 * If we're putting the file "/a/kernel" into the filesystem
1123 1116 * "/a", then fs_namelen == 2 and term_char == '/'. If, we're
1124 1117 * putting "/etc/termcap" into "/", fs_namelen == 1 and
1125 1118 * term_char (unfortunately) == 'e'. In the case of
1126 1119 * fs_namelen == 1, we check to make sure the filesystem is
1127 1120 * "/" and if it is, we have a guaranteed fit, otherwise we
1128 1121 * do the string compare. -- JST
1129 1122 */
1130 1123 if ((fs_namelen == 1 && *(fs_tab[i]->name) == '/') ||
1131 1124 ((term_char == '/' || term_char == NULL) &&
1132 1125 strncmp(fs_tab[i]->name, path2use, fs_namelen) == 0)) {
1133 1126 return (i);
1134 1127 }
1135 1128 }
1136 1129
1137 1130 /*
1138 1131 * It only gets here if the root filesystem is fundamentally corrupt.
1139 1132 * (This can happen!)
1140 1133 */
1141 1134 progerr(ERR_FSYS_FELLOUT, path2use);
1142 1135
1143 1136 return (-1);
1144 1137 }
1145 1138
1146 1139 /*
1147 1140 * This function returns the entry in the fs_tab[] corresponding to the
1148 1141 * actual filesystem of record. It won't return a loopback filesystem entry,
1149 1142 * it will return the filesystem that the loopback filesystem is mounted
1150 1143 * over.
1151 1144 */
1152 1145 uint32_t
1153 1146 resolved_fsys(char *path)
1154 1147 {
1155 1148 int i = -1;
1156 1149 char path2use[PATH_MAX];
1157 1150
1158 1151 (void) strcpy(path2use, path);
1159 1152
1160 1153 /* If this isn't a "real" filesystem, resolve the map. */
1161 1154 do {
1162 1155 (void) strcpy(path2use, server_map(path2use, i));
1163 1156 i = fsys(path2use);
1164 1157 } while (fs_tab[i]->srvr_map);
1165 1158
1166 1159 return (i);
1167 1160 }
1168 1161
1169 1162 /*
1170 1163 * This function returns the srvr_map status based upon the fs_tab entry
1171 1164 * number. This tells us if the server path constructed from the package
1172 1165 * install root is really the target filesystem.
1173 1166 */
1174 1167 int
1175 1168 use_srvr_map_n(uint32_t n)
1176 1169 {
1177 1170 return ((int)fs_tab[n]->srvr_map);
1178 1171 }
1179 1172
1180 1173 /*
1181 1174 * This function returns the mount status based upon the fs_tab entry
1182 1175 * number. This tells us if there is any hope of gaining access
1183 1176 * to this file system.
1184 1177 */
1185 1178 int
1186 1179 is_mounted_n(uint32_t n)
1187 1180 {
1188 1181 return ((int)fs_tab[n]->mounted);
1189 1182 }
1190 1183
1191 1184 /*
1192 1185 * is_fs_writeable_n - given an fstab index, return 1
1193 1186 * if it's writeable, 0 if read-only.
1194 1187 */
1195 1188 int
1196 1189 is_fs_writeable_n(uint32_t n)
1197 1190 {
1198 1191 /*
1199 1192 * If the write access permissions haven't been confirmed, do that
1200 1193 * now. Note that the only reason we need to do the special check is
1201 1194 * in the case of an NFS mount (remote) because we can't determine if
1202 1195 * root has access in any other way.
1203 1196 */
1204 1197 if (fs_tab[n]->remote && fs_tab[n]->mounted &&
1205 1198 !fs_tab[n]->write_tested) {
1206 1199 if (fs_tab[n]->writeable && !really_write(fs_tab[n]->name))
1207 1200 fs_tab[n]->writeable = 0; /* not really */
1208 1201
1209 1202 fs_tab[n]->write_tested = 1; /* confirmed */
1210 1203 }
1211 1204
1212 1205 return ((int)fs_tab[n]->writeable);
1213 1206 }
1214 1207
1215 1208 /*
1216 1209 * is_remote_fs_n - given an fstab index, return 1
1217 1210 * if it's a remote filesystem, 0 if local.
1218 1211 *
1219 1212 * Note: Upon entry, a valid fsys() is required.
1220 1213 */
1221 1214 int
1222 1215 is_remote_fs_n(uint32_t n)
1223 1216 {
1224 1217 return ((int)fs_tab[n]->remote);
1225 1218 }
1226 1219
1227 1220 /* index-driven is_served() */
1228 1221 int
1229 1222 is_served_n(uint32_t n)
1230 1223 {
1231 1224 return ((int)fs_tab[n]->served);
1232 1225 }
1233 1226
1234 1227 /*
1235 1228 * This returns the number of blocks available on the indicated filesystem.
1236 1229 *
1237 1230 * Note: Upon entry, a valid fsys() is required.
1238 1231 */
1239 1232 fsblkcnt_t
1240 1233 get_blk_free_n(uint32_t n)
1241 1234 {
1242 1235 return (fs_tab[n]->bfree);
1243 1236 }
1244 1237
1245 1238 /*
1246 1239 * This returns the number of blocks being used on the indicated filesystem.
1247 1240 *
1248 1241 * Note: Upon entry, a valid fsys() is required.
1249 1242 */
1250 1243 fsblkcnt_t
1251 1244 get_blk_used_n(uint32_t n)
1252 1245 {
1253 1246 return (fs_tab[n]->bused);
1254 1247 }
1255 1248
1256 1249 /*
1257 1250 * This returns the number of inodes available on the indicated filesystem.
1258 1251 *
1259 1252 * Note: Upon entry, a valid fsys() is required.
1260 1253 */
1261 1254 fsblkcnt_t
1262 1255 get_inode_free_n(uint32_t n)
1263 1256 {
1264 1257 return (fs_tab[n]->ffree);
1265 1258 }
1266 1259
1267 1260 /*
1268 1261 * This returns the number of inodes being used on the indicated filesystem.
1269 1262 *
1270 1263 * Note: Upon entry, a valid fsys() is required.
1271 1264 */
1272 1265 fsblkcnt_t
1273 1266 get_inode_used_n(uint32_t n)
1274 1267 {
1275 1268 return (fs_tab[n]->fused);
1276 1269 }
1277 1270
1278 1271 /*
1279 1272 * Sets the number of blocks being used on the indicated filesystem.
1280 1273 *
1281 1274 * Note: Upon entry, a valid fsys() is required.
1282 1275 */
1283 1276 void
1284 1277 set_blk_used_n(uint32_t n, fsblkcnt_t value)
1285 1278 {
1286 1279 fs_tab[n]->bused = value;
1287 1280 }
1288 1281
1289 1282 /* Get the filesystem block size. */
1290 1283 fsblkcnt_t
1291 1284 get_blk_size_n(uint32_t n)
1292 1285 {
1293 1286 return (fs_tab[n]->bsize);
1294 1287 }
1295 1288
1296 1289 /* Get the filesystem fragment size. */
1297 1290 fsblkcnt_t
1298 1291 get_frag_size_n(uint32_t n)
1299 1292 {
1300 1293 return (fs_tab[n]->bsize);
1301 1294 }
1302 1295
1303 1296 /*
1304 1297 * This returns the name of the indicated filesystem.
1305 1298 */
1306 1299 char *
1307 1300 get_fs_name_n(uint32_t n)
1308 1301 {
1309 1302 if (fs_tab_used == 0) {
1310 1303 return (NULL);
1311 1304 } else if (n >= fs_tab_used) {
1312 1305 return (NULL);
1313 1306 } else {
1314 1307 return (fs_tab[n]->name);
1315 1308 }
1316 1309 }
1317 1310
1318 1311 /*
1319 1312 * This returns the remote name of the indicated filesystem.
1320 1313 *
1321 1314 * Note: Upon entry, a valid fsys() is required.
1322 1315 */
1323 1316 char *
1324 1317 get_source_name_n(uint32_t n)
1325 1318 {
1326 1319 return (fs_tab[n]->remote_name);
1327 1320 }
1328 1321
1329 1322 /*
1330 1323 * This function returns the srvr_map status based upon the path.
1331 1324 */
1332 1325 int
1333 1326 use_srvr_map(char *path, uint32_t *fsys_value)
1334 1327 {
1335 1328 if (*fsys_value == BADFSYS)
1336 1329 *fsys_value = fsys(path);
1337 1330
1338 1331 return (use_srvr_map_n(*fsys_value));
1339 1332 }
1340 1333
1341 1334 /*
1342 1335 * This function returns the mount status based upon the path.
1343 1336 */
1344 1337 int
1345 1338 is_mounted(char *path, uint32_t *fsys_value)
1346 1339 {
1347 1340 if (*fsys_value == BADFSYS)
1348 1341 *fsys_value = fsys(path);
1349 1342
1350 1343 return (is_mounted_n(*fsys_value));
1351 1344 }
1352 1345
1353 1346 /*
1354 1347 * is_fs_writeable - given a cfent entry, return 1
1355 1348 * if it's writeable, 0 if read-only.
1356 1349 *
1357 1350 * Note: Upon exit, a valid fsys() is guaranteed. This is
1358 1351 * an interface requirement.
1359 1352 */
1360 1353 int
1361 1354 is_fs_writeable(char *path, uint32_t *fsys_value)
1362 1355 {
1363 1356 if (*fsys_value == BADFSYS)
1364 1357 *fsys_value = fsys(path);
1365 1358
1366 1359 return (is_fs_writeable_n(*fsys_value));
1367 1360 }
1368 1361
1369 1362 /*
1370 1363 * is_remote_fs - given a cfent entry, return 1
1371 1364 * if it's a remote filesystem, 0 if local.
1372 1365 *
1373 1366 * Also Note: Upon exit, a valid fsys() is guaranteed. This is
1374 1367 * an interface requirement.
1375 1368 */
1376 1369 int
1377 1370 is_remote_fs(char *path, uint32_t *fsys_value)
1378 1371 {
1379 1372 if (*fsys_value == BADFSYS)
1380 1373 *fsys_value = fsys(path);
1381 1374
1382 1375 return (is_remote_fs_n(*fsys_value));
1383 1376 }
1384 1377
1385 1378 /*
1386 1379 * This function returns the served status of the filesystem. Served means a
1387 1380 * client is getting this file from a server and it is not writeable by the
1388 1381 * client. It has nothing to do with whether or not this particular operation
1389 1382 * (eg: pkgadd or pkgrm) will be writing to it.
1390 1383 */
1391 1384 int
1392 1385 is_served(char *path, uint32_t *fsys_value)
1393 1386 {
1394 1387 if (*fsys_value == BADFSYS)
1395 1388 *fsys_value = fsys(path);
1396 1389
1397 1390 return (is_served_n(*fsys_value));
1398 1391 }
1399 1392
1400 1393 /*
1401 1394 * get_remote_path - given a filesystem table index, return the
1402 1395 * path of the filesystem on the remote system. Otherwise,
1403 1396 * return NULL if it's a local filesystem.
1404 1397 */
1405 1398 char *
1406 1399 get_remote_path(uint32_t n)
1407 1400 {
1408 1401 char *p;
1409 1402
1410 1403 if (!is_remote_fs_n(n))
1411 1404 return (NULL); /* local */
1412 1405 p = strchr(fs_tab[n]->remote_name, ':');
1413 1406 if (!p)
1414 1407 p = fs_tab[n]->remote_name; /* Loopback */
1415 1408 else
1416 1409 p++; /* remote */
1417 1410 return (p);
1418 1411 }
1419 1412
1420 1413 /*
1421 1414 * get_mount_point - given a filesystem table index, return the
1422 1415 * path of the mount point. Otherwise,
1423 1416 * return NULL if it's a local filesystem.
1424 1417 */
1425 1418 char *
1426 1419 get_mount_point(uint32_t n)
1427 1420 {
1428 1421 if (!is_remote_fs_n(n))
1429 1422 return (NULL); /* local */
1430 1423 return (fs_tab[n]->name);
1431 1424 }
1432 1425
1433 1426 struct fstable *
1434 1427 get_fs_entry(uint32_t n)
1435 1428 {
1436 1429 if (fs_tab_used == 0) {
1437 1430 return (NULL);
1438 1431 } else if (n >= fs_tab_used) {
1439 1432 return (NULL);
1440 1433 } else {
1441 1434 return (fs_tab[n]);
1442 1435 }
1443 1436 }
↓ open down ↓ |
465 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX