xref: /titanic_51/usr/src/lib/libast/common/port/mnt.c (revision a31148363f598def767ac48c5d82e1572e44b935)
1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1985-2009 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 
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 _lib_getmntinfo && _sys_mount
133 
134 /*
135  * 4.4 bsd
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 
144 #include <sys/param.h>		/* expect some macro redefinitions here */
145 #include <sys/mount.h>
146 
147 #if _lib_getmntinfo_statvfs
148 #define statfs		statvfs
149 #define f_flags		f_flag
150 #endif
151 
152 typedef struct
153 {
154 	Header_t	hdr;
155 	struct statfs*	next;
156 	struct statfs*	last;
157 	char		opt[256];
158 } Handle_t;
159 
160 #ifdef MFSNAMELEN
161 #define TYPE(f)		((f)->f_fstypename)
162 #else
163 #ifdef INITMOUNTNAMES
164 #define TYPE(f)		((char*)type[(f)->f_type])
165 static const char*	type[] = INITMOUNTNAMES;
166 #else
167 #if _sys_fs_types
168 #define TYPE(f)		((char*)mnt_names[(f)->f_type])
169 #include <sys/fs_types.h>
170 #else
171 #define TYPE(f)		(strchr((f)->f_mntfromname,':')?"nfs":"ufs")
172 #endif
173 #endif
174 #endif
175 
176 static struct Mnt_options_t
177 {
178 	unsigned long	flag;
179 	const char*	name;
180 }
181 options[] =
182 {
183 #ifdef MNT_RDONLY
184 	MNT_RDONLY,	"rdonly",
185 #endif
186 #ifdef MNT_SYNCHRONOUS
187 	MNT_SYNCHRONOUS,"synchronous",
188 #endif
189 #ifdef MNT_NOEXEC
190 	MNT_NOEXEC,	"noexec",
191 #endif
192 #ifdef MNT_NOSUID
193 	MNT_NOSUID,	"nosuid",
194 #endif
195 #ifdef MNT_NODEV
196 	MNT_NODEV,	"nodev",
197 #endif
198 #ifdef MNT_UNION
199 	MNT_UNION,	"union",
200 #endif
201 #ifdef MNT_ASYNC
202 	MNT_ASYNC,	"async",
203 #endif
204 #ifdef MNT_NOCOREDUMP
205 	MNT_NOCOREDUMP,	"nocoredump",
206 #endif
207 #ifdef MNT_NOATIME
208 	MNT_NOATIME,	"noatime",
209 #endif
210 #ifdef MNT_SYMPERM
211 	MNT_SYMPERM,	"symperm",
212 #endif
213 #ifdef MNT_NODEVMTIME
214 	MNT_NODEVMTIME,	"nodevmtime",
215 #endif
216 #ifdef MNT_SOFTDEP
217 	MNT_SOFTDEP,	"softdep",
218 #endif
219 #ifdef MNT_EXRDONLY
220 	MNT_EXRDONLY,	"exrdonly",
221 #endif
222 #ifdef MNT_EXPORTED
223 	MNT_EXPORTED,	"exported",
224 #endif
225 #ifdef MNT_DEFEXPORTED
226 	MNT_DEFEXPORTED,"defexported",
227 #endif
228 #ifdef MNT_EXPORTANON
229 	MNT_EXPORTANON,	"exportanon",
230 #endif
231 #ifdef MNT_EXKERB
232 	MNT_EXKERB,	"exkerb",
233 #endif
234 #ifdef MNT_EXNORESPORT
235 	MNT_EXNORESPORT,"exnoresport",
236 #endif
237 #ifdef MNT_EXPUBLIC
238 	MNT_EXPUBLIC,	"expublic",
239 #endif
240 #ifdef MNT_LOCAL
241 	MNT_LOCAL,	"local",
242 #endif
243 #ifdef MNT_QUOTA
244 	MNT_QUOTA,	"quota",
245 #endif
246 #ifdef MNT_ROOTFS
247 	MNT_ROOTFS,	"rootfs",
248 #endif
249 	0,		"unknown",
250 };
251 
252 void*
253 mntopen(const char* path, const char* mode)
254 {
255 	register Handle_t*	mp;
256 	register int		n;
257 
258 	FIXARGS(path, mode, 0);
259 	if (!(mp = newof(0, Handle_t, 1, 0)))
260 		return 0;
261 	if ((n = getmntinfo(&mp->next, 0)) <= 0)
262 	{
263 		free(mp);
264 		return 0;
265 	}
266 	mp->last = mp->next + n;
267 	return (void*)mp;
268 }
269 
270 Mnt_t*
271 mntread(void* handle)
272 {
273 	register Handle_t*	mp = (Handle_t*)handle;
274 	register int		i;
275 	register int		n;
276 	register unsigned long	flags;
277 
278 	if (mp->next < mp->last)
279 	{
280 		flags = mp->next->f_flags;
281 		n = 0;
282 		for (i = 0; i < elementsof(options); i++)
283 			if (flags & options[i].flag)
284 				n += sfsprintf(mp->opt + n, sizeof(mp->opt) - n - 1, ",%s", options[i].name);
285 		set(&mp->hdr, mp->next->f_mntfromname, mp->next->f_mntonname, TYPE(mp->next), n ? (mp->opt + 1) : (char*)0);
286 		mp->next++;
287 		return &mp->hdr.mnt;
288 	}
289 	return 0;
290 }
291 
292 int
293 mntclose(void* handle)
294 {
295 	register Handle_t*	mp = (Handle_t*)handle;
296 
297 	if (!mp)
298 		return -1;
299 	free(mp);
300 	return 0;
301 }
302 
303 #else
304 
305 #if _lib_mntctl && _sys_vmount
306 
307 /*
308  * aix
309  */
310 
311 #include <sys/vmount.h>
312 
313 #define SIZE		(16 * 1024)
314 
315 static const char*	type[] =
316 {
317 	"aix", "aix#1", "nfs", "jfs", "aix#4", "cdrom"
318 };
319 
320 typedef struct
321 {
322 	Header_t	hdr;
323 	long		count;
324 	struct vmount*	next;
325 	char		remote[128];
326 	char		type[16];
327 	struct vmount	info[1];
328 } Handle_t;
329 
330 void*
331 mntopen(const char* path, const char* mode)
332 {
333 	register Handle_t*	mp;
334 
335 	FIXARGS(path, mode, 0);
336 	if (!(mp = newof(0, Handle_t, 1, SIZE)))
337 		return 0;
338 	if ((mp->count = mntctl(MCTL_QUERY, sizeof(Handle_t) + SIZE, &mp->info)) <= 0)
339 	{
340 		free(mp);
341 		return 0;
342 	}
343 	mp->next = mp->info;
344 	return (void*)mp;
345 }
346 
347 Mnt_t*
348 mntread(void* handle)
349 {
350 	register Handle_t*	mp = (Handle_t*)handle;
351 	register char*		s;
352 	register char*		t;
353 	register char*		o;
354 
355 	if (mp->count > 0)
356 	{
357 		if (vmt2datasize(mp->next, VMT_HOST) && (s = vmt2dataptr(mp->next, VMT_HOST)) && !streq(s, "-"))
358 		{
359 			sfsprintf(mp->remote, sizeof(mp->remote) - 1, "%s:%s", s, vmt2dataptr(mp->next, VMT_OBJECT));
360 			s = mp->remote;
361 		}
362 		else
363 			s = vmt2dataptr(mp->next, VMT_OBJECT);
364 		if (vmt2datasize(mp->next, VMT_ARGS))
365 			o = vmt2dataptr(mp->next, VMT_ARGS);
366 		else
367 			o = NiL;
368 		switch (mp->next->vmt_gfstype)
369 		{
370 #ifdef MNT_AIX
371 		case MNT_AIX:
372 			t = "aix";
373 			break;
374 #endif
375 #ifdef MNT_NFS
376 		case MNT_NFS:
377 			t = "nfs";
378 			break;
379 #endif
380 #ifdef MNT_JFS
381 		case MNT_JFS:
382 			t = "jfs";
383 			break;
384 #endif
385 #ifdef MNT_CDROM
386 		case MNT_CDROM:
387 			t = "cdrom";
388 			break;
389 #endif
390 #ifdef MNT_SFS
391 		case MNT_SFS:
392 			t = "sfs";
393 			break;
394 #endif
395 #ifdef MNT_CACHEFS
396 		case MNT_CACHEFS:
397 			t = "cachefs";
398 			break;
399 #endif
400 #ifdef MNT_NFS3
401 		case MNT_NFS3:
402 			t = "nfs3";
403 			break;
404 #endif
405 #ifdef MNT_AUTOFS
406 		case MNT_AUTOFS:
407 			t = "autofs";
408 			break;
409 #endif
410 		default:
411 			sfsprintf(t = mp->type, sizeof(mp->type), "aix%+d", mp->next->vmt_gfstype);
412 			break;
413 		}
414 		set(&mp->hdr, s, vmt2dataptr(mp->next, VMT_STUB), t, o);
415 		if (--mp->count > 0)
416 			mp->next = (struct vmount*)((char*)mp->next + mp->next->vmt_length);
417 		return &mp->hdr.mnt;
418 	}
419 	return 0;
420 }
421 
422 int
423 mntclose(void* handle)
424 {
425 	register Handle_t*	mp = (Handle_t*)handle;
426 
427 	if (!mp)
428 		return -1;
429 	free(mp);
430 	return 0;
431 }
432 
433 #else
434 
435 #if !_lib_setmntent
436 #undef	_lib_getmntent
437 #if !_SCO_COFF && !_SCO_ELF && !_UTS
438 #undef	_hdr_mnttab
439 #endif
440 #endif
441 
442 #if _lib_getmntent && ( _hdr_mntent || _sys_mntent && !_sys_mnttab )
443 
444 #if defined(__STDPP__directive) && defined(__STDPP__hide)
445 __STDPP__directive pragma pp:hide endmntent getmntent
446 #else
447 #define endmntent	______endmntent
448 #define getmntent	______getmntent
449 #endif
450 
451 #include <stdio.h>
452 #if _hdr_mntent
453 #include <mntent.h>
454 #else
455 #include <sys/mntent.h>
456 #endif
457 
458 #if defined(__STDPP__directive) && defined(__STDPP__hide)
459 __STDPP__directive pragma pp:nohide endmntent getmntent
460 #else
461 #undef	endmntent
462 #undef	getmntent
463 #endif
464 
465 extern int		endmntent(FILE*);
466 extern struct mntent*	getmntent(FILE*);
467 
468 #else
469 
470 #undef	_lib_getmntent
471 
472 #if _hdr_mnttab
473 #include <mnttab.h>
474 #else
475 #if _sys_mnttab
476 #include <sys/mnttab.h>
477 #endif
478 #endif
479 
480 #endif
481 
482 #ifndef MOUNTED
483 #ifdef	MNT_MNTTAB
484 #define MOUNTED		MNT_MNTTAB
485 #else
486 #if _hdr_mnttab || _sys_mnttab
487 #define MOUNTED		"/etc/mnttab"
488 #else
489 #define MOUNTED		"/etc/mtab"
490 #endif
491 #endif
492 #endif
493 
494 #ifdef __Lynx__
495 #undef	MOUNTED
496 #define MOUNTED		"/etc/fstab"
497 #define SEP		':'
498 #endif
499 
500 #if _lib_getmntent
501 
502 typedef struct
503 #if _mem_mnt_opts_mntent
504 #define OPTIONS(p)	((p)->mnt_opts)
505 #else
506 #define OPTIONS(p)	NiL
507 #endif
508 
509 {
510 	Header_t	hdr;
511 	FILE*		fp;
512 } Handle_t;
513 
514 void*
515 mntopen(const char* path, const char* mode)
516 {
517 	register Handle_t*	mp;
518 
519 	FIXARGS(path, mode, MOUNTED);
520 	if (!(mp = newof(0, Handle_t, 1, 0)))
521 		return 0;
522 	if (!(mp->fp = setmntent(path, mode)))
523 	{
524 		free(mp);
525 		return 0;
526 	}
527 	return (void*)mp;
528 }
529 
530 Mnt_t*
531 mntread(void* handle)
532 {
533 	register Handle_t*	mp = (Handle_t*)handle;
534 	register struct mntent*	mnt;
535 
536 	if (mnt = getmntent(mp->fp))
537 	{
538 		set(&mp->hdr, mnt->mnt_fsname, mnt->mnt_dir, mnt->mnt_type, OPTIONS(mnt));
539 		return &mp->hdr.mnt;
540 	}
541 	return 0;
542 }
543 
544 int
545 mntclose(void* handle)
546 {
547 	register Handle_t*	mp = (Handle_t*)handle;
548 
549 	if (!mp)
550 		return -1;
551 	endmntent(mp->fp);
552 	free(mp);
553 	return 0;
554 }
555 
556 #else
557 
558 #if _sys_mntent && _lib_w_getmntent
559 
560 #include <sys/mntent.h>
561 
562 #define mntent		w_mntent
563 
564 #define mnt_dir		mnt_mountpoint
565 #define mnt_type	mnt_fstname
566 
567 #define MNTBUFSIZE	(sizeof(struct w_mnth)+16*sizeof(struct w_mntent))
568 
569 #if _mem_mnt_opts_w_mntent
570 #define OPTIONS(p)	((p)->mnt_opts)
571 #else
572 #define OPTIONS(p)	NiL
573 #endif
574 
575 #else
576 
577 #undef _lib_w_getmntent
578 
579 #define MNTBUFSIZE	sizeof(struct mntent)
580 
581 #if !_mem_mt_dev_mnttab || !_mem_mt_filsys_mnttab
582 #undef	_hdr_mnttab
583 #endif
584 
585 #if _hdr_mnttab
586 
587 #define mntent	mnttab
588 
589 #define mnt_fsname	mt_dev
590 #define mnt_dir		mt_filsys
591 #if _mem_mt_fstyp_mnttab
592 #define mnt_type	mt_fstyp
593 #endif
594 
595 #if _mem_mnt_opts_mnttab
596 #define OPTIONS(p)	((p)->mnt_opts)
597 #else
598 #define OPTIONS(p)	NiL
599 #endif
600 
601 #else
602 
603 struct mntent
604 {
605 	char	mnt_fsname[256];
606 	char	mnt_dir[256];
607 	char	mnt_type[32];
608 	char	mnt_opts[64];
609 };
610 
611 #define OPTIONS(p)	((p)->mnt_opts)
612 
613 #endif
614 
615 #endif
616 
617 typedef struct
618 {
619 	Header_t	hdr;
620 	Sfio_t*		fp;
621 	struct mntent*	mnt;
622 #if _lib_w_getmntent
623 	int		count;
624 #endif
625 	char		buf[MNTBUFSIZE];
626 } Handle_t;
627 
628 void*
629 mntopen(const char* path, const char* mode)
630 {
631 	register Handle_t*	mp;
632 
633 	FIXARGS(path, mode, MOUNTED);
634 	if (!(mp = newof(0, Handle_t, 1, 0)))
635 		return 0;
636 #if _lib_w_getmntent
637 	if ((mp->count = w_getmntent(mp->buf, sizeof(mp->buf))) > 0)
638 		mp->mnt = (struct mntent*)(((struct w_mnth*)mp->buf) + 1);
639 	else
640 #else
641 	mp->mnt = (struct mntent*)mp->buf;
642 	if (!(mp->fp = sfopen(NiL, path, mode)))
643 #endif
644 	{
645 		free(mp);
646 		return 0;
647 	}
648 	return (void*)mp;
649 }
650 
651 Mnt_t*
652 mntread(void* handle)
653 {
654 	register Handle_t*	mp = (Handle_t*)handle;
655 
656 #if _lib_w_getmntent
657 
658 	if (mp->count-- <= 0)
659 	{
660 		if ((mp->count = w_getmntent(mp->buf, sizeof(mp->buf))) <= 0)
661 			return 0;
662 		mp->count--;
663 		mp->mnt = (struct mntent*)(((struct w_mnth*)mp->buf) + 1);
664 	}
665 	set(&mp->hdr, mp->mnt->mnt_fsname, mp->mnt->mnt_dir, mp->mnt->mnt_type, OPTIONS(mp->mnt));
666 	mp->mnt++;
667 	return &mp->hdr.mnt;
668 
669 #else
670 
671 #if _hdr_mnttab
672 
673 	while (sfread(mp->fp, &mp->buf, sizeof(mp->buf)) == sizeof(mp->buf))
674 		if (*mp->mnt->mnt_fsname && *mp->mnt->mnt_dir)
675 		{
676 #ifndef mnt_type
677 			struct stat	st;
678 
679 			static char	typ[32];
680 
681 			set(&mp->hdr, mp->mnt->mnt_fsname, mp->mnt->mnt_dir, stat(mp->mnt->mnt_dir, &st) ? FS_default : strncpy(typ, fmtfs(&st), sizeof(typ) - 1), OPTIONS(mp->mnt));
682 #else
683 			set(&mp->hdr, mp->mnt->mnt_fsname, mp->mnt->mnt_dir, mp->mnt->mnt_type, OPTIONS(mp->mnt));
684 #endif
685 			return &mp->hdr.mnt;
686 		}
687 	return 0;
688 
689 #else
690 
691 	register int		c;
692 	register char*		s;
693 	register char*		m;
694 	register char*		b;
695 	register int		q;
696 	register int		x;
697 
698  again:
699 	q = 0;
700 	x = 0;
701 	b = s = mp->mnt->mnt_fsname;
702 	m = s + sizeof(mp->mnt->mnt_fsname) - 1;
703 	for (;;) switch (c = sfgetc(mp->fp))
704 	{
705 	case EOF:
706 		return 0;
707 	case '"':
708 	case '\'':
709 		if (q == c)
710 			q = 0;
711 		else if (!q)
712 			q = c;
713 		break;
714 #ifdef SEP
715 	case SEP:
716 #else
717 	case ' ':
718 	case '\t':
719 #endif
720 		if (s != b && !q) switch (++x)
721 		{
722 		case 1:
723 			*s = 0;
724 			b = s = mp->mnt->mnt_dir;
725 			m = s + sizeof(mp->mnt->mnt_dir) - 1;
726 			break;
727 		case 2:
728 			*s = 0;
729 			b = s = mp->mnt->mnt_type;
730 			m = s + sizeof(mp->mnt->mnt_type) - 1;
731 			break;
732 		case 3:
733 			*s = 0;
734 			b = s = mp->mnt->mnt_opts;
735 			m = s + sizeof(mp->mnt->mnt_opts) - 1;
736 			break;
737 		case 4:
738 			*s = 0;
739 			b = s = m = 0;
740 			break;
741 		}
742 		break;
743 	case '\n':
744 		if (x >= 3)
745 		{
746 			set(&mp->hdr, mp->mnt->mnt_fsname, mp->mnt->mnt_dir, mp->mnt->mnt_type, OPTIONS(mp->mnt));
747 			return &mp->hdr.mnt;
748 		}
749 		goto again;
750 	default:
751 		if (s < m)
752 			*s++ = c;
753 		break;
754 	}
755 
756 #endif
757 
758 #endif
759 
760 }
761 
762 int
763 mntclose(void* handle)
764 {
765 	register Handle_t*	mp = (Handle_t*)handle;
766 
767 	if (!mp)
768 		return -1;
769 	sfclose(mp->fp);
770 	free(mp);
771 	return 0;
772 }
773 
774 #endif
775 
776 #endif
777 
778 #endif
779 
780 /*
781  * currently no write
782  */
783 
784 int
785 mntwrite(void* handle, const Mnt_t* mnt)
786 {
787 	NoP(handle);
788 	NoP(mnt);
789 	return -1;
790 }
791 
792 #endif
793