1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2011 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Eclipse Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.eclipse.org/org/documents/epl-v10.html * 11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * Glenn Fowler <gsf@research.att.com> * 18 * David Korn <dgk@research.att.com> * 19 * Phong Vo <kpv@research.att.com> * 20 * * 21 ***********************************************************************/ 22 #pragma prototyped 23 /* 24 * Glenn Fowler 25 * AT&T Research 26 * 27 * mounted filesystem scan support 28 * where are the standards when you really need them 29 */ 30 31 #include <ast.h> 32 #include <mnt.h> 33 #include <ls.h> 34 35 #if _lib_mntopen && _lib_mntread && _lib_mntclose 36 37 NoN(mnt) 38 39 #else 40 41 /* 42 * the original interface just had mode 43 */ 44 45 #define FIXARGS(p,m,s) do { \ 46 if ((p)&&*(p)!='/') { \ 47 mode = p; \ 48 path = 0; \ 49 } \ 50 if (!path) \ 51 path = s; \ 52 } while (0) 53 typedef struct 54 { 55 Mnt_t mnt; 56 char buf[128]; 57 #if __CYGWIN__ 58 char typ[128]; 59 char opt[128]; 60 #endif 61 } Header_t; 62 63 #if __CYGWIN__ 64 #include <ast_windows.h> 65 #endif 66 67 static void 68 set(register Header_t* hp, const char* fs, const char* dir, const char* type, const char* options) 69 { 70 const char* x; 71 72 hp->mnt.flags = 0; 73 if (x = (const char*)strchr(fs, ':')) 74 { 75 if (*++x && *x != '\\') 76 { 77 hp->mnt.flags |= MNT_REMOTE; 78 if (*x == '(') 79 { 80 fs = x; 81 type = "auto"; 82 } 83 } 84 } 85 else if (x = (const char*)strchr(fs, '@')) 86 { 87 hp->mnt.flags |= MNT_REMOTE; 88 sfsprintf(hp->buf, sizeof(hp->buf) - 1, "%s:%*.*s", x + 1, x - fs, x - fs, fs); 89 fs = (const char*)hp->buf; 90 } 91 else if (strmatch(type, "[aAnN][fF][sS]*")) 92 hp->mnt.flags |= MNT_REMOTE; 93 if (streq(fs, "none")) 94 fs = dir; 95 hp->mnt.fs = (char*)fs; 96 hp->mnt.dir = (char*)dir; 97 hp->mnt.type = (char*)type; 98 hp->mnt.options = (char*)options; 99 #if __CYGWIN__ 100 if (streq(type, "system") || streq(type, "user")) 101 { 102 char* s; 103 int mode; 104 DWORD vser; 105 DWORD flags; 106 DWORD len; 107 char drive[4]; 108 109 mode = SetErrorMode(SEM_FAILCRITICALERRORS); 110 drive[0] = fs[0]; 111 drive[1] = ':'; 112 drive[2] = '\\'; 113 drive[3] = 0; 114 if (GetVolumeInformation(drive, 0, 0, &vser, &len, &flags, hp->typ, sizeof(hp->typ) - 1)) 115 hp->mnt.type = hp->typ; 116 else 117 flags = 0; 118 SetErrorMode(mode); 119 s = strcopy(hp->mnt.options = hp->opt, type); 120 s = strcopy(s, ",ignorecase"); 121 if (options) 122 { 123 *s++ = ','; 124 strcpy(s, options); 125 } 126 } 127 #endif 128 } 129 130 #undef MNT_REMOTE 131 132 #if _sys_mount && ( _lib_getfsstat || _lib_getmntinfo ) 133 134 /* 135 * 4.4 bsd getmntinfo 136 * 137 * what a crappy interface 138 * data returned in static buffer -- ok 139 * big chunk of allocated memory that cannot be freed -- come on 140 * *and* netbsd changed the interface somewhere along the line 141 * private interface? my bad -- public interface? par for the bsd course 142 * 143 * we assume getfsstat may suffer the same statfs/statvfs confusion 144 */ 145 146 #include <sys/param.h> /* expect some macro redefinitions here */ 147 #include <sys/mount.h> 148 149 #if _lib_getfsstat 150 #if _lib_getfsstat_statvfs 151 #define statfs statvfs 152 #define f_flags f_flag 153 #endif 154 #else 155 #if _lib_getmntinfo_statvfs 156 #define statfs statvfs 157 #define f_flags f_flag 158 #endif 159 #endif 160 161 typedef struct 162 { 163 Header_t hdr; 164 struct statfs* next; 165 struct statfs* last; 166 char opt[256]; 167 #if _lib_getfsstat 168 struct statfs buf[1]; 169 #endif 170 } Handle_t; 171 172 #ifdef MFSNAMELEN 173 #define TYPE(f) ((f)->f_fstypename) 174 #else 175 #ifdef INITMOUNTNAMES 176 #define TYPE(f) ((char*)type[(f)->f_type]) 177 static const char* type[] = INITMOUNTNAMES; 178 #else 179 #if _sys_fs_types 180 #define TYPE(f) ((char*)mnt_names[(f)->f_type]) 181 #include <sys/fs_types.h> 182 #else 183 #define TYPE(f) (strchr((f)->f_mntfromname,':')?"nfs":"ufs") 184 #endif 185 #endif 186 #endif 187 188 static struct Mnt_options_t 189 { 190 unsigned long flag; 191 const char* name; 192 } 193 options[] = 194 { 195 #ifdef MNT_RDONLY 196 MNT_RDONLY, "rdonly", 197 #endif 198 #ifdef MNT_SYNCHRONOUS 199 MNT_SYNCHRONOUS,"synchronous", 200 #endif 201 #ifdef MNT_NOEXEC 202 MNT_NOEXEC, "noexec", 203 #endif 204 #ifdef MNT_NOSUID 205 MNT_NOSUID, "nosuid", 206 #endif 207 #ifdef MNT_NODEV 208 MNT_NODEV, "nodev", 209 #endif 210 #ifdef MNT_UNION 211 MNT_UNION, "union", 212 #endif 213 #ifdef MNT_ASYNC 214 MNT_ASYNC, "async", 215 #endif 216 #ifdef MNT_NOCOREDUMP 217 MNT_NOCOREDUMP, "nocoredump", 218 #endif 219 #ifdef MNT_NOATIME 220 MNT_NOATIME, "noatime", 221 #endif 222 #ifdef MNT_SYMPERM 223 MNT_SYMPERM, "symperm", 224 #endif 225 #ifdef MNT_NODEVMTIME 226 MNT_NODEVMTIME, "nodevmtime", 227 #endif 228 #ifdef MNT_SOFTDEP 229 MNT_SOFTDEP, "softdep", 230 #endif 231 #ifdef MNT_EXRDONLY 232 MNT_EXRDONLY, "exrdonly", 233 #endif 234 #ifdef MNT_EXPORTED 235 MNT_EXPORTED, "exported", 236 #endif 237 #ifdef MNT_DEFEXPORTED 238 MNT_DEFEXPORTED,"defexported", 239 #endif 240 #ifdef MNT_EXPORTANON 241 MNT_EXPORTANON, "exportanon", 242 #endif 243 #ifdef MNT_EXKERB 244 MNT_EXKERB, "exkerb", 245 #endif 246 #ifdef MNT_EXNORESPORT 247 MNT_EXNORESPORT,"exnoresport", 248 #endif 249 #ifdef MNT_EXPUBLIC 250 MNT_EXPUBLIC, "expublic", 251 #endif 252 #ifdef MNT_LOCAL 253 MNT_LOCAL, "local", 254 #endif 255 #ifdef MNT_QUOTA 256 MNT_QUOTA, "quota", 257 #endif 258 #ifdef MNT_ROOTFS 259 MNT_ROOTFS, "rootfs", 260 #endif 261 0, "unknown", 262 }; 263 264 void* 265 mntopen(const char* path, const char* mode) 266 { 267 register Handle_t* mp; 268 register int n; 269 270 FIXARGS(path, mode, 0); 271 #if _lib_getfsstat 272 if ((n = getfsstat(NiL, 0, MNT_WAIT)) <= 0) 273 return 0; 274 n = (n - 1) * sizeof(struct statfs); 275 #else 276 n = 0; 277 #endif 278 if (!(mp = newof(0, Handle_t, 1, n))) 279 return 0; 280 #if _lib_getfsstat 281 n = getfsstat(mp->next = mp->buf, n + sizeof(struct statfs), MNT_WAIT); 282 #else 283 n = getmntinfo(&mp->next, 0); 284 #endif 285 if (n <= 0) 286 { 287 free(mp); 288 return 0; 289 } 290 mp->last = mp->next + n; 291 return (void*)mp; 292 } 293 294 Mnt_t* 295 mntread(void* handle) 296 { 297 register Handle_t* mp = (Handle_t*)handle; 298 register int i; 299 register int n; 300 register unsigned long flags; 301 302 if (mp->next < mp->last) 303 { 304 flags = mp->next->f_flags; 305 n = 0; 306 for (i = 0; i < elementsof(options); i++) 307 if (flags & options[i].flag) 308 n += sfsprintf(mp->opt + n, sizeof(mp->opt) - n - 1, ",%s", options[i].name); 309 set(&mp->hdr, mp->next->f_mntfromname, mp->next->f_mntonname, TYPE(mp->next), n ? (mp->opt + 1) : (char*)0); 310 mp->next++; 311 return &mp->hdr.mnt; 312 } 313 return 0; 314 } 315 316 int 317 mntclose(void* handle) 318 { 319 register Handle_t* mp = (Handle_t*)handle; 320 321 if (!mp) 322 return -1; 323 free(mp); 324 return 0; 325 } 326 327 #else 328 329 #if _lib_mntctl && _sys_vmount 330 331 /* 332 * aix 333 */ 334 335 #include <sys/vmount.h> 336 337 #define SIZE (16 * 1024) 338 339 static const char* type[] = 340 { 341 "aix", "aix#1", "nfs", "jfs", "aix#4", "cdrom" 342 }; 343 344 typedef struct 345 { 346 Header_t hdr; 347 long count; 348 struct vmount* next; 349 char remote[128]; 350 char type[16]; 351 struct vmount info[1]; 352 } Handle_t; 353 354 void* 355 mntopen(const char* path, const char* mode) 356 { 357 register Handle_t* mp; 358 359 FIXARGS(path, mode, 0); 360 if (!(mp = newof(0, Handle_t, 1, SIZE))) 361 return 0; 362 if ((mp->count = mntctl(MCTL_QUERY, sizeof(Handle_t) + SIZE, &mp->info)) <= 0) 363 { 364 free(mp); 365 return 0; 366 } 367 mp->next = mp->info; 368 return (void*)mp; 369 } 370 371 Mnt_t* 372 mntread(void* handle) 373 { 374 register Handle_t* mp = (Handle_t*)handle; 375 register char* s; 376 register char* t; 377 register char* o; 378 379 if (mp->count > 0) 380 { 381 if (vmt2datasize(mp->next, VMT_HOST) && (s = vmt2dataptr(mp->next, VMT_HOST)) && !streq(s, "-")) 382 { 383 sfsprintf(mp->remote, sizeof(mp->remote) - 1, "%s:%s", s, vmt2dataptr(mp->next, VMT_OBJECT)); 384 s = mp->remote; 385 } 386 else 387 s = vmt2dataptr(mp->next, VMT_OBJECT); 388 if (vmt2datasize(mp->next, VMT_ARGS)) 389 o = vmt2dataptr(mp->next, VMT_ARGS); 390 else 391 o = NiL; 392 switch (mp->next->vmt_gfstype) 393 { 394 #ifdef MNT_AIX 395 case MNT_AIX: 396 t = "aix"; 397 break; 398 #endif 399 #ifdef MNT_NFS 400 case MNT_NFS: 401 t = "nfs"; 402 break; 403 #endif 404 #ifdef MNT_JFS 405 case MNT_JFS: 406 t = "jfs"; 407 break; 408 #endif 409 #ifdef MNT_CDROM 410 case MNT_CDROM: 411 t = "cdrom"; 412 break; 413 #endif 414 #ifdef MNT_SFS 415 case MNT_SFS: 416 t = "sfs"; 417 break; 418 #endif 419 #ifdef MNT_NFS3 420 case MNT_NFS3: 421 t = "nfs3"; 422 break; 423 #endif 424 #ifdef MNT_AUTOFS 425 case MNT_AUTOFS: 426 t = "autofs"; 427 break; 428 #endif 429 default: 430 sfsprintf(t = mp->type, sizeof(mp->type), "aix%+d", mp->next->vmt_gfstype); 431 break; 432 } 433 set(&mp->hdr, s, vmt2dataptr(mp->next, VMT_STUB), t, o); 434 if (--mp->count > 0) 435 mp->next = (struct vmount*)((char*)mp->next + mp->next->vmt_length); 436 return &mp->hdr.mnt; 437 } 438 return 0; 439 } 440 441 int 442 mntclose(void* handle) 443 { 444 register Handle_t* mp = (Handle_t*)handle; 445 446 if (!mp) 447 return -1; 448 free(mp); 449 return 0; 450 } 451 452 #else 453 454 #if !_lib_setmntent 455 #undef _lib_getmntent 456 #if !_SCO_COFF && !_SCO_ELF && !_UTS 457 #undef _hdr_mnttab 458 #endif 459 #endif 460 461 #if _lib_getmntent && ( _hdr_mntent || _sys_mntent && !_sys_mnttab ) 462 463 #if defined(__STDPP__directive) && defined(__STDPP__hide) 464 __STDPP__directive pragma pp:hide endmntent getmntent 465 #else 466 #define endmntent ______endmntent 467 #define getmntent ______getmntent 468 #endif 469 470 #include <stdio.h> 471 #if _hdr_mntent 472 #include <mntent.h> 473 #else 474 #include <sys/mntent.h> 475 #endif 476 477 #if defined(__STDPP__directive) && defined(__STDPP__hide) 478 __STDPP__directive pragma pp:nohide endmntent getmntent 479 #else 480 #undef endmntent 481 #undef getmntent 482 #endif 483 484 extern int endmntent(FILE*); 485 extern struct mntent* getmntent(FILE*); 486 487 #else 488 489 #undef _lib_getmntent 490 491 #if _hdr_mnttab 492 #include <mnttab.h> 493 #else 494 #if _sys_mnttab 495 #include <sys/mnttab.h> 496 #endif 497 #endif 498 499 #endif 500 501 #ifndef MOUNTED 502 #ifdef MNT_MNTTAB 503 #define MOUNTED MNT_MNTTAB 504 #else 505 #if _hdr_mnttab || _sys_mnttab 506 #define MOUNTED "/etc/mnttab" 507 #else 508 #define MOUNTED "/etc/mtab" 509 #endif 510 #endif 511 #endif 512 513 #ifdef __Lynx__ 514 #undef MOUNTED 515 #define MOUNTED "/etc/fstab" 516 #define SEP ':' 517 #endif 518 519 #if _lib_getmntent 520 521 typedef struct 522 #if _mem_mnt_opts_mntent 523 #define OPTIONS(p) ((p)->mnt_opts) 524 #else 525 #define OPTIONS(p) NiL 526 #endif 527 528 { 529 Header_t hdr; 530 FILE* fp; 531 } Handle_t; 532 533 void* 534 mntopen(const char* path, const char* mode) 535 { 536 register Handle_t* mp; 537 538 FIXARGS(path, mode, MOUNTED); 539 if (!(mp = newof(0, Handle_t, 1, 0))) 540 return 0; 541 if (!(mp->fp = setmntent(path, mode))) 542 { 543 free(mp); 544 return 0; 545 } 546 return (void*)mp; 547 } 548 549 Mnt_t* 550 mntread(void* handle) 551 { 552 register Handle_t* mp = (Handle_t*)handle; 553 register struct mntent* mnt; 554 555 if (mnt = getmntent(mp->fp)) 556 { 557 set(&mp->hdr, mnt->mnt_fsname, mnt->mnt_dir, mnt->mnt_type, OPTIONS(mnt)); 558 return &mp->hdr.mnt; 559 } 560 return 0; 561 } 562 563 int 564 mntclose(void* handle) 565 { 566 register Handle_t* mp = (Handle_t*)handle; 567 568 if (!mp) 569 return -1; 570 endmntent(mp->fp); 571 free(mp); 572 return 0; 573 } 574 575 #else 576 577 #if _sys_mntent && _lib_w_getmntent 578 579 #include <sys/mntent.h> 580 581 #define mntent w_mntent 582 583 #define mnt_dir mnt_mountpoint 584 #define mnt_type mnt_fstname 585 586 #define MNTBUFSIZE (sizeof(struct w_mnth)+16*sizeof(struct w_mntent)) 587 588 #if _mem_mnt_opts_w_mntent 589 #define OPTIONS(p) ((p)->mnt_opts) 590 #else 591 #define OPTIONS(p) NiL 592 #endif 593 594 #else 595 596 #undef _lib_w_getmntent 597 598 #define MNTBUFSIZE sizeof(struct mntent) 599 600 #if !_mem_mt_dev_mnttab || !_mem_mt_filsys_mnttab 601 #undef _hdr_mnttab 602 #endif 603 604 #if _hdr_mnttab 605 606 #define mntent mnttab 607 608 #define mnt_fsname mt_dev 609 #define mnt_dir mt_filsys 610 #if _mem_mt_fstyp_mnttab 611 #define mnt_type mt_fstyp 612 #endif 613 614 #if _mem_mnt_opts_mnttab 615 #define OPTIONS(p) ((p)->mnt_opts) 616 #else 617 #define OPTIONS(p) NiL 618 #endif 619 620 #else 621 622 struct mntent 623 { 624 char mnt_fsname[256]; 625 char mnt_dir[256]; 626 char mnt_type[32]; 627 char mnt_opts[64]; 628 }; 629 630 #define OPTIONS(p) ((p)->mnt_opts) 631 632 #endif 633 634 #endif 635 636 typedef struct 637 { 638 Header_t hdr; 639 Sfio_t* fp; 640 struct mntent* mnt; 641 #if _lib_w_getmntent 642 int count; 643 #endif 644 char buf[MNTBUFSIZE]; 645 } Handle_t; 646 647 void* 648 mntopen(const char* path, const char* mode) 649 { 650 register Handle_t* mp; 651 652 FIXARGS(path, mode, MOUNTED); 653 if (!(mp = newof(0, Handle_t, 1, 0))) 654 return 0; 655 #if _lib_w_getmntent 656 if ((mp->count = w_getmntent(mp->buf, sizeof(mp->buf))) > 0) 657 mp->mnt = (struct mntent*)(((struct w_mnth*)mp->buf) + 1); 658 else 659 #else 660 mp->mnt = (struct mntent*)mp->buf; 661 if (!(mp->fp = sfopen(NiL, path, mode))) 662 #endif 663 { 664 free(mp); 665 return 0; 666 } 667 return (void*)mp; 668 } 669 670 Mnt_t* 671 mntread(void* handle) 672 { 673 register Handle_t* mp = (Handle_t*)handle; 674 675 #if _lib_w_getmntent 676 677 if (mp->count-- <= 0) 678 { 679 if ((mp->count = w_getmntent(mp->buf, sizeof(mp->buf))) <= 0) 680 return 0; 681 mp->count--; 682 mp->mnt = (struct mntent*)(((struct w_mnth*)mp->buf) + 1); 683 } 684 set(&mp->hdr, mp->mnt->mnt_fsname, mp->mnt->mnt_dir, mp->mnt->mnt_type, OPTIONS(mp->mnt)); 685 mp->mnt++; 686 return &mp->hdr.mnt; 687 688 #else 689 690 #if _hdr_mnttab 691 692 while (sfread(mp->fp, &mp->buf, sizeof(mp->buf)) == sizeof(mp->buf)) 693 if (*mp->mnt->mnt_fsname && *mp->mnt->mnt_dir) 694 { 695 #ifndef mnt_type 696 struct stat st; 697 698 static char typ[32]; 699 700 set(&mp->hdr, mp->mnt->mnt_fsname, mp->mnt->mnt_dir, stat(mp->mnt->mnt_dir, &st) ? FS_default : strlcpy(typ, fmtfs(&st), sizeof(typ)), OPTIONS(mp->mnt)); 701 #else 702 set(&mp->hdr, mp->mnt->mnt_fsname, mp->mnt->mnt_dir, mp->mnt->mnt_type, OPTIONS(mp->mnt)); 703 #endif 704 return &mp->hdr.mnt; 705 } 706 return 0; 707 708 #else 709 710 register int c; 711 register char* s; 712 register char* m; 713 register char* b; 714 register int q; 715 register int x; 716 717 again: 718 q = 0; 719 x = 0; 720 b = s = mp->mnt->mnt_fsname; 721 m = s + sizeof(mp->mnt->mnt_fsname) - 1; 722 for (;;) switch (c = sfgetc(mp->fp)) 723 { 724 case EOF: 725 return 0; 726 case '"': 727 case '\'': 728 if (q == c) 729 q = 0; 730 else if (!q) 731 q = c; 732 break; 733 #ifdef SEP 734 case SEP: 735 #else 736 case ' ': 737 case '\t': 738 #endif 739 if (s != b && !q) switch (++x) 740 { 741 case 1: 742 *s = 0; 743 b = s = mp->mnt->mnt_dir; 744 m = s + sizeof(mp->mnt->mnt_dir) - 1; 745 break; 746 case 2: 747 *s = 0; 748 b = s = mp->mnt->mnt_type; 749 m = s + sizeof(mp->mnt->mnt_type) - 1; 750 break; 751 case 3: 752 *s = 0; 753 b = s = mp->mnt->mnt_opts; 754 m = s + sizeof(mp->mnt->mnt_opts) - 1; 755 break; 756 case 4: 757 *s = 0; 758 b = s = m = 0; 759 break; 760 } 761 break; 762 case '\n': 763 if (x >= 3) 764 { 765 set(&mp->hdr, mp->mnt->mnt_fsname, mp->mnt->mnt_dir, mp->mnt->mnt_type, OPTIONS(mp->mnt)); 766 return &mp->hdr.mnt; 767 } 768 goto again; 769 default: 770 if (s < m) 771 *s++ = c; 772 break; 773 } 774 775 #endif 776 777 #endif 778 779 } 780 781 int 782 mntclose(void* handle) 783 { 784 register Handle_t* mp = (Handle_t*)handle; 785 786 if (!mp) 787 return -1; 788 sfclose(mp->fp); 789 free(mp); 790 return 0; 791 } 792 793 #endif 794 795 #endif 796 797 #endif 798 799 /* 800 * currently no write 801 */ 802 803 int 804 mntwrite(void* handle, const Mnt_t* mnt) 805 { 806 NoP(handle); 807 NoP(mnt); 808 return -1; 809 } 810 811 #endif 812