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* Common Public License, Version 1.0 * 7* by AT&T Intellectual Property * 8* * 9* A copy of the License is available at * 10* http://www.opensource.org/licenses/cpl1.0.txt * 11* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 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 37NoN(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) 53typedef 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 67static void 68set(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 161typedef 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]) 177static 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 188static struct Mnt_options_t 189{ 190 unsigned long flag; 191 const char* name; 192} 193options[] = 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 264void* 265mntopen(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 294Mnt_t* 295mntread(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 316int 317mntclose(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 339static const char* type[] = 340{ 341 "aix", "aix#1", "nfs", "jfs", "aix#4", "cdrom" 342}; 343 344typedef 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 354void* 355mntopen(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 371Mnt_t* 372mntread(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_CACHEFS 420 case MNT_CACHEFS: 421 t = "cachefs"; 422 break; 423#endif 424#ifdef MNT_NFS3 425 case MNT_NFS3: 426 t = "nfs3"; 427 break; 428#endif 429#ifdef MNT_AUTOFS 430 case MNT_AUTOFS: 431 t = "autofs"; 432 break; 433#endif 434 default: 435 sfsprintf(t = mp->type, sizeof(mp->type), "aix%+d", mp->next->vmt_gfstype); 436 break; 437 } 438 set(&mp->hdr, s, vmt2dataptr(mp->next, VMT_STUB), t, o); 439 if (--mp->count > 0) 440 mp->next = (struct vmount*)((char*)mp->next + mp->next->vmt_length); 441 return &mp->hdr.mnt; 442 } 443 return 0; 444} 445 446int 447mntclose(void* handle) 448{ 449 register Handle_t* mp = (Handle_t*)handle; 450 451 if (!mp) 452 return -1; 453 free(mp); 454 return 0; 455} 456 457#else 458 459#if !_lib_setmntent 460#undef _lib_getmntent 461#if !_SCO_COFF && !_SCO_ELF && !_UTS 462#undef _hdr_mnttab 463#endif 464#endif 465 466#if _lib_getmntent && ( _hdr_mntent || _sys_mntent && !_sys_mnttab ) 467 468#if defined(__STDPP__directive) && defined(__STDPP__hide) 469__STDPP__directive pragma pp:hide endmntent getmntent 470#else 471#define endmntent ______endmntent 472#define getmntent ______getmntent 473#endif 474 475#include <stdio.h> 476#if _hdr_mntent 477#include <mntent.h> 478#else 479#include <sys/mntent.h> 480#endif 481 482#if defined(__STDPP__directive) && defined(__STDPP__hide) 483__STDPP__directive pragma pp:nohide endmntent getmntent 484#else 485#undef endmntent 486#undef getmntent 487#endif 488 489extern int endmntent(FILE*); 490extern struct mntent* getmntent(FILE*); 491 492#else 493 494#undef _lib_getmntent 495 496#if _hdr_mnttab 497#include <mnttab.h> 498#else 499#if _sys_mnttab 500#include <sys/mnttab.h> 501#endif 502#endif 503 504#endif 505 506#ifndef MOUNTED 507#ifdef MNT_MNTTAB 508#define MOUNTED MNT_MNTTAB 509#else 510#if _hdr_mnttab || _sys_mnttab 511#define MOUNTED "/etc/mnttab" 512#else 513#define MOUNTED "/etc/mtab" 514#endif 515#endif 516#endif 517 518#ifdef __Lynx__ 519#undef MOUNTED 520#define MOUNTED "/etc/fstab" 521#define SEP ':' 522#endif 523 524#if _lib_getmntent 525 526typedef struct 527#if _mem_mnt_opts_mntent 528#define OPTIONS(p) ((p)->mnt_opts) 529#else 530#define OPTIONS(p) NiL 531#endif 532 533{ 534 Header_t hdr; 535 FILE* fp; 536} Handle_t; 537 538void* 539mntopen(const char* path, const char* mode) 540{ 541 register Handle_t* mp; 542 543 FIXARGS(path, mode, MOUNTED); 544 if (!(mp = newof(0, Handle_t, 1, 0))) 545 return 0; 546 if (!(mp->fp = setmntent(path, mode))) 547 { 548 free(mp); 549 return 0; 550 } 551 return (void*)mp; 552} 553 554Mnt_t* 555mntread(void* handle) 556{ 557 register Handle_t* mp = (Handle_t*)handle; 558 register struct mntent* mnt; 559 560 if (mnt = getmntent(mp->fp)) 561 { 562 set(&mp->hdr, mnt->mnt_fsname, mnt->mnt_dir, mnt->mnt_type, OPTIONS(mnt)); 563 return &mp->hdr.mnt; 564 } 565 return 0; 566} 567 568int 569mntclose(void* handle) 570{ 571 register Handle_t* mp = (Handle_t*)handle; 572 573 if (!mp) 574 return -1; 575 endmntent(mp->fp); 576 free(mp); 577 return 0; 578} 579 580#else 581 582#if _sys_mntent && _lib_w_getmntent 583 584#include <sys/mntent.h> 585 586#define mntent w_mntent 587 588#define mnt_dir mnt_mountpoint 589#define mnt_type mnt_fstname 590 591#define MNTBUFSIZE (sizeof(struct w_mnth)+16*sizeof(struct w_mntent)) 592 593#if _mem_mnt_opts_w_mntent 594#define OPTIONS(p) ((p)->mnt_opts) 595#else 596#define OPTIONS(p) NiL 597#endif 598 599#else 600 601#undef _lib_w_getmntent 602 603#define MNTBUFSIZE sizeof(struct mntent) 604 605#if !_mem_mt_dev_mnttab || !_mem_mt_filsys_mnttab 606#undef _hdr_mnttab 607#endif 608 609#if _hdr_mnttab 610 611#define mntent mnttab 612 613#define mnt_fsname mt_dev 614#define mnt_dir mt_filsys 615#if _mem_mt_fstyp_mnttab 616#define mnt_type mt_fstyp 617#endif 618 619#if _mem_mnt_opts_mnttab 620#define OPTIONS(p) ((p)->mnt_opts) 621#else 622#define OPTIONS(p) NiL 623#endif 624 625#else 626 627struct mntent 628{ 629 char mnt_fsname[256]; 630 char mnt_dir[256]; 631 char mnt_type[32]; 632 char mnt_opts[64]; 633}; 634 635#define OPTIONS(p) ((p)->mnt_opts) 636 637#endif 638 639#endif 640 641typedef struct 642{ 643 Header_t hdr; 644 Sfio_t* fp; 645 struct mntent* mnt; 646#if _lib_w_getmntent 647 int count; 648#endif 649 char buf[MNTBUFSIZE]; 650} Handle_t; 651 652void* 653mntopen(const char* path, const char* mode) 654{ 655 register Handle_t* mp; 656 657 FIXARGS(path, mode, MOUNTED); 658 if (!(mp = newof(0, Handle_t, 1, 0))) 659 return 0; 660#if _lib_w_getmntent 661 if ((mp->count = w_getmntent(mp->buf, sizeof(mp->buf))) > 0) 662 mp->mnt = (struct mntent*)(((struct w_mnth*)mp->buf) + 1); 663 else 664#else 665 mp->mnt = (struct mntent*)mp->buf; 666 if (!(mp->fp = sfopen(NiL, path, mode))) 667#endif 668 { 669 free(mp); 670 return 0; 671 } 672 return (void*)mp; 673} 674 675Mnt_t* 676mntread(void* handle) 677{ 678 register Handle_t* mp = (Handle_t*)handle; 679 680#if _lib_w_getmntent 681 682 if (mp->count-- <= 0) 683 { 684 if ((mp->count = w_getmntent(mp->buf, sizeof(mp->buf))) <= 0) 685 return 0; 686 mp->count--; 687 mp->mnt = (struct mntent*)(((struct w_mnth*)mp->buf) + 1); 688 } 689 set(&mp->hdr, mp->mnt->mnt_fsname, mp->mnt->mnt_dir, mp->mnt->mnt_type, OPTIONS(mp->mnt)); 690 mp->mnt++; 691 return &mp->hdr.mnt; 692 693#else 694 695#if _hdr_mnttab 696 697 while (sfread(mp->fp, &mp->buf, sizeof(mp->buf)) == sizeof(mp->buf)) 698 if (*mp->mnt->mnt_fsname && *mp->mnt->mnt_dir) 699 { 700#ifndef mnt_type 701 struct stat st; 702 703 static char typ[32]; 704 705 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)); 706#else 707 set(&mp->hdr, mp->mnt->mnt_fsname, mp->mnt->mnt_dir, mp->mnt->mnt_type, OPTIONS(mp->mnt)); 708#endif 709 return &mp->hdr.mnt; 710 } 711 return 0; 712 713#else 714 715 register int c; 716 register char* s; 717 register char* m; 718 register char* b; 719 register int q; 720 register int x; 721 722 again: 723 q = 0; 724 x = 0; 725 b = s = mp->mnt->mnt_fsname; 726 m = s + sizeof(mp->mnt->mnt_fsname) - 1; 727 for (;;) switch (c = sfgetc(mp->fp)) 728 { 729 case EOF: 730 return 0; 731 case '"': 732 case '\'': 733 if (q == c) 734 q = 0; 735 else if (!q) 736 q = c; 737 break; 738#ifdef SEP 739 case SEP: 740#else 741 case ' ': 742 case '\t': 743#endif 744 if (s != b && !q) switch (++x) 745 { 746 case 1: 747 *s = 0; 748 b = s = mp->mnt->mnt_dir; 749 m = s + sizeof(mp->mnt->mnt_dir) - 1; 750 break; 751 case 2: 752 *s = 0; 753 b = s = mp->mnt->mnt_type; 754 m = s + sizeof(mp->mnt->mnt_type) - 1; 755 break; 756 case 3: 757 *s = 0; 758 b = s = mp->mnt->mnt_opts; 759 m = s + sizeof(mp->mnt->mnt_opts) - 1; 760 break; 761 case 4: 762 *s = 0; 763 b = s = m = 0; 764 break; 765 } 766 break; 767 case '\n': 768 if (x >= 3) 769 { 770 set(&mp->hdr, mp->mnt->mnt_fsname, mp->mnt->mnt_dir, mp->mnt->mnt_type, OPTIONS(mp->mnt)); 771 return &mp->hdr.mnt; 772 } 773 goto again; 774 default: 775 if (s < m) 776 *s++ = c; 777 break; 778 } 779 780#endif 781 782#endif 783 784} 785 786int 787mntclose(void* handle) 788{ 789 register Handle_t* mp = (Handle_t*)handle; 790 791 if (!mp) 792 return -1; 793 sfclose(mp->fp); 794 free(mp); 795 return 0; 796} 797 798#endif 799 800#endif 801 802#endif 803 804/* 805 * currently no write 806 */ 807 808int 809mntwrite(void* handle, const Mnt_t* mnt) 810{ 811 NoP(handle); 812 NoP(mnt); 813 return -1; 814} 815 816#endif 817