1/***********************************************************************
2*                                                                      *
3*               This software is part of the ast package               *
4*          Copyright (c) 1985-2010 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 _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
152typedef 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])
165static 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
176static struct Mnt_options_t
177{
178	unsigned long	flag;
179	const char*	name;
180}
181options[] =
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
252void*
253mntopen(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
270Mnt_t*
271mntread(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
292int
293mntclose(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
315static const char*	type[] =
316{
317	"aix", "aix#1", "nfs", "jfs", "aix#4", "cdrom"
318};
319
320typedef 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
330void*
331mntopen(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
347Mnt_t*
348mntread(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
422int
423mntclose(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
465extern int		endmntent(FILE*);
466extern 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
502typedef 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
514void*
515mntopen(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
530Mnt_t*
531mntread(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
544int
545mntclose(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
603struct 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
617typedef 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
628void*
629mntopen(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
651Mnt_t*
652mntread(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
762int
763mntclose(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
784int
785mntwrite(void* handle, const Mnt_t* mnt)
786{
787	NoP(handle);
788	NoP(mnt);
789	return -1;
790}
791
792#endif
793