#include <sys/types.h>
#include <sys/uio.h>
#include <sys/stat.h>
#include <errno.h>
#include <limits.h>
#include <fstab.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static FILE *_fs_fp;
static struct fstab _fs_fstab;
static int fstabscan(void);
static int
fstabscan(void)
{
char *cp;
#define MAXLINELENGTH 1024
static char line[MAXLINELENGTH];
char subline[MAXLINELENGTH];
const char *errstr;
char *last;
int typexx;
for (;;) {
if (!(cp = fgets(line, sizeof(line), _fs_fp)))
return(0);
if (!strpbrk(cp, " \t")) {
_fs_fstab.fs_spec = strtok_r(cp, ":\n", &last);
if (!_fs_fstab.fs_spec || *_fs_fstab.fs_spec == '#')
continue;
_fs_fstab.fs_file = strtok_r(NULL, ":\n", &last);
_fs_fstab.fs_type = strtok_r(NULL, ":\n", &last);
if (_fs_fstab.fs_type) {
if (!strcmp(_fs_fstab.fs_type, FSTAB_XX))
continue;
_fs_fstab.fs_mntops = _fs_fstab.fs_type;
_fs_fstab.fs_vfstype =
strcmp(_fs_fstab.fs_type, FSTAB_SW) ?
"ufs" : "swap";
if ((cp = strtok_r(NULL, ":\n", &last))) {
_fs_fstab.fs_freq = strtonum(cp, 0,
INT_MAX, &errstr);
if (errstr)
goto bad;
if ((cp = strtok_r(NULL,
":\n", &last))) {
_fs_fstab.fs_passno =
strtonum(cp, 0, INT_MAX,
&errstr);
if (errstr)
goto bad;
return(1);
}
}
}
goto bad;
}
_fs_fstab.fs_spec = strtok_r(cp, " \t\n", &last);
if (!_fs_fstab.fs_spec || *_fs_fstab.fs_spec == '#')
continue;
_fs_fstab.fs_file = strtok_r(NULL, " \t\n", &last);
_fs_fstab.fs_vfstype = strtok_r(NULL, " \t\n", &last);
_fs_fstab.fs_mntops = strtok_r(NULL, " \t\n", &last);
if (_fs_fstab.fs_mntops == NULL)
goto bad;
_fs_fstab.fs_freq = 0;
_fs_fstab.fs_passno = 0;
if ((cp = strtok_r(NULL, " \t\n", &last)) != NULL) {
_fs_fstab.fs_freq = strtonum(cp, 0, INT_MAX, &errstr);
if (errstr)
goto bad;
if ((cp = strtok_r(NULL, " \t\n", &last)) != NULL) {
_fs_fstab.fs_passno = strtonum(cp, 0, INT_MAX,
&errstr);
if (errstr)
goto bad;
}
}
strlcpy(subline, _fs_fstab.fs_mntops, sizeof subline);
for (typexx = 0, cp = strtok_r(subline, ",", &last); cp;
cp = strtok_r(NULL, ",", &last)) {
if (strlen(cp) != 2)
continue;
if (!strcmp(cp, FSTAB_RW)) {
_fs_fstab.fs_type = FSTAB_RW;
break;
}
if (!strcmp(cp, FSTAB_RQ)) {
_fs_fstab.fs_type = FSTAB_RQ;
break;
}
if (!strcmp(cp, FSTAB_RO)) {
_fs_fstab.fs_type = FSTAB_RO;
break;
}
if (!strcmp(cp, FSTAB_SW)) {
_fs_fstab.fs_type = FSTAB_SW;
break;
}
if (!strcmp(cp, FSTAB_XX)) {
_fs_fstab.fs_type = FSTAB_XX;
typexx++;
break;
}
}
if (typexx)
continue;
if (cp != NULL)
return(1);
bad:
;
}
}
struct fstab *
getfsent(void)
{
if ((!_fs_fp && !setfsent()) || !fstabscan())
return(NULL);
return(&_fs_fstab);
}
struct fstab *
getfsspec(const char *name)
{
if (setfsent())
while (fstabscan())
if (!strcmp(_fs_fstab.fs_spec, name))
return(&_fs_fstab);
return(NULL);
}
struct fstab *
getfsfile(const char *name)
{
if (setfsent())
while (fstabscan())
if (!strcmp(_fs_fstab.fs_file, name))
return(&_fs_fstab);
return(NULL);
}
int
setfsent(void)
{
struct stat sbuf;
if (_fs_fp) {
rewind(_fs_fp);
return(1);
}
if (stat(_PATH_FSTAB, &sbuf) != 0)
goto fail;
if ((sbuf.st_size == 0) || ((sbuf.st_mode & S_IFMT) != S_IFREG)) {
errno = EFTYPE;
goto fail;
}
if ((_fs_fp = fopen(_PATH_FSTAB, "re")))
return(1);
fail:
return(0);
}
DEF_WEAK(setfsent);
void
endfsent(void)
{
if (_fs_fp) {
(void)fclose(_fs_fp);
_fs_fp = NULL;
}
}