|
Packit |
8480eb |
/* ----------------------------------------------------------------------- *
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* ctl-dev-lib.c - module for Linux automount mount table lookup functions
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* Copyright 2008 Red Hat, Inc. All rights reserved.
|
|
Packit |
8480eb |
* Copyright 2008 Ian Kent <raven@themaw.net> - All Rights Reserved
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
8480eb |
* it under the terms of the GNU General Public License as published by
|
|
Packit |
8480eb |
* the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
|
|
Packit |
8480eb |
* USA; either version 2 of the License, or (at your option) any later
|
|
Packit |
8480eb |
* version; incorporated herein by reference.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* ----------------------------------------------------------------------- */
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#include <stdio.h>
|
|
Packit |
8480eb |
#include <stdlib.h>
|
|
Packit |
8480eb |
#include <string.h>
|
|
Packit |
8480eb |
#include <errno.h>
|
|
Packit |
8480eb |
#include <limits.h>
|
|
Packit |
8480eb |
#include <sys/types.h>
|
|
Packit |
8480eb |
#include <sys/stat.h>
|
|
Packit |
8480eb |
#include <sys/ioctl.h>
|
|
Packit |
8480eb |
#include <fcntl.h>
|
|
Packit |
8480eb |
#include <sys/vfs.h>
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#include "automount.h"
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* ioctld control function interface */
|
|
Packit |
8480eb |
static struct ioctl_ctl ctl = { -1, NULL };
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#ifndef AUTOFS_SUPER_MAGIC
|
|
Packit |
8480eb |
#define AUTOFS_SUPER_MAGIC 0x0187
|
|
Packit |
8480eb |
#endif
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Define functions for autofs ioctl control.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* We provide two interfaces. One which routes ioctls via a
|
|
Packit |
8480eb |
* miscelaneous device node and can be used to obtain an ioctl
|
|
Packit |
8480eb |
* file descriptor for autofs mounts that are covered by an
|
|
Packit |
8480eb |
* active mount (eg. active direct or multi-mount offsets).
|
|
Packit |
8480eb |
* The other provides the traditional autofs ioctl implementation.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* The miscielaneous device control functions are prefixed with
|
|
Packit |
8480eb |
* dev_ctl_ and the traditional ones are prefixed with ioctl_.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
static int dev_ioctl_version(unsigned int, int, struct autofs_dev_ioctl *);
|
|
Packit |
8480eb |
static int dev_ioctl_protover(unsigned int, int, unsigned int *);
|
|
Packit |
8480eb |
static int dev_ioctl_protosubver(unsigned int, int, unsigned int *);
|
|
Packit |
8480eb |
static int dev_ioctl_mount_device(unsigned int, const char *, unsigned int, dev_t *);
|
|
Packit |
8480eb |
static int dev_ioctl_open(unsigned int, int *, dev_t, const char *);
|
|
Packit |
8480eb |
static int dev_ioctl_close(unsigned int, int);
|
|
Packit |
8480eb |
static int dev_ioctl_send_ready(unsigned int, int, unsigned int);
|
|
Packit |
8480eb |
static int dev_ioctl_send_fail(unsigned int, int, unsigned int, int);
|
|
Packit |
8480eb |
static int dev_ioctl_setpipefd(unsigned int, int, int);
|
|
Packit |
8480eb |
static int dev_ioctl_catatonic(unsigned int, int);
|
|
Packit |
8480eb |
static int dev_ioctl_timeout(unsigned int, int, time_t);
|
|
Packit |
8480eb |
static int dev_ioctl_requester(unsigned int, int, const char *, uid_t *, gid_t *);
|
|
Packit |
8480eb |
static int dev_ioctl_expire(unsigned int, int, const char *, unsigned int);
|
|
Packit |
8480eb |
static int dev_ioctl_askumount(unsigned int, int, unsigned int *);
|
|
Packit |
8480eb |
static int dev_ioctl_ismountpoint(unsigned int, int, const char *, unsigned int *);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int ioctl_protover(unsigned int, int, unsigned int *);
|
|
Packit |
8480eb |
static int ioctl_protosubver(unsigned int, int, unsigned int *);
|
|
Packit |
8480eb |
static int ioctl_mount_device(unsigned int, const char *, unsigned int, dev_t *);
|
|
Packit |
8480eb |
static int ioctl_open(unsigned int, int *, dev_t, const char *);
|
|
Packit |
8480eb |
static int ioctl_close(unsigned int, int);
|
|
Packit |
8480eb |
static int ioctl_send_ready(unsigned int, int, unsigned int);
|
|
Packit |
8480eb |
static int ioctl_send_fail(unsigned int, int, unsigned int, int);
|
|
Packit |
8480eb |
static int ioctl_catatonic(unsigned int, int);
|
|
Packit |
8480eb |
static int ioctl_timeout(unsigned int, int, time_t);
|
|
Packit |
8480eb |
static int ioctl_expire(unsigned int, int, const char *, unsigned int);
|
|
Packit |
8480eb |
static int ioctl_askumount(unsigned int, int, unsigned int *);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static struct ioctl_ops dev_ioctl_ops = {
|
|
Packit |
8480eb |
.version = dev_ioctl_version,
|
|
Packit |
8480eb |
.protover = dev_ioctl_protover,
|
|
Packit |
8480eb |
.protosubver = dev_ioctl_protosubver,
|
|
Packit |
8480eb |
.mount_device = dev_ioctl_mount_device,
|
|
Packit |
8480eb |
.open = dev_ioctl_open,
|
|
Packit |
8480eb |
.close = dev_ioctl_close,
|
|
Packit |
8480eb |
.send_ready = dev_ioctl_send_ready,
|
|
Packit |
8480eb |
.send_fail = dev_ioctl_send_fail,
|
|
Packit |
8480eb |
.setpipefd = dev_ioctl_setpipefd,
|
|
Packit |
8480eb |
.catatonic = dev_ioctl_catatonic,
|
|
Packit |
8480eb |
.timeout = dev_ioctl_timeout,
|
|
Packit |
8480eb |
.requester = dev_ioctl_requester,
|
|
Packit |
8480eb |
.expire = dev_ioctl_expire,
|
|
Packit |
8480eb |
.askumount = dev_ioctl_askumount,
|
|
Packit |
8480eb |
.ismountpoint = dev_ioctl_ismountpoint
|
|
Packit |
8480eb |
};
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static struct ioctl_ops ioctl_ops = {
|
|
Packit |
8480eb |
.version = NULL,
|
|
Packit |
8480eb |
.protover = ioctl_protover,
|
|
Packit |
8480eb |
.protosubver = ioctl_protosubver,
|
|
Packit |
8480eb |
.mount_device = ioctl_mount_device,
|
|
Packit |
8480eb |
.open = ioctl_open,
|
|
Packit |
8480eb |
.close = ioctl_close,
|
|
Packit |
8480eb |
.send_ready = ioctl_send_ready,
|
|
Packit |
8480eb |
.send_fail = ioctl_send_fail,
|
|
Packit |
8480eb |
.setpipefd = NULL,
|
|
Packit |
8480eb |
.catatonic = ioctl_catatonic,
|
|
Packit |
8480eb |
.timeout = ioctl_timeout,
|
|
Packit |
8480eb |
.requester = NULL,
|
|
Packit |
8480eb |
.expire = ioctl_expire,
|
|
Packit |
8480eb |
.askumount = ioctl_askumount,
|
|
Packit |
8480eb |
.ismountpoint = NULL
|
|
Packit |
8480eb |
};
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Allocate the control struct that holds the misc device file
|
|
Packit |
8480eb |
* descriptor and operation despatcher table.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
void init_ioctl_ctl(void)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int devfd;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ctl.ops)
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
devfd = open_fd(CONTROL_DEVICE, O_RDONLY);
|
|
Packit |
8480eb |
if (devfd == -1)
|
|
Packit |
8480eb |
ctl.ops = &ioctl_ops;
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
struct autofs_dev_ioctl param;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Check compile version against kernel.
|
|
Packit |
8480eb |
* Selinux may allow us to open the device but not
|
|
Packit |
8480eb |
* actually allow us to do anything.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
init_autofs_dev_ioctl(¶m;;
|
|
Packit |
8480eb |
if (ioctl(devfd, AUTOFS_DEV_IOCTL_VERSION, ¶m) == -1) {
|
|
Packit |
8480eb |
close(devfd);
|
|
Packit |
8480eb |
ctl.ops = &ioctl_ops;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
ctl.devfd = devfd;
|
|
Packit |
8480eb |
ctl.ops = &dev_ioctl_ops;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void close_ioctl_ctl(void)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
if (ctl.devfd != -1) {
|
|
Packit |
8480eb |
close(ctl.devfd);
|
|
Packit |
8480eb |
ctl.devfd = -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
ctl.ops = NULL;
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Return a pointer to the operations control struct */
|
|
Packit |
8480eb |
struct ioctl_ops *get_ioctl_ops(void)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
if (!ctl.ops)
|
|
Packit |
8480eb |
init_ioctl_ctl();
|
|
Packit |
8480eb |
return ctl.ops;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Get kenrel version of misc device code */
|
|
Packit |
8480eb |
static int dev_ioctl_version(unsigned int logopt,
|
|
Packit |
8480eb |
int ioctlfd, struct autofs_dev_ioctl *param)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
param->ioctlfd = ioctlfd;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_VERSION, param) == -1)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Get major version of autofs kernel module mount protocol */
|
|
Packit |
8480eb |
static int dev_ioctl_protover(unsigned int logopt,
|
|
Packit |
8480eb |
int ioctlfd, unsigned int *major)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct autofs_dev_ioctl param;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
init_autofs_dev_ioctl(¶m;;
|
|
Packit |
8480eb |
param.ioctlfd = ioctlfd;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_PROTOVER, ¶m) == -1)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*major = param.protover.version;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int ioctl_protover(unsigned int logopt,
|
|
Packit |
8480eb |
int ioctlfd, unsigned int *major)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
return ioctl(ioctlfd, AUTOFS_IOC_PROTOVER, major);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Get minor version of autofs kernel module mount protocol */
|
|
Packit |
8480eb |
static int dev_ioctl_protosubver(unsigned int logopt,
|
|
Packit |
8480eb |
int ioctlfd, unsigned int *minor)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct autofs_dev_ioctl param;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
init_autofs_dev_ioctl(¶m;;
|
|
Packit |
8480eb |
param.ioctlfd = ioctlfd;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_PROTOSUBVER, ¶m) == -1)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*minor = param.protosubver.sub_version;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int ioctl_protosubver(unsigned int logopt,
|
|
Packit |
8480eb |
int ioctlfd, unsigned int *minor)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
return ioctl(ioctlfd, AUTOFS_IOC_PROTOSUBVER, minor);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Allocate a parameter struct for misc device ioctl used when
|
|
Packit |
8480eb |
* opening an autofs mount point. Attach the path to the end
|
|
Packit |
8480eb |
* of the struct. and lookup the device number if not given.
|
|
Packit |
8480eb |
* Locating the device number relies on the mount option
|
|
Packit |
8480eb |
* "dev=<device number>" being present in the autofs fs mount
|
|
Packit |
8480eb |
* options.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
static struct autofs_dev_ioctl *alloc_dev_ioctl_open(const char *path, dev_t devid)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct autofs_dev_ioctl *ioctl;
|
|
Packit |
8480eb |
size_t size, p_len;
|
|
Packit |
8480eb |
dev_t devno = devid;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!path)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
p_len = strlen(path);
|
|
Packit |
8480eb |
size = sizeof(struct autofs_dev_ioctl) + p_len + 1;
|
|
Packit |
8480eb |
ioctl = malloc(size);
|
|
Packit |
8480eb |
if (!ioctl) {
|
|
Packit |
8480eb |
errno = ENOMEM;
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
init_autofs_dev_ioctl(ioctl);
|
|
Packit |
8480eb |
ioctl->size = size;
|
|
Packit |
8480eb |
memcpy(ioctl->path, path, p_len);
|
|
Packit |
8480eb |
ioctl->path[p_len] = '\0';
|
|
Packit |
8480eb |
ioctl->openmount.devid = devno;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return ioctl;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void free_dev_ioctl_open(struct autofs_dev_ioctl *ioctl)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
free(ioctl);
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Allocate a parameter struct for misc device ioctl which includes
|
|
Packit |
8480eb |
* a path. This is used when getting the last mount requester uid
|
|
Packit |
8480eb |
* and gid and when checking if a path within the autofs filesystem
|
|
Packit |
8480eb |
* is a mount point. We add the path to the end of the struct.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
static struct autofs_dev_ioctl *alloc_dev_ioctl_path(int ioctlfd, const char *path)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct autofs_dev_ioctl *ioctl;
|
|
Packit |
8480eb |
size_t size, p_len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!path) {
|
|
Packit |
8480eb |
errno = EINVAL;
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
p_len = strlen(path);
|
|
Packit |
8480eb |
size = sizeof(struct autofs_dev_ioctl) + p_len + 1;
|
|
Packit |
8480eb |
ioctl = malloc(size);
|
|
Packit |
8480eb |
if (!ioctl) {
|
|
Packit |
8480eb |
errno = ENOMEM;
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
init_autofs_dev_ioctl(ioctl);
|
|
Packit |
8480eb |
ioctl->ioctlfd = ioctlfd;
|
|
Packit |
8480eb |
ioctl->size = size;
|
|
Packit |
8480eb |
memcpy(ioctl->path, path, p_len);
|
|
Packit |
8480eb |
ioctl->path[p_len] = '\0';
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return ioctl;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void free_dev_ioctl_path(struct autofs_dev_ioctl *ioctl)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
free(ioctl);
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Find the device number of an autofs mount with given path and
|
|
Packit |
8480eb |
* type (eg..AUTOFS_TYPE_DIRECT). The device number is used by
|
|
Packit |
8480eb |
* the kernel to identify the autofs super block when searching
|
|
Packit |
8480eb |
* for the mount.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
static int dev_ioctl_mount_device(unsigned int logopt, const char *path, unsigned int type, dev_t *devid)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct autofs_dev_ioctl *param;
|
|
Packit |
8480eb |
int err;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!path) {
|
|
Packit |
8480eb |
errno = EINVAL;
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*devid = -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
param = alloc_dev_ioctl_path(-1, path);
|
|
Packit |
8480eb |
if (!param)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
param->ismountpoint.in.type = type;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
err = ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_ISMOUNTPOINT, param);
|
|
Packit |
8480eb |
if (err == -1) {
|
|
Packit |
8480eb |
int save_errno = errno;
|
|
Packit |
8480eb |
free_dev_ioctl_path(param);
|
|
Packit |
8480eb |
errno = save_errno;
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (err)
|
|
Packit |
8480eb |
*devid = param->ismountpoint.out.devid;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free_dev_ioctl_path(param);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return err;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int ioctl_mount_device(unsigned int logopt,
|
|
Packit |
8480eb |
const char *path, unsigned int type,
|
|
Packit |
8480eb |
dev_t *devid)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Get a file descriptor for control operations */
|
|
Packit |
8480eb |
static int dev_ioctl_open(unsigned int logopt,
|
|
Packit |
8480eb |
int *ioctlfd, dev_t devid, const char *path)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct autofs_dev_ioctl *param;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*ioctlfd = -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
param = alloc_dev_ioctl_open(path, devid);
|
|
Packit |
8480eb |
if (!param)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_OPENMOUNT, param) == -1) {
|
|
Packit |
8480eb |
int save_errno = errno;
|
|
Packit |
8480eb |
free_dev_ioctl_open(param);
|
|
Packit |
8480eb |
errno = save_errno;
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*ioctlfd = param->ioctlfd;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free_dev_ioctl_open(param);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int ioctl_open(unsigned int logopt,
|
|
Packit |
8480eb |
int *ioctlfd, dev_t devid, const char *path)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct statfs sfs;
|
|
Packit |
8480eb |
int save_errno, fd;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*ioctlfd = -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
fd = open_fd(path, O_RDONLY);
|
|
Packit |
8480eb |
if (fd == -1)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (fstatfs(fd, &sfs) == -1) {
|
|
Packit |
8480eb |
save_errno = errno;
|
|
Packit |
8480eb |
goto err;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (sfs.f_type != AUTOFS_SUPER_MAGIC) {
|
|
Packit |
8480eb |
save_errno = ENOENT;
|
|
Packit |
8480eb |
goto err;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*ioctlfd = fd;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
err:
|
|
Packit |
8480eb |
close(fd);
|
|
Packit |
8480eb |
errno = save_errno;
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Close */
|
|
Packit |
8480eb |
static int dev_ioctl_close(unsigned int logopt, int ioctlfd)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct autofs_dev_ioctl param;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
init_autofs_dev_ioctl(¶m;;
|
|
Packit |
8480eb |
param.ioctlfd = ioctlfd;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_CLOSEMOUNT, ¶m) == -1)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int ioctl_close(unsigned int logopt, int ioctlfd)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
return close(ioctlfd);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Send ready status for given token */
|
|
Packit |
8480eb |
static int dev_ioctl_send_ready(unsigned int logopt,
|
|
Packit |
8480eb |
int ioctlfd, unsigned int token)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct autofs_dev_ioctl param;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (token == 0) {
|
|
Packit |
8480eb |
errno = EINVAL;
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(logopt, "token = %d", token);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
init_autofs_dev_ioctl(¶m;;
|
|
Packit |
8480eb |
param.ioctlfd = ioctlfd;
|
|
Packit |
8480eb |
param.ready.token = token;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_READY, ¶m) == -1) {
|
|
Packit |
8480eb |
char *estr, buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
int save_errno = errno;
|
|
Packit |
8480eb |
estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
logerr("AUTOFS_DEV_IOCTL_READY: error %s", estr);
|
|
Packit |
8480eb |
errno = save_errno;
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int ioctl_send_ready(unsigned int logopt,
|
|
Packit |
8480eb |
int ioctlfd, unsigned int token)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
if (token == 0) {
|
|
Packit |
8480eb |
errno = EINVAL;
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(logopt, "token = %d", token);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ioctl(ioctlfd, AUTOFS_IOC_READY, token) == -1) {
|
|
Packit |
8480eb |
char *estr, buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
int save_errno = errno;
|
|
Packit |
8480eb |
estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
logerr("AUTOFS_IOC_READY: error %s", estr);
|
|
Packit |
8480eb |
errno = save_errno;
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Send ready status for given token.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* The device node ioctl implementation allows for sending a status
|
|
Packit |
8480eb |
* of other than ENOENT, unlike the tradional interface.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
static int dev_ioctl_send_fail(unsigned int logopt,
|
|
Packit |
8480eb |
int ioctlfd, unsigned int token, int status)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct autofs_dev_ioctl param;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (token == 0) {
|
|
Packit |
8480eb |
errno = EINVAL;
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(logopt, "token = %d", token);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
init_autofs_dev_ioctl(¶m;;
|
|
Packit |
8480eb |
param.ioctlfd = ioctlfd;
|
|
Packit |
8480eb |
param.fail.token = token;
|
|
Packit |
8480eb |
param.fail.status = status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_FAIL, ¶m) == -1) {
|
|
Packit |
8480eb |
char *estr, buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
int save_errno = errno;
|
|
Packit |
8480eb |
estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
logerr("AUTOFS_DEV_IOCTL_FAIL: error %s", estr);
|
|
Packit |
8480eb |
errno = save_errno;
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int ioctl_send_fail(unsigned int logopt,
|
|
Packit |
8480eb |
int ioctlfd, unsigned int token, int status)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
if (token == 0) {
|
|
Packit |
8480eb |
errno = EINVAL;
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(logopt, "token = %d", token);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ioctl(ioctlfd, AUTOFS_IOC_FAIL, token) == -1) {
|
|
Packit |
8480eb |
char *estr, buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
int save_errno = errno;
|
|
Packit |
8480eb |
estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
logerr("AUTOFS_IOC_FAIL: error %s", estr);
|
|
Packit |
8480eb |
errno = save_errno;
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Set the pipe fd for kernel communication.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* Normally this is set at mount using an option but if we
|
|
Packit |
8480eb |
* are reconnecting to a busy mount then we need to use this
|
|
Packit |
8480eb |
* to tell the autofs kernel module about the new pipe fd. In
|
|
Packit |
8480eb |
* order to protect mounts against incorrectly setting the
|
|
Packit |
8480eb |
* pipefd we also require that the autofs mount be catatonic.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* If successful this also sets the process group id used to
|
|
Packit |
8480eb |
* identify the controlling process to the process group of
|
|
Packit |
8480eb |
* the caller.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
static int dev_ioctl_setpipefd(unsigned int logopt, int ioctlfd, int pipefd)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct autofs_dev_ioctl param;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (pipefd == -1) {
|
|
Packit |
8480eb |
errno = EBADF;
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
init_autofs_dev_ioctl(¶m;;
|
|
Packit |
8480eb |
param.ioctlfd = ioctlfd;
|
|
Packit |
8480eb |
param.setpipefd.pipefd = pipefd;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_SETPIPEFD, ¶m) == -1)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Make the autofs mount point catatonic, no longer responsive to
|
|
Packit |
8480eb |
* mount requests. Also closes the kernel pipe file descriptor.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
static int dev_ioctl_catatonic(unsigned int logopt, int ioctlfd)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct autofs_dev_ioctl param;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
init_autofs_dev_ioctl(¶m;;
|
|
Packit |
8480eb |
param.ioctlfd = ioctlfd;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_CATATONIC, ¶m) == -1)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int ioctl_catatonic(unsigned int logopt, int ioctlfd)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
return ioctl(ioctlfd, AUTOFS_IOC_CATATONIC, 0);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Set the autofs mount timeout */
|
|
Packit |
8480eb |
static int dev_ioctl_timeout(unsigned int logopt, int ioctlfd, time_t timeout)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct autofs_dev_ioctl param;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
init_autofs_dev_ioctl(¶m;;
|
|
Packit |
8480eb |
param.ioctlfd = ioctlfd;
|
|
Packit |
8480eb |
param.timeout.timeout = timeout;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_TIMEOUT, ¶m) == -1)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int ioctl_timeout(unsigned int logopt, int ioctlfd, time_t timeout)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
time_t tout = timeout;
|
|
Packit |
8480eb |
return ioctl(ioctlfd, AUTOFS_IOC_SETTIMEOUT, &tout);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Get the uid and gid of the last request for the mountpoint, path.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* When reconstructing an autofs mount tree with active mounts
|
|
Packit |
8480eb |
* we need to re-connect to mounts that may have used the original
|
|
Packit |
8480eb |
* process uid and gid (or string variations of them) for mount
|
|
Packit |
8480eb |
* lookups within the map entry.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
static int dev_ioctl_requester(unsigned int logopt,
|
|
Packit |
8480eb |
int ioctlfd, const char *path,
|
|
Packit |
8480eb |
uid_t *uid, gid_t *gid)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct autofs_dev_ioctl *param;
|
|
Packit |
8480eb |
int err;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!path)
|
|
Packit |
8480eb |
errno = EINVAL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*uid = -1;
|
|
Packit |
8480eb |
*gid = -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
param = alloc_dev_ioctl_path(ioctlfd, path);
|
|
Packit |
8480eb |
if (!param)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
err = ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_REQUESTER, param);
|
|
Packit |
8480eb |
if (err == -1) {
|
|
Packit |
8480eb |
int save_errno = errno;
|
|
Packit |
8480eb |
free_dev_ioctl_open(param);
|
|
Packit |
8480eb |
errno = save_errno;
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*uid = param->requester.uid;
|
|
Packit |
8480eb |
*gid = param->requester.gid;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free_dev_ioctl_path(param);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Call repeatedly until it returns EAGAIN, meaning there's nothing
|
|
Packit |
8480eb |
* more that can be done.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
static int expire(unsigned int logopt,
|
|
Packit |
8480eb |
int cmd, int fd, int ioctlfd, const char *path, void *arg)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int ret, retries = EXPIRE_RETRIES;
|
|
Packit |
8480eb |
unsigned int may_umount;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (retries--) {
|
|
Packit |
8480eb |
struct timespec tm = {0, 100000000};
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Ggenerate expire message for the mount. */
|
|
Packit |
8480eb |
ret = ioctl(fd, cmd, arg);
|
|
Packit |
8480eb |
if (ret == -1) {
|
|
Packit |
8480eb |
/* Mount has gone away */
|
|
Packit |
8480eb |
if (errno == EBADF || errno == EINVAL)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Other than EAGAIN is an expire error so continue.
|
|
Packit |
8480eb |
* Kernel will try the next mount for indirect maps
|
|
Packit |
8480eb |
* and the same mount again for direct maps, limited
|
|
Packit |
8480eb |
* by retries.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (errno == EAGAIN)
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
nanosleep(&tm, NULL);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
may_umount = 0;
|
|
Packit |
8480eb |
if (ctl.ops->askumount(logopt, ioctlfd, &may_umount))
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!may_umount)
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int dev_ioctl_expire(unsigned int logopt,
|
|
Packit |
8480eb |
int ioctlfd, const char *path, unsigned int when)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct autofs_dev_ioctl param;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
init_autofs_dev_ioctl(¶m;;
|
|
Packit |
8480eb |
param.ioctlfd = ioctlfd;
|
|
Packit |
8480eb |
param.expire.how = when;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return expire(logopt, AUTOFS_DEV_IOCTL_EXPIRE,
|
|
Packit |
8480eb |
ctl.devfd, ioctlfd, path, (void *) ¶m;;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int ioctl_expire(unsigned int logopt,
|
|
Packit |
8480eb |
int ioctlfd, const char *path, unsigned int when)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
return expire(logopt, AUTOFS_IOC_EXPIRE_MULTI,
|
|
Packit |
8480eb |
ioctlfd, ioctlfd, path, (void *) &when);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Check if autofs mount point is in use */
|
|
Packit |
8480eb |
static int dev_ioctl_askumount(unsigned int logopt,
|
|
Packit |
8480eb |
int ioctlfd, unsigned int *busy)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct autofs_dev_ioctl param;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
init_autofs_dev_ioctl(¶m;;
|
|
Packit |
8480eb |
param.ioctlfd = ioctlfd;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_ASKUMOUNT, ¶m) == -1)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*busy = param.askumount.may_umount;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int ioctl_askumount(unsigned int logopt,
|
|
Packit |
8480eb |
int ioctlfd, unsigned int *busy)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
return ioctl(ioctlfd, AUTOFS_IOC_ASKUMOUNT, busy);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Check if the given path is a mountpoint.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* The path is considered a mountpoint if it is itself a mountpoint
|
|
Packit |
8480eb |
* or contains a mount, such as a multi-mount without a root mount.
|
|
Packit |
8480eb |
* In addition, if the path is itself a mountpoint we return whether
|
|
Packit |
8480eb |
* the mounted file system is an autofs filesystem or other file
|
|
Packit |
8480eb |
* system.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
static int dev_ioctl_ismountpoint(unsigned int logopt,
|
|
Packit |
8480eb |
int ioctlfd, const char *path,
|
|
Packit |
8480eb |
unsigned int *mountpoint)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct autofs_dev_ioctl *param;
|
|
Packit |
8480eb |
int err;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*mountpoint = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!path) {
|
|
Packit |
8480eb |
errno = EINVAL;
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
param = alloc_dev_ioctl_path(ioctlfd, path);
|
|
Packit |
8480eb |
if (!param)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
set_autofs_type_any(¶m->ismountpoint.in.type);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
err = ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_ISMOUNTPOINT, param);
|
|
Packit |
8480eb |
if (err == -1) {
|
|
Packit |
8480eb |
int save_errno = errno;
|
|
Packit |
8480eb |
free_dev_ioctl_path(param);
|
|
Packit |
8480eb |
errno = save_errno;
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (err) {
|
|
Packit |
8480eb |
*mountpoint = DEV_IOCTL_IS_MOUNTED;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (param->ismountpoint.out.magic == AUTOFS_SUPER_MAGIC)
|
|
Packit |
8480eb |
*mountpoint |= DEV_IOCTL_IS_AUTOFS;
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
*mountpoint |= DEV_IOCTL_IS_OTHER;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free_dev_ioctl_path(param);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|