|
Packit Service |
569379 |
/**
|
|
Packit Service |
569379 |
* @file fsdev.c
|
|
Packit Service |
569379 |
* @brief fsdev API implementation
|
|
Packit Service |
569379 |
* @author "Daniel Kopecek" <dkopecek@redhat.com>
|
|
Packit Service |
569379 |
*
|
|
Packit Service |
569379 |
*/
|
|
Packit Service |
569379 |
/*
|
|
Packit Service |
569379 |
* Copyright 2009 Red Hat Inc., Durham, North Carolina.
|
|
Packit Service |
569379 |
* All Rights Reserved.
|
|
Packit Service |
569379 |
*
|
|
Packit Service |
569379 |
* This library is free software; you can redistribute it and/or
|
|
Packit Service |
569379 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit Service |
569379 |
* License as published by the Free Software Foundation; either
|
|
Packit Service |
569379 |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit Service |
569379 |
*
|
|
Packit Service |
569379 |
* This library is distributed in the hope that it will be useful,
|
|
Packit Service |
569379 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
569379 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
569379 |
* Lesser General Public License for more details.
|
|
Packit Service |
569379 |
*
|
|
Packit Service |
569379 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit Service |
569379 |
* License along with this library; if not, write to the Free Software
|
|
Packit Service |
569379 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
Packit Service |
569379 |
*
|
|
Packit Service |
569379 |
* Authors:
|
|
Packit Service |
569379 |
* "Daniel Kopecek" <dkopecek@redhat.com>
|
|
Packit Service |
569379 |
*/
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
#ifdef HAVE_CONFIG_H
|
|
Packit Service |
569379 |
#include <config.h>
|
|
Packit Service |
569379 |
#endif
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
#include <stdio.h>
|
|
Packit Service |
569379 |
#include <stddef.h>
|
|
Packit Service |
569379 |
#include <string.h>
|
|
Packit Service |
569379 |
#include <ctype.h>
|
|
Packit Service |
569379 |
#include <stdlib.h>
|
|
Packit Service |
569379 |
#include <sys/types.h>
|
|
Packit Service |
569379 |
#include <sys/stat.h>
|
|
Packit Service |
569379 |
#include <errno.h>
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
#if defined(OS_LINUX)
|
|
Packit Service |
569379 |
# include <mntent.h>
|
|
Packit Service |
569379 |
# include <unistd.h>
|
|
Packit Service |
569379 |
#elif defined(OS_SOLARIS)
|
|
Packit Service |
569379 |
# include <sys/mnttab.h>
|
|
Packit Service |
569379 |
# include <sys/mntent.h>
|
|
Packit Service |
569379 |
# include <sys/unistd.h>
|
|
Packit Service |
569379 |
#elif defined(OS_FREEBSD) || defined(OS_APPLE)
|
|
Packit Service |
569379 |
# include <sys/param.h>
|
|
Packit Service |
569379 |
# include <sys/ucred.h>
|
|
Packit Service |
569379 |
# include <sys/mount.h>
|
|
Packit Service |
569379 |
#elif defined(OS_AIX)
|
|
Packit Service |
569379 |
# include <unistd.h>
|
|
Packit Service |
569379 |
# include <mntent.h>
|
|
Packit Service |
569379 |
# include <fshelp.h>
|
|
Packit Service |
569379 |
# include <sys/vfs.h>
|
|
Packit Service |
569379 |
# include <sys/vmount.h>
|
|
Packit Service |
569379 |
# define _PATH_MOUNTED MOUNTED
|
|
Packit Service |
569379 |
#else
|
|
Packit Service |
569379 |
# error "Sorry, your OS isn't supported."
|
|
Packit Service |
569379 |
#endif
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
#include "fsdev.h"
|
|
Packit Service |
5b50fa |
#include "common/util.h"
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
/**
|
|
Packit Service |
569379 |
* Compare two dev_t variables.
|
|
Packit Service |
569379 |
*/
|
|
Packit Service |
569379 |
static int fsdev_cmp(const void *a, const void *b)
|
|
Packit Service |
569379 |
{
|
|
Packit Service |
569379 |
return memcmp(a, b, sizeof(dev_t));
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
#if defined(OS_LINUX) || defined(OS_AIX)
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
#define DEVID_ARRAY_SIZE 16
|
|
Packit Service |
569379 |
#define DEVID_ARRAY_ADD 8
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
#if defined(OS_LINUX)
|
|
Packit Service |
569379 |
static int is_local_fs(struct mntent *ment)
|
|
Packit Service |
569379 |
{
|
|
Packit Service |
569379 |
/*
|
|
Packit Service |
569379 |
* When type of the filesystem is autofs, it means the mtab entry
|
|
Packit Service |
569379 |
* describes the autofs configuration, which means ment->mnt_fsname
|
|
Packit Service |
569379 |
* is a path to the relevant autofs map, eg. /etc/auto.misc. In this
|
|
Packit Service |
569379 |
* situation, the following code which analyses ment->mnt_type would
|
|
Packit Service |
569379 |
* not work. When the filesystem handled by autofs is mounted, there
|
|
Packit Service |
569379 |
* is another different entry in mtab which contains the real block
|
|
Packit Service |
569379 |
* special device or remote filesystem in ment->mnt_fsname, and that
|
|
Packit Service |
569379 |
* will be parsed in a different call of this function.
|
|
Packit Service |
569379 |
*/
|
|
Packit Service |
569379 |
if (!strcmp(ment->mnt_type, "autofs")) {
|
|
Packit Service |
569379 |
return 0;
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
|
|
Packit Service |
5b50fa |
/*
|
|
Packit Service |
5b50fa |
* The following code is inspired by systemd, function fstype_is_network:
|
|
Packit Service |
5b50fa |
* https://github.com/systemd/systemd/blob/21fd6bc263f49b57867d90d2e1f9f255e5509134/src/basic/mountpoint-util.c#L290
|
|
Packit Service |
569379 |
*/
|
|
Packit Service |
569379 |
|
|
Packit Service |
5b50fa |
const char *fstype = ment->mnt_type;
|
|
Packit Service |
5b50fa |
if (oscap_str_startswith(fstype, "fuse.")) {
|
|
Packit Service |
5b50fa |
fstype += strlen("fuse.");
|
|
Packit Service |
5b50fa |
}
|
|
Packit Service |
5b50fa |
const char *network_fs[] = {
|
|
Packit Service |
5b50fa |
"afs",
|
|
Packit Service |
5b50fa |
"ceph",
|
|
Packit Service |
5b50fa |
"cifs",
|
|
Packit Service |
5b50fa |
"smb3",
|
|
Packit Service |
5b50fa |
"smbfs",
|
|
Packit Service |
5b50fa |
"sshfs",
|
|
Packit Service |
5b50fa |
"ncpfs",
|
|
Packit Service |
5b50fa |
"ncp",
|
|
Packit Service |
5b50fa |
"nfs",
|
|
Packit Service |
5b50fa |
"nfs4",
|
|
Packit Service |
5b50fa |
"gfs",
|
|
Packit Service |
5b50fa |
"gfs2",
|
|
Packit Service |
5b50fa |
"glusterfs",
|
|
Packit Service |
5b50fa |
"gpfs",
|
|
Packit Service |
5b50fa |
"pvfs2", /* OrangeFS */
|
|
Packit Service |
5b50fa |
"ocfs2",
|
|
Packit Service |
5b50fa |
"lustre",
|
|
Packit Service |
5b50fa |
"davfs",
|
|
Packit Service |
5b50fa |
NULL
|
|
Packit Service |
5b50fa |
};
|
|
Packit Service |
5b50fa |
for (int i = 0; network_fs[i]; i++) {
|
|
Packit Service |
5b50fa |
if (!strcmp(network_fs[i], fstype)) {
|
|
Packit Service |
5b50fa |
return 0;
|
|
Packit Service |
5b50fa |
}
|
|
Packit Service |
5b50fa |
}
|
|
Packit Service |
569379 |
return 1;
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
#elif defined(OS_AIX)
|
|
Packit Service |
569379 |
static int is_local_fs(struct mntent *ment)
|
|
Packit Service |
569379 |
{
|
|
Packit Service |
569379 |
int i;
|
|
Packit Service |
569379 |
struct vfs_ent *e;
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
static const int remote_fs_types[] = {
|
|
Packit Service |
569379 |
MNT_NFS,
|
|
Packit Service |
569379 |
MNT_NFS3,
|
|
Packit Service |
569379 |
MNT_AUTOFS, /* remote? */
|
|
Packit Service |
569379 |
MNT_NFS4,
|
|
Packit Service |
569379 |
MNT_RFS4,
|
|
Packit Service |
569379 |
MNT_CIFS,
|
|
Packit Service |
569379 |
MNT_BADVFS /* end mark */
|
|
Packit Service |
569379 |
};
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
for (i = 0; remote_fs_types[i] != MNT_BADVFS; i++) {
|
|
Packit Service |
569379 |
e = getvfsbytype(remote_fs_types[i]);
|
|
Packit Service |
569379 |
if (e != NULL
|
|
Packit Service |
569379 |
&& e->vfsent_name != NULL
|
|
Packit Service |
569379 |
&& strcmp(ment->mnt_type, e->vfsent_name) == 0) {
|
|
Packit Service |
569379 |
return 0;
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
return 1;
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
#endif /* OS_AIX */
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
static fsdev_t *__fsdev_init(fsdev_t *lfs)
|
|
Packit Service |
569379 |
{
|
|
Packit Service |
569379 |
int e;
|
|
Packit Service |
569379 |
FILE *fp;
|
|
Packit Service |
569379 |
size_t i;
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
struct mntent *ment;
|
|
Packit Service |
569379 |
struct stat st;
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
fp = setmntent(_PATH_MOUNTED, "r");
|
|
Packit Service |
569379 |
if (fp == NULL) {
|
|
Packit Service |
569379 |
e = errno;
|
|
Packit Service |
569379 |
free(lfs);
|
|
Packit Service |
569379 |
errno = e;
|
|
Packit Service |
569379 |
return (NULL);
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
lfs->ids = malloc(sizeof(dev_t) * DEVID_ARRAY_SIZE);
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
if (lfs->ids == NULL) {
|
|
Packit Service |
569379 |
e = errno;
|
|
Packit Service |
569379 |
free(lfs);
|
|
Packit Service |
569379 |
endmntent(fp);
|
|
Packit Service |
569379 |
errno = e;
|
|
Packit Service |
569379 |
return (NULL);
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
lfs->cnt = DEVID_ARRAY_SIZE;
|
|
Packit Service |
569379 |
i = 0;
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
while ((ment = getmntent(fp)) != NULL) {
|
|
Packit Service |
569379 |
if (!is_local_fs(ment))
|
|
Packit Service |
569379 |
continue;
|
|
Packit Service |
569379 |
if (stat(ment->mnt_dir, &st) != 0)
|
|
Packit Service |
569379 |
continue;
|
|
Packit Service |
569379 |
if (i >= lfs->cnt) {
|
|
Packit Service |
569379 |
lfs->cnt += DEVID_ARRAY_ADD;
|
|
Packit Service |
569379 |
lfs->ids = realloc(lfs->ids, sizeof(dev_t) * lfs->cnt);
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
memcpy(&(lfs->ids[i++]), &st.st_dev, sizeof(dev_t));
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
endmntent(fp);
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
lfs->ids = realloc(lfs->ids, sizeof(dev_t) * i);
|
|
Packit Service |
569379 |
lfs->cnt = (lfs->ids == NULL ? 0 : i);
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
return (lfs);
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
#elif defined(OS_FREEBSD) || defined(OS_APPLE)
|
|
Packit Service |
569379 |
static fsdev_t *__fsdev_init(fsdev_t *lfs)
|
|
Packit Service |
569379 |
{
|
|
Packit Service |
569379 |
struct statfs *mntbuf = NULL;
|
|
Packit Service |
569379 |
struct stat st;
|
|
Packit Service |
569379 |
int i;
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
lfs->cnt = getmntinfo(&mntbuf, (fs == NULL ? MNT_LOCAL : 0) | MNT_NOWAIT);
|
|
Packit Service |
569379 |
lfs->ids = malloc(sizeof(dev_t) * lfs->cnt);
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
for (i = 0; i < lfs->cnt; ++i) {
|
|
Packit Service |
569379 |
if (stat(mntbuf[i].f_mntonname, &st) != 0)
|
|
Packit Service |
569379 |
continue;
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
memcpy(&(lfs->ids[i]), &st.st_dev, sizeof(dev_t));
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
if (i != lfs->cnt) {
|
|
Packit Service |
569379 |
lfs->ids = realloc(lfs->ids, sizeof(dev_t) * i);
|
|
Packit Service |
569379 |
lfs->cnt = i;
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
return (lfs);
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
#elif defined(OS_SOLARIS)
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
#define DEVID_ARRAY_SIZE 16
|
|
Packit Service |
569379 |
#define DEVID_ARRAY_ADD 8
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
static fsdev_t *__fsdev_init(fsdev_t *lfs)
|
|
Packit Service |
569379 |
{
|
|
Packit Service |
569379 |
int e;
|
|
Packit Service |
569379 |
FILE *fp;
|
|
Packit Service |
569379 |
size_t i;
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
struct mnttab mentbuf;
|
|
Packit Service |
569379 |
struct stat st;
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
fp = fopen(MNTTAB, "r");
|
|
Packit Service |
569379 |
if (fp == NULL) {
|
|
Packit Service |
569379 |
e = errno;
|
|
Packit Service |
569379 |
free(lfs);
|
|
Packit Service |
569379 |
errno = e;
|
|
Packit Service |
569379 |
return (NULL);
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
lfs->ids = malloc(sizeof(dev_t) * DEVID_ARRAY_SIZE);
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
if (lfs->ids == NULL) {
|
|
Packit Service |
569379 |
e = errno;
|
|
Packit Service |
569379 |
free(lfs);
|
|
Packit Service |
569379 |
fclose(fp);
|
|
Packit Service |
569379 |
errno = e;
|
|
Packit Service |
569379 |
return (NULL);
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
lfs->cnt = DEVID_ARRAY_SIZE;
|
|
Packit Service |
569379 |
i = 0;
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
while ((getmntent(fp, &mentbuf)) == 0) {
|
|
Packit Service |
569379 |
/* TODO: Is this check reliable? */
|
|
Packit Service |
569379 |
if (stat(mentbuf.mnt_special, &st) == 0 && (st.st_mode & S_IFCHR)) {
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
if (i >= lfs->cnt) {
|
|
Packit Service |
569379 |
lfs->cnt += DEVID_ARRAY_ADD;
|
|
Packit Service |
569379 |
lfs->ids = realloc(lfs->ids, sizeof(dev_t) * lfs->cnt);
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
memcpy(&(lfs->ids[i++]), &st.st_dev, sizeof(dev_t));
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
fclose(fp);
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
lfs->ids = realloc(lfs->ids, sizeof(dev_t) * i);
|
|
Packit Service |
569379 |
lfs->cnt = (lfs->ids == NULL ? 0 : i);
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
return (lfs);
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
#endif
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
fsdev_t *fsdev_init()
|
|
Packit Service |
569379 |
{
|
|
Packit Service |
569379 |
fsdev_t *lfs;
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
lfs = malloc(sizeof(fsdev_t));
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
if (lfs == NULL)
|
|
Packit Service |
569379 |
return (NULL);
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
if (__fsdev_init(lfs) == NULL)
|
|
Packit Service |
569379 |
return (NULL);
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
if (lfs->ids != NULL && lfs->cnt > 1)
|
|
Packit Service |
569379 |
qsort(lfs->ids, lfs->cnt, sizeof(dev_t), fsdev_cmp);
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
return (lfs);
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
static inline int isfschar(int c)
|
|
Packit Service |
569379 |
{
|
|
Packit Service |
569379 |
return (isalpha(c) || isdigit(c) || c == '-' || c == '_');
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
void fsdev_free(fsdev_t * lfs)
|
|
Packit Service |
569379 |
{
|
|
Packit Service |
569379 |
if (lfs != NULL) {
|
|
Packit Service |
569379 |
free(lfs->ids);
|
|
Packit Service |
569379 |
free(lfs);
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
return;
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
int fsdev_search(fsdev_t * lfs, void *id)
|
|
Packit Service |
569379 |
{
|
|
Packit Service |
569379 |
uint16_t w, s;
|
|
Packit Service |
569379 |
int cmp;
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
if (!lfs)
|
|
Packit Service |
569379 |
return 1;
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
w = lfs->cnt;
|
|
Packit Service |
569379 |
s = 0;
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
while (w > 0) {
|
|
Packit Service |
569379 |
cmp = fsdev_cmp(id, &(lfs->ids[s + w / 2]));
|
|
Packit Service |
569379 |
if (cmp > 0) {
|
|
Packit Service |
569379 |
s += w / 2 + 1;
|
|
Packit Service |
569379 |
w = w - w / 2 - 1;
|
|
Packit Service |
569379 |
} else if (cmp < 0) {
|
|
Packit Service |
569379 |
w = w / 2;
|
|
Packit Service |
569379 |
} else {
|
|
Packit Service |
569379 |
return (1);
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
return (0);
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
int fsdev_path(fsdev_t * lfs, const char *path)
|
|
Packit Service |
569379 |
{
|
|
Packit Service |
569379 |
struct stat st;
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
if (stat(path, &st) != 0)
|
|
Packit Service |
569379 |
return (-1);
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
return fsdev_search(lfs, &st.st_dev);
|
|
Packit Service |
569379 |
}
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
int fsdev_fd(fsdev_t * lfs, int fd)
|
|
Packit Service |
569379 |
{
|
|
Packit Service |
569379 |
struct stat st;
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
if (fstat(fd, &st) != 0)
|
|
Packit Service |
569379 |
return (-1);
|
|
Packit Service |
569379 |
|
|
Packit Service |
569379 |
return fsdev_search(lfs, &st.st_dev);
|
|
Packit Service |
569379 |
}
|