master
  1#include <stdio.h>
  2#include <string.h>
  3#include <mntent.h>
  4#include <errno.h>
  5#include <limits.h>
  6
  7static char *internal_buf;
  8static size_t internal_bufsize;
  9
 10#define SENTINEL (char *)&internal_buf
 11
 12FILE *setmntent(const char *name, const char *mode)
 13{
 14	return fopen(name, mode);
 15}
 16
 17int endmntent(FILE *f)
 18{
 19	if (f) fclose(f);
 20	return 1;
 21}
 22
 23static char *unescape_ent(char *beg)
 24{
 25	char *dest = beg;
 26	const char *src = beg;
 27	while (*src) {
 28		const char *val;
 29		unsigned char cval = 0;
 30		if (*src != '\\') {
 31			*dest++ = *src++;
 32			continue;
 33		}
 34		if (src[1] == '\\') {
 35			++src;
 36			*dest++ = *src++;
 37			continue;
 38		}
 39		val = src + 1;
 40		for (int i = 0; i < 3; ++i) {
 41			if (*val >= '0' && *val <= '7') {
 42				cval <<= 3;
 43				cval += *val++ - '0';
 44			} else {
 45				break;
 46			}
 47		}
 48		if (cval) {
 49			*dest++ = cval;
 50			src = val;
 51		} else {
 52			*dest++ = *src++;
 53		}
 54	}
 55	*dest = 0;
 56	return beg;
 57}
 58
 59struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int buflen)
 60{
 61	int n[8], use_internal = (linebuf == SENTINEL);
 62	size_t len, i;
 63
 64	mnt->mnt_freq = 0;
 65	mnt->mnt_passno = 0;
 66
 67	do {
 68		if (use_internal) {
 69			getline(&internal_buf, &internal_bufsize, f);
 70			linebuf = internal_buf;
 71		} else {
 72			fgets(linebuf, buflen, f);
 73		}
 74		if (feof(f) || ferror(f)) return 0;
 75		if (!strchr(linebuf, '\n')) {
 76			fscanf(f, "%*[^\n]%*[\n]");
 77			errno = ERANGE;
 78			return 0;
 79		}
 80
 81		len = strlen(linebuf);
 82		if (len > INT_MAX) continue;
 83		for (i = 0; i < sizeof n / sizeof *n; i++) n[i] = len;
 84		sscanf(linebuf, " %n%*[^ \t]%n %n%*[^ \t]%n %n%*[^ \t]%n %n%*[^ \t]%n %d %d",
 85			n, n+1, n+2, n+3, n+4, n+5, n+6, n+7,
 86			&mnt->mnt_freq, &mnt->mnt_passno);
 87	} while (linebuf[n[0]] == '#' || n[1]==len);
 88
 89	linebuf[n[1]] = 0;
 90	linebuf[n[3]] = 0;
 91	linebuf[n[5]] = 0;
 92	linebuf[n[7]] = 0;
 93
 94	mnt->mnt_fsname = unescape_ent(linebuf+n[0]);
 95	mnt->mnt_dir = unescape_ent(linebuf+n[2]);
 96	mnt->mnt_type = unescape_ent(linebuf+n[4]);
 97	mnt->mnt_opts = unescape_ent(linebuf+n[6]);
 98
 99	return mnt;
100}
101
102struct mntent *getmntent(FILE *f)
103{
104	static struct mntent mnt;
105	return getmntent_r(f, &mnt, SENTINEL, 0);
106}
107
108int addmntent(FILE *f, const struct mntent *mnt)
109{
110	if (fseek(f, 0, SEEK_END)) return 1;
111	return fprintf(f, "%s\t%s\t%s\t%s\t%d\t%d\n",
112		mnt->mnt_fsname, mnt->mnt_dir, mnt->mnt_type, mnt->mnt_opts,
113		mnt->mnt_freq, mnt->mnt_passno) < 0;
114}
115
116char *hasmntopt(const struct mntent *mnt, const char *opt)
117{
118	return strstr(mnt->mnt_opts, opt);
119}