|
Packit |
8480eb |
/* ----------------------------------------------------------------------- *
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* mounts.c - module for mount utilities.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* Copyright 2002-2005 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 <stdlib.h>
|
|
Packit |
8480eb |
#include <string.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 <sys/mount.h>
|
|
Packit |
8480eb |
#include <sys/wait.h>
|
|
Packit |
8480eb |
#include <ctype.h>
|
|
Packit |
8480eb |
#include <stdio.h>
|
|
Packit |
8480eb |
#include <dirent.h>
|
|
Packit |
8480eb |
#include <sys/vfs.h>
|
|
Packit |
8480eb |
#include <pwd.h>
|
|
Packit |
8480eb |
#include <grp.h>
|
|
Packit |
8480eb |
#include <libgen.h>
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#include "automount.h"
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#define MAX_OPTIONS_LEN 80
|
|
Packit |
8480eb |
#define MAX_MNT_NAME_LEN 30
|
|
Packit |
8480eb |
#define MAX_ENV_NAME 15
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#define EBUFSIZ 1024
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
const unsigned int t_indirect = AUTOFS_TYPE_INDIRECT;
|
|
Packit |
8480eb |
const unsigned int t_direct = AUTOFS_TYPE_DIRECT;
|
|
Packit |
8480eb |
const unsigned int t_offset = AUTOFS_TYPE_OFFSET;
|
|
Packit |
8480eb |
const unsigned int type_count = 3;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static const char options_template[] = "fd=%d,pgrp=%u,minproto=5,maxproto=%d";
|
|
Packit |
8480eb |
static const char options_template_extra[] = "fd=%d,pgrp=%u,minproto=5,maxproto=%d,%s";
|
|
Packit |
8480eb |
static const char mnt_name_template[] = "automount(pid%u)";
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static struct kernel_mod_version kver = {0, 0};
|
|
Packit |
8480eb |
static const char kver_options_template[] = "fd=%d,pgrp=%u,minproto=3,maxproto=5";
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
extern size_t detached_thread_stack_size;
|
|
Packit |
8480eb |
static size_t maxgrpbuf = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#define EXT_MOUNTS_HASH_SIZE 50
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct ext_mount {
|
|
Packit |
8480eb |
char *mountpoint;
|
|
Packit |
8480eb |
unsigned int umount;
|
|
Packit |
8480eb |
struct list_head mount;
|
|
Packit |
8480eb |
struct list_head mounts;
|
|
Packit |
8480eb |
};
|
|
Packit |
8480eb |
static struct list_head ext_mounts_hash[EXT_MOUNTS_HASH_SIZE];
|
|
Packit |
8480eb |
static unsigned int ext_mounts_hash_init_done = 0;
|
|
Packit |
8480eb |
static pthread_mutex_t ext_mount_hash_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
unsigned int linux_version_code(void)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct utsname my_utsname;
|
|
Packit |
8480eb |
unsigned int p, q, r;
|
|
Packit |
8480eb |
char *tmp, *save;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (uname(&my_utsname))
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
p = q = r = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tmp = strtok_r(my_utsname.release, ".", &save);
|
|
Packit |
8480eb |
if (!tmp)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
p = (unsigned int ) atoi(tmp);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tmp = strtok_r(NULL, ".", &save);
|
|
Packit |
8480eb |
if (!tmp)
|
|
Packit |
8480eb |
return KERNEL_VERSION(p, 0, 0);
|
|
Packit |
8480eb |
q = (unsigned int) atoi(tmp);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tmp = strtok_r(NULL, ".", &save);
|
|
Packit |
8480eb |
if (!tmp)
|
|
Packit |
8480eb |
return KERNEL_VERSION(p, q, 0);
|
|
Packit |
8480eb |
r = (unsigned int) atoi(tmp);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return KERNEL_VERSION(p, q, r);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
unsigned int query_kproto_ver(void)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct ioctl_ops *ops;
|
|
Packit |
8480eb |
char dir[] = "/tmp/autoXXXXXX", *t_dir;
|
|
Packit |
8480eb |
char options[MAX_OPTIONS_LEN + 1];
|
|
Packit |
8480eb |
pid_t pgrp = getpgrp();
|
|
Packit |
8480eb |
int pipefd[2], ioctlfd, len;
|
|
Packit |
8480eb |
struct stat st;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
t_dir = mkdtemp(dir);
|
|
Packit |
8480eb |
if (!t_dir)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (pipe(pipefd) == -1) {
|
|
Packit |
8480eb |
rmdir(t_dir);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
len = snprintf(options, MAX_OPTIONS_LEN,
|
|
Packit |
8480eb |
kver_options_template, pipefd[1], (unsigned) pgrp);
|
|
Packit |
8480eb |
if (len < 0) {
|
|
Packit |
8480eb |
close(pipefd[0]);
|
|
Packit |
8480eb |
close(pipefd[1]);
|
|
Packit |
8480eb |
rmdir(t_dir);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (mount("automount", t_dir, "autofs", MS_MGC_VAL, options)) {
|
|
Packit |
8480eb |
close(pipefd[0]);
|
|
Packit |
8480eb |
close(pipefd[1]);
|
|
Packit |
8480eb |
rmdir(t_dir);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
close(pipefd[1]);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (stat(t_dir, &st) == -1) {
|
|
Packit |
8480eb |
umount(t_dir);
|
|
Packit |
8480eb |
close(pipefd[0]);
|
|
Packit |
8480eb |
rmdir(t_dir);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ops = get_ioctl_ops();
|
|
Packit |
8480eb |
if (!ops) {
|
|
Packit |
8480eb |
umount(t_dir);
|
|
Packit |
8480eb |
close(pipefd[0]);
|
|
Packit |
8480eb |
rmdir(t_dir);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ops->open(LOGOPT_NONE, &ioctlfd, st.st_dev, t_dir);
|
|
Packit |
8480eb |
if (ioctlfd == -1) {
|
|
Packit |
8480eb |
umount(t_dir);
|
|
Packit |
8480eb |
close(pipefd[0]);
|
|
Packit |
8480eb |
close_ioctl_ctl();
|
|
Packit |
8480eb |
rmdir(t_dir);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ops->catatonic(LOGOPT_NONE, ioctlfd);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* If this ioctl() doesn't work, it is kernel version 2 */
|
|
Packit |
8480eb |
if (ops->protover(LOGOPT_NONE, ioctlfd, &kver.major)) {
|
|
Packit |
8480eb |
ops->close(LOGOPT_NONE, ioctlfd);
|
|
Packit |
8480eb |
umount(t_dir);
|
|
Packit |
8480eb |
close(pipefd[0]);
|
|
Packit |
8480eb |
close_ioctl_ctl();
|
|
Packit |
8480eb |
rmdir(t_dir);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* If this ioctl() doesn't work, version is 4 or less */
|
|
Packit |
8480eb |
if (ops->protosubver(LOGOPT_NONE, ioctlfd, &kver.minor)) {
|
|
Packit |
8480eb |
ops->close(LOGOPT_NONE, ioctlfd);
|
|
Packit |
8480eb |
umount(t_dir);
|
|
Packit |
8480eb |
close(pipefd[0]);
|
|
Packit |
8480eb |
close_ioctl_ctl();
|
|
Packit |
8480eb |
rmdir(t_dir);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ops->close(LOGOPT_NONE, ioctlfd);
|
|
Packit |
8480eb |
umount(t_dir);
|
|
Packit |
8480eb |
close(pipefd[0]);
|
|
Packit |
8480eb |
close_ioctl_ctl();
|
|
Packit |
8480eb |
rmdir(t_dir);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
unsigned int get_kver_major(void)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
return kver.major;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
unsigned int get_kver_minor(void)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
return kver.minor;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#ifdef HAVE_MOUNT_NFS
|
|
Packit |
8480eb |
static int extract_version(char *start, struct nfs_mount_vers *vers)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *s_ver = strchr(start, ' ');
|
|
Packit |
8480eb |
if (!s_ver)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
while (*s_ver && !isdigit(*s_ver)) {
|
|
Packit |
8480eb |
s_ver++;
|
|
Packit |
8480eb |
if (!*s_ver)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
vers->major = atoi(strtok(s_ver, "."));
|
|
Packit |
8480eb |
vers->minor = (unsigned int) atoi(strtok(NULL, "."));
|
|
Packit |
8480eb |
vers->fix = (unsigned int) atoi(strtok(NULL, "."));
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int check_nfs_mount_version(struct nfs_mount_vers *vers,
|
|
Packit |
8480eb |
struct nfs_mount_vers *check)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
pid_t f;
|
|
Packit |
8480eb |
int ret, status, pipefd[2];
|
|
Packit |
8480eb |
char errbuf[EBUFSIZ + 1], *p, *sp;
|
|
Packit |
8480eb |
int errp, errn;
|
|
Packit |
8480eb |
sigset_t allsigs, tmpsig, oldsig;
|
|
Packit |
8480eb |
char *s_ver;
|
|
Packit |
8480eb |
int cancel_state;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (open_pipe(pipefd))
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel_state);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
sigfillset(&allsigs);
|
|
Packit |
8480eb |
pthread_sigmask(SIG_BLOCK, &allsigs, &oldsig);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
open_mutex_lock();
|
|
Packit |
8480eb |
f = fork();
|
|
Packit |
8480eb |
if (f == 0) {
|
|
Packit |
8480eb |
reset_signals();
|
|
Packit |
8480eb |
close(pipefd[0]);
|
|
Packit |
8480eb |
dup2(pipefd[1], STDOUT_FILENO);
|
|
Packit |
8480eb |
dup2(pipefd[1], STDERR_FILENO);
|
|
Packit |
8480eb |
close(pipefd[1]);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
execl(PATH_MOUNT_NFS, PATH_MOUNT_NFS, "-V", (char *) NULL);
|
|
Packit |
8480eb |
_exit(255); /* execv() failed */
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tmpsig = oldsig;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
sigaddset(&tmpsig, SIGCHLD);
|
|
Packit |
8480eb |
pthread_sigmask(SIG_SETMASK, &tmpsig, NULL);
|
|
Packit |
8480eb |
open_mutex_unlock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
close(pipefd[1]);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (f < 0) {
|
|
Packit |
8480eb |
close(pipefd[0]);
|
|
Packit |
8480eb |
pthread_sigmask(SIG_SETMASK, &oldsig, NULL);
|
|
Packit |
8480eb |
pthread_setcancelstate(cancel_state, NULL);
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
errp = 0;
|
|
Packit |
8480eb |
do {
|
|
Packit |
8480eb |
while (1) {
|
|
Packit |
8480eb |
errn = read(pipefd[0], errbuf + errp, EBUFSIZ - errp);
|
|
Packit |
8480eb |
if (errn == -1 && errno == EINTR)
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (errn > 0) {
|
|
Packit |
8480eb |
errp += errn;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
sp = errbuf;
|
|
Packit |
8480eb |
while (errp && (p = memchr(sp, '\n', errp))) {
|
|
Packit |
8480eb |
*p++ = '\0';
|
|
Packit |
8480eb |
errp -= (p - sp);
|
|
Packit |
8480eb |
sp = p;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (errp && sp != errbuf)
|
|
Packit |
8480eb |
memmove(errbuf, sp, errp);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (errp >= EBUFSIZ) {
|
|
Packit |
8480eb |
/* Line too long, split */
|
|
Packit |
8480eb |
errbuf[errp] = '\0';
|
|
Packit |
8480eb |
if ((s_ver = strstr(errbuf, "nfs-utils"))) {
|
|
Packit |
8480eb |
if (extract_version(s_ver, vers))
|
|
Packit |
8480eb |
ret = 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
errp = 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if ((s_ver = strstr(errbuf, "nfs-utils"))) {
|
|
Packit |
8480eb |
if (extract_version(s_ver, vers))
|
|
Packit |
8480eb |
ret = 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
} while (errn > 0);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
close(pipefd[0]);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (errp > 0) {
|
|
Packit |
8480eb |
/* End of file without \n */
|
|
Packit |
8480eb |
errbuf[errp] = '\0';
|
|
Packit |
8480eb |
if ((s_ver = strstr(errbuf, "nfs-utils"))) {
|
|
Packit |
8480eb |
if (extract_version(s_ver, vers))
|
|
Packit |
8480eb |
ret = 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ret) {
|
|
Packit |
8480eb |
if ((vers->major < check->major) ||
|
|
Packit |
8480eb |
((vers->major == check->major) && (vers->minor < check->minor)) ||
|
|
Packit |
8480eb |
((vers->major == check->major) && (vers->minor == check->minor) &&
|
|
Packit |
8480eb |
(vers->fix < check->fix)))
|
|
Packit |
8480eb |
ret = 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (waitpid(f, &status, 0) != f)
|
|
Packit |
8480eb |
debug(LOGOPT_NONE, "no process found to wait for");
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_sigmask(SIG_SETMASK, &oldsig, NULL);
|
|
Packit |
8480eb |
pthread_setcancelstate(cancel_state, NULL);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
#else
|
|
Packit |
8480eb |
int check_nfs_mount_version(struct nfs_mount_vers *vers,
|
|
Packit |
8480eb |
struct nfs_mount_vers *check)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
#endif
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static char *set_env_name(const char *prefix, const char *name, char *buf)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
size_t len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
len = strlen(name);
|
|
Packit |
8480eb |
if (prefix)
|
|
Packit |
8480eb |
len += strlen(prefix);
|
|
Packit |
8480eb |
len++;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (len > MAX_ENV_NAME)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!prefix)
|
|
Packit |
8480eb |
strcpy(buf, name);
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
strcpy(buf, prefix);
|
|
Packit |
8480eb |
strcat(buf, name);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return buf;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static struct substvar *do_macro_addvar(struct substvar *list,
|
|
Packit |
8480eb |
const char *prefix,
|
|
Packit |
8480eb |
const char *name,
|
|
Packit |
8480eb |
const char *val)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char buf[MAX_ENV_NAME + 1];
|
|
Packit |
8480eb |
char *new;
|
|
Packit |
8480eb |
size_t len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
new = set_env_name(prefix, name, buf);
|
|
Packit |
8480eb |
if (new) {
|
|
Packit |
8480eb |
len = strlen(new);
|
|
Packit |
8480eb |
list = macro_addvar(list, new, len, val);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return list;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static struct substvar *do_macro_removevar(struct substvar *list,
|
|
Packit |
8480eb |
const char *prefix,
|
|
Packit |
8480eb |
const char *name)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char buf[MAX_ENV_NAME + 1];
|
|
Packit |
8480eb |
char *new;
|
|
Packit |
8480eb |
size_t len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
new = set_env_name(prefix, name, buf);
|
|
Packit |
8480eb |
if (new) {
|
|
Packit |
8480eb |
len = strlen(new);
|
|
Packit |
8480eb |
list = macro_removevar(list, new, len);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return list;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct substvar *addstdenv(struct substvar *sv, const char *prefix)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct substvar *list = sv;
|
|
Packit |
8480eb |
struct thread_stdenv_vars *tsv;
|
|
Packit |
8480eb |
char numbuf[16];
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tsv = pthread_getspecific(key_thread_stdenv_vars);
|
|
Packit |
8480eb |
if (tsv) {
|
|
Packit |
8480eb |
const struct substvar *mv;
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
long num;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
num = (long) tsv->uid;
|
|
Packit |
8480eb |
ret = sprintf(numbuf, "%ld", num);
|
|
Packit |
8480eb |
if (ret > 0)
|
|
Packit |
8480eb |
list = do_macro_addvar(list, prefix, "UID", numbuf);
|
|
Packit |
8480eb |
num = (long) tsv->gid;
|
|
Packit |
8480eb |
ret = sprintf(numbuf, "%ld", num);
|
|
Packit |
8480eb |
if (ret > 0)
|
|
Packit |
8480eb |
list = do_macro_addvar(list, prefix, "GID", numbuf);
|
|
Packit |
8480eb |
list = do_macro_addvar(list, prefix, "USER", tsv->user);
|
|
Packit |
8480eb |
list = do_macro_addvar(list, prefix, "GROUP", tsv->group);
|
|
Packit |
8480eb |
list = do_macro_addvar(list, prefix, "HOME", tsv->home);
|
|
Packit |
8480eb |
mv = macro_findvar(list, "HOST", 4);
|
|
Packit |
8480eb |
if (mv) {
|
|
Packit |
8480eb |
char *shost = strdup(mv->val);
|
|
Packit |
8480eb |
if (shost) {
|
|
Packit |
8480eb |
char *dot = strchr(shost, '.');
|
|
Packit |
8480eb |
if (dot)
|
|
Packit |
8480eb |
*dot = '\0';
|
|
Packit |
8480eb |
list = do_macro_addvar(list,
|
|
Packit |
8480eb |
prefix, "SHOST", shost);
|
|
Packit |
8480eb |
free(shost);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return list;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct substvar *removestdenv(struct substvar *sv, const char *prefix)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct substvar *list = sv;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
list = do_macro_removevar(list, prefix, "UID");
|
|
Packit |
8480eb |
list = do_macro_removevar(list, prefix, "USER");
|
|
Packit |
8480eb |
list = do_macro_removevar(list, prefix, "HOME");
|
|
Packit |
8480eb |
list = do_macro_removevar(list, prefix, "GID");
|
|
Packit |
8480eb |
list = do_macro_removevar(list, prefix, "GROUP");
|
|
Packit |
8480eb |
list = do_macro_removevar(list, prefix, "SHOST");
|
|
Packit |
8480eb |
return list;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void add_std_amd_vars(struct substvar *sv)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *tmp;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tmp = conf_amd_get_arch();
|
|
Packit |
8480eb |
if (tmp) {
|
|
Packit |
8480eb |
macro_global_addvar("arch", 4, tmp);
|
|
Packit |
8480eb |
free(tmp);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tmp = conf_amd_get_karch();
|
|
Packit |
8480eb |
if (tmp) {
|
|
Packit |
8480eb |
macro_global_addvar("karch", 5, tmp);
|
|
Packit |
8480eb |
free(tmp);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tmp = conf_amd_get_os();
|
|
Packit |
8480eb |
if (tmp) {
|
|
Packit |
8480eb |
macro_global_addvar("os", 2, tmp);
|
|
Packit |
8480eb |
free(tmp);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tmp = conf_amd_get_full_os();
|
|
Packit |
8480eb |
if (tmp) {
|
|
Packit |
8480eb |
macro_global_addvar("full_os", 7, tmp);
|
|
Packit |
8480eb |
free(tmp);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tmp = conf_amd_get_os_ver();
|
|
Packit |
8480eb |
if (tmp) {
|
|
Packit |
8480eb |
macro_global_addvar("osver", 5, tmp);
|
|
Packit |
8480eb |
free(tmp);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tmp = conf_amd_get_vendor();
|
|
Packit |
8480eb |
if (tmp) {
|
|
Packit |
8480eb |
macro_global_addvar("vendor", 6, tmp);
|
|
Packit |
8480eb |
free(tmp);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Umm ... HP_UX cluster name, probably not used */
|
|
Packit |
8480eb |
tmp = conf_amd_get_cluster();
|
|
Packit |
8480eb |
if (tmp) {
|
|
Packit |
8480eb |
macro_global_addvar("cluster", 7, tmp);
|
|
Packit |
8480eb |
free(tmp);
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
const struct substvar *v = macro_findvar(sv, "domain", 4);
|
|
Packit |
8480eb |
if (v && *v->val) {
|
|
Packit |
8480eb |
tmp = strdup(v->val);
|
|
Packit |
0f1c87 |
if (tmp) {
|
|
Packit |
8480eb |
macro_global_addvar("cluster", 7, tmp);
|
|
Packit |
0f1c87 |
free(tmp);
|
|
Packit |
0f1c87 |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tmp = conf_amd_get_auto_dir();
|
|
Packit |
8480eb |
if (tmp) {
|
|
Packit |
8480eb |
macro_global_addvar("autodir", 7, tmp);
|
|
Packit |
8480eb |
free(tmp);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void remove_std_amd_vars(void)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
macro_global_removevar("autodir", 7);
|
|
Packit |
8480eb |
macro_global_removevar("cluster", 7);
|
|
Packit |
8480eb |
macro_global_removevar("vendor", 6);
|
|
Packit |
8480eb |
macro_global_removevar("osver", 5);
|
|
Packit |
8480eb |
macro_global_removevar("full_os", 7);
|
|
Packit |
8480eb |
macro_global_removevar("os", 2);
|
|
Packit |
8480eb |
macro_global_removevar("karch", 5);
|
|
Packit |
8480eb |
macro_global_removevar("arch", 4);
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct amd_entry *new_amd_entry(const struct substvar *sv)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct amd_entry *new;
|
|
Packit |
8480eb |
const struct substvar *v;
|
|
Packit |
8480eb |
char *path;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
v = macro_findvar(sv, "path", 4);
|
|
Packit |
8480eb |
if (!v)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
path = strdup(v->val);
|
|
Packit |
8480eb |
if (!path)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
new = malloc(sizeof(struct amd_entry));
|
|
Packit |
8480eb |
if (!new) {
|
|
Packit |
8480eb |
free(path);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
memset(new, 0, sizeof(*new));
|
|
Packit |
8480eb |
new->path = path;
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&new->list);
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&new->entries);
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&new->ext_mount);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return new;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void clear_amd_entry(struct amd_entry *entry)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
if (!entry)
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
if (entry->path)
|
|
Packit |
8480eb |
free(entry->path);
|
|
Packit |
8480eb |
if (entry->map_type)
|
|
Packit |
8480eb |
free(entry->map_type);
|
|
Packit |
8480eb |
if (entry->pref)
|
|
Packit |
8480eb |
free(entry->pref);
|
|
Packit |
8480eb |
if (entry->fs)
|
|
Packit |
8480eb |
free(entry->fs);
|
|
Packit |
8480eb |
if (entry->rhost)
|
|
Packit |
8480eb |
free(entry->rhost);
|
|
Packit |
8480eb |
if (entry->rfs)
|
|
Packit |
8480eb |
free(entry->rfs);
|
|
Packit |
8480eb |
if (entry->opts)
|
|
Packit |
8480eb |
free(entry->opts);
|
|
Packit |
8480eb |
if (entry->addopts)
|
|
Packit |
8480eb |
free(entry->addopts);
|
|
Packit |
8480eb |
if (entry->remopts)
|
|
Packit |
8480eb |
free(entry->remopts);
|
|
Packit |
8480eb |
if (entry->sublink)
|
|
Packit |
8480eb |
free(entry->sublink);
|
|
Packit |
8480eb |
if (entry->selector)
|
|
Packit |
8480eb |
free_selector(entry->selector);
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void free_amd_entry(struct amd_entry *entry)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
clear_amd_entry(entry);
|
|
Packit |
8480eb |
free(entry);
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void free_amd_entry_list(struct list_head *entries)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
if (!list_empty(entries)) {
|
|
Packit |
8480eb |
struct list_head *head = entries;
|
|
Packit |
8480eb |
struct amd_entry *this;
|
|
Packit |
8480eb |
struct list_head *p;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
p = head->next;
|
|
Packit |
8480eb |
while (p != head) {
|
|
Packit |
8480eb |
this = list_entry(p, struct amd_entry, list);
|
|
Packit |
8480eb |
p = p->next;
|
|
Packit |
8480eb |
free_amd_entry(this);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Make common autofs mount options string
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
char *make_options_string(char *path, int pipefd, const char *extra)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *options;
|
|
Packit |
8480eb |
int len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
options = malloc(MAX_OPTIONS_LEN + 1);
|
|
Packit |
8480eb |
if (!options) {
|
|
Packit |
8480eb |
logerr("can't malloc options string");
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (extra)
|
|
Packit |
8480eb |
len = snprintf(options, MAX_OPTIONS_LEN,
|
|
Packit |
8480eb |
options_template_extra,
|
|
Packit |
8480eb |
pipefd, (unsigned) getpgrp(),
|
|
Packit |
8480eb |
AUTOFS_MAX_PROTO_VERSION, extra);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
len = snprintf(options, MAX_OPTIONS_LEN, options_template,
|
|
Packit |
8480eb |
pipefd, (unsigned) getpgrp(),
|
|
Packit |
8480eb |
AUTOFS_MAX_PROTO_VERSION);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (len >= MAX_OPTIONS_LEN) {
|
|
Packit |
8480eb |
logerr("buffer to small for options - truncated");
|
|
Packit |
8480eb |
len = MAX_OPTIONS_LEN - 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (len < 0) {
|
|
Packit |
8480eb |
logerr("failed to malloc autofs mount options for %s", path);
|
|
Packit |
8480eb |
free(options);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
options[len] = '\0';
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return options;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
char *make_mnt_name_string(char *path)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *mnt_name;
|
|
Packit |
8480eb |
int len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mnt_name = malloc(MAX_MNT_NAME_LEN + 1);
|
|
Packit |
8480eb |
if (!mnt_name) {
|
|
Packit |
8480eb |
logerr("can't malloc mnt_name string");
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
len = snprintf(mnt_name, MAX_MNT_NAME_LEN,
|
|
Packit |
8480eb |
mnt_name_template, (unsigned) getpid());
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (len >= MAX_MNT_NAME_LEN) {
|
|
Packit |
8480eb |
logerr("buffer to small for mnt_name - truncated");
|
|
Packit |
8480eb |
len = MAX_MNT_NAME_LEN - 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (len < 0) {
|
|
Packit |
8480eb |
logerr("failed setting up mnt_name for autofs path %s", path);
|
|
Packit |
8480eb |
free(mnt_name);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
mnt_name[len] = '\0';
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return mnt_name;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void ext_mounts_hash_init(void)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int i;
|
|
Packit |
8480eb |
for (i = 0; i < EXT_MOUNTS_HASH_SIZE; i++)
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&ext_mounts_hash[i]);
|
|
Packit |
8480eb |
ext_mounts_hash_init_done = 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static struct ext_mount *ext_mount_lookup(const char *mountpoint)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
u_int32_t hval = hash(mountpoint, EXT_MOUNTS_HASH_SIZE);
|
|
Packit |
8480eb |
struct list_head *p, *head;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!ext_mounts_hash_init_done)
|
|
Packit |
8480eb |
ext_mounts_hash_init();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (list_empty(&ext_mounts_hash[hval]))
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
head = &ext_mounts_hash[hval];
|
|
Packit |
8480eb |
list_for_each(p, head) {
|
|
Packit |
8480eb |
struct ext_mount *this = list_entry(p, struct ext_mount, mount);
|
|
Packit |
8480eb |
if (!strcmp(this->mountpoint, mountpoint))
|
|
Packit |
8480eb |
return this;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int ext_mount_add(struct list_head *entry, const char *path, unsigned int umount)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct ext_mount *em;
|
|
Packit |
8480eb |
u_int32_t hval;
|
|
Packit |
8480eb |
int ret = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_mutex_lock(&ext_mount_hash_mutex);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
em = ext_mount_lookup(path);
|
|
Packit |
8480eb |
if (em) {
|
|
Packit |
8480eb |
struct list_head *p, *head;
|
|
Packit |
8480eb |
head = &em->mounts;
|
|
Packit |
8480eb |
list_for_each(p, head) {
|
|
Packit |
8480eb |
if (p == entry)
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
list_add_tail(entry, &em->mounts);
|
|
Packit |
8480eb |
ret = 1;
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
em = malloc(sizeof(struct ext_mount));
|
|
Packit |
f0deab |
if (!em)
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
em->mountpoint = strdup(path);
|
|
Packit |
8480eb |
if (!em->mountpoint) {
|
|
Packit |
8480eb |
free(em);
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
em->umount = umount;
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&em->mount);
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&em->mounts);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
hval = hash(path, EXT_MOUNTS_HASH_SIZE);
|
|
Packit |
8480eb |
list_add_tail(&em->mount, &ext_mounts_hash[hval]);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
list_add_tail(entry, &em->mounts);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = 1;
|
|
Packit |
8480eb |
done:
|
|
Packit |
8480eb |
pthread_mutex_unlock(&ext_mount_hash_mutex);
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int ext_mount_remove(struct list_head *entry, const char *path)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct ext_mount *em;
|
|
Packit |
8480eb |
int ret = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_mutex_lock(&ext_mount_hash_mutex);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
em = ext_mount_lookup(path);
|
|
Packit |
8480eb |
if (!em)
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
list_del_init(entry);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!list_empty(&em->mounts))
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
list_del_init(&em->mount);
|
|
Packit |
8480eb |
if (em->umount)
|
|
Packit |
8480eb |
ret = 1;
|
|
Packit |
8480eb |
if (list_empty(&em->mount)) {
|
|
Packit |
8480eb |
free(em->mountpoint);
|
|
Packit |
8480eb |
free(em);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
done:
|
|
Packit |
8480eb |
pthread_mutex_unlock(&ext_mount_hash_mutex);
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int ext_mount_inuse(const char *path)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct ext_mount *em;
|
|
Packit |
8480eb |
int ret = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_mutex_lock(&ext_mount_hash_mutex);
|
|
Packit |
8480eb |
em = ext_mount_lookup(path);
|
|
Packit |
8480eb |
if (!em)
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!list_empty(&em->mounts))
|
|
Packit |
8480eb |
ret = 1;
|
|
Packit |
8480eb |
done:
|
|
Packit |
8480eb |
pthread_mutex_unlock(&ext_mount_hash_mutex);
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
736b0b |
/* From glibc decode_name() */
|
|
Packit |
736b0b |
/* Since the values in a line are separated by spaces, a name cannot
|
|
Packit |
736b0b |
* contain a space. Therefore some programs encode spaces in names
|
|
Packit |
736b0b |
* by the strings "\040". We undo the encoding when reading an entry.
|
|
Packit |
736b0b |
* The decoding happens in place.
|
|
Packit |
736b0b |
*/
|
|
Packit |
736b0b |
static char *local_decode_name(char *buf)
|
|
Packit |
736b0b |
{
|
|
Packit |
736b0b |
char *rp = buf;
|
|
Packit |
736b0b |
char *wp = buf;
|
|
Packit |
736b0b |
|
|
Packit |
736b0b |
do {
|
|
Packit |
736b0b |
if (rp[0] == '\\' && rp[1] == '0' &&
|
|
Packit |
736b0b |
rp[2] == '4' && rp[3] == '0') {
|
|
Packit |
736b0b |
/* \040 is a SPACE. */
|
|
Packit |
736b0b |
*wp++ = ' ';
|
|
Packit |
736b0b |
rp += 3;
|
|
Packit |
736b0b |
} else if (rp[0] == '\\' && rp[1] == '0' &&
|
|
Packit |
736b0b |
rp[2] == '1' && rp[3] == '1') {
|
|
Packit |
736b0b |
/* \011 is a TAB. */
|
|
Packit |
736b0b |
*wp++ = '\t';
|
|
Packit |
736b0b |
rp += 3;
|
|
Packit |
736b0b |
} else if (rp[0] == '\\' && rp[1] == '0' &&
|
|
Packit |
736b0b |
rp[2] == '1' && rp[3] == '2') {
|
|
Packit |
736b0b |
/* \012 is a NEWLINE. */
|
|
Packit |
736b0b |
*wp++ = '\n';
|
|
Packit |
736b0b |
rp += 3;
|
|
Packit |
736b0b |
} else if (rp[0] == '\\' && rp[1] == '\\') {
|
|
Packit |
736b0b |
/*
|
|
Packit |
736b0b |
* We have to escape \\ to be able to represent
|
|
Packit |
736b0b |
* all characters.
|
|
Packit |
736b0b |
*/
|
|
Packit |
736b0b |
*wp++ = '\\';
|
|
Packit |
736b0b |
rp += 1;
|
|
Packit |
736b0b |
} else if (rp[0] == '\\' && rp[1] == '1' &&
|
|
Packit |
736b0b |
rp[2] == '3' && rp[3] == '4') {
|
|
Packit |
736b0b |
/* \134 is also \\. */
|
|
Packit |
736b0b |
*wp++ = '\\';
|
|
Packit |
736b0b |
rp += 3;
|
|
Packit |
736b0b |
} else
|
|
Packit |
736b0b |
*wp++ = *rp;
|
|
Packit |
736b0b |
} while (*rp++ != '\0');
|
|
Packit |
736b0b |
|
|
Packit |
736b0b |
return buf;
|
|
Packit |
736b0b |
}
|
|
Packit |
736b0b |
|
|
Packit |
736b0b |
/* From glibc getmntent_r() */
|
|
Packit |
736b0b |
static struct mntent *
|
|
Packit |
736b0b |
local_getmntent_r(FILE *tab, struct mntent *mnt, char *buf, int size)
|
|
Packit |
736b0b |
{
|
|
Packit |
736b0b |
char *cp, *head;
|
|
Packit |
736b0b |
|
|
Packit |
736b0b |
do {
|
|
Packit |
736b0b |
char *end_ptr;
|
|
Packit |
736b0b |
|
|
Packit |
736b0b |
if (fgets(buf, size, tab) == NULL)
|
|
Packit |
736b0b |
return 0;
|
|
Packit |
736b0b |
|
|
Packit |
736b0b |
end_ptr = strchr(buf, '\n');
|
|
Packit |
736b0b |
if (end_ptr != NULL) {
|
|
Packit |
736b0b |
while (end_ptr[-1] == ' ' || end_ptr[-1] == '\t')
|
|
Packit |
736b0b |
end_ptr--;
|
|
Packit |
736b0b |
*end_ptr = '\0';
|
|
Packit |
736b0b |
} else {
|
|
Packit |
736b0b |
/* Whole line was not read. Do it now but forget it. */
|
|
Packit |
736b0b |
char tmp[1024];
|
|
Packit |
736b0b |
while (fgets(tmp, sizeof tmp, tab) != NULL)
|
|
Packit |
736b0b |
if (strchr(tmp, '\n') != NULL)
|
|
Packit |
736b0b |
break;
|
|
Packit |
736b0b |
}
|
|
Packit |
736b0b |
|
|
Packit |
736b0b |
head = buf + strspn(buf, " \t");
|
|
Packit |
736b0b |
/* skip empty lines and comment lines */
|
|
Packit |
736b0b |
} while (head[0] == '\0' || head[0] == '#');
|
|
Packit |
736b0b |
|
|
Packit |
736b0b |
cp = strsep(&head, " \t");
|
|
Packit |
736b0b |
mnt->mnt_fsname = cp != NULL ? local_decode_name(cp) : (char *) "";
|
|
Packit |
736b0b |
if (head)
|
|
Packit |
736b0b |
head += strspn(head, " \t");
|
|
Packit |
736b0b |
cp = strsep(&head, " \t");
|
|
Packit |
736b0b |
mnt->mnt_dir = cp != NULL ? local_decode_name (cp) : (char *) "";
|
|
Packit |
736b0b |
if (head)
|
|
Packit |
736b0b |
head += strspn(head, " \t");
|
|
Packit |
736b0b |
cp = strsep(&head, " \t");
|
|
Packit |
736b0b |
mnt->mnt_type = cp != NULL ? local_decode_name (cp) : (char *) "";
|
|
Packit |
736b0b |
if (head)
|
|
Packit |
736b0b |
head += strspn (head, " \t");
|
|
Packit |
736b0b |
cp = strsep (&head, " \t");
|
|
Packit |
736b0b |
mnt->mnt_opts = cp != NULL ? local_decode_name (cp) : (char *) "";
|
|
Packit |
736b0b |
|
|
Packit |
736b0b |
/* autofs doesn't need freq or passno */
|
|
Packit |
736b0b |
|
|
Packit |
736b0b |
return mnt;
|
|
Packit |
736b0b |
}
|
|
Packit |
736b0b |
|
|
Packit |
350d1f |
int unlink_mount_tree(struct autofs_point *ap, const char *mp)
|
|
Packit |
231b91 |
{
|
|
Packit |
350d1f |
FILE *tab;
|
|
Packit |
350d1f |
struct mntent *mnt;
|
|
Packit |
350d1f |
struct mntent mnt_wrk;
|
|
Packit |
350d1f |
char buf[PATH_MAX * 3];
|
|
Packit |
350d1f |
unsigned int mp_len = strlen(mp);
|
|
Packit |
350d1f |
int rv, ret = 1;
|
|
Packit |
231b91 |
|
|
Packit |
350d1f |
tab = open_fopen_r(_PROC_MOUNTS);
|
|
Packit |
350d1f |
if (!tab) {
|
|
Packit |
350d1f |
char *estr = strerror_r(errno, buf, PATH_MAX - 1);
|
|
Packit |
350d1f |
logerr("fopen: %s", estr);
|
|
Packit |
350d1f |
return 0;
|
|
Packit |
350d1f |
}
|
|
Packit |
350d1f |
|
|
Packit |
350d1f |
while ((mnt = local_getmntent_r(tab, &mnt_wrk, buf, PATH_MAX * 3))) {
|
|
Packit |
350d1f |
unsigned int mnt_dir_len;
|
|
Packit |
350d1f |
int is_autofs;
|
|
Packit |
350d1f |
|
|
Packit |
350d1f |
if (strncmp(mnt->mnt_dir, mp, mp_len))
|
|
Packit |
350d1f |
continue;
|
|
Packit |
350d1f |
|
|
Packit |
350d1f |
mnt_dir_len = strlen(mnt->mnt_dir);
|
|
Packit |
350d1f |
is_autofs = !strcmp(mnt->mnt_type, "autofs");
|
|
Packit |
350d1f |
|
|
Packit |
350d1f |
if (mnt_dir_len == mp_len && !is_autofs) {
|
|
Packit |
350d1f |
ret = 0;
|
|
Packit |
350d1f |
break;
|
|
Packit |
350d1f |
}
|
|
Packit |
350d1f |
|
|
Packit |
350d1f |
if (is_autofs)
|
|
Packit |
350d1f |
rv = umount2(mnt->mnt_dir, MNT_DETACH);
|
|
Packit |
231b91 |
else
|
|
Packit |
350d1f |
rv = spawn_umount(ap->logopt, "-l", mnt->mnt_dir, NULL);
|
|
Packit |
231b91 |
if (rv == -1) {
|
|
Packit |
231b91 |
debug(ap->logopt,
|
|
Packit |
350d1f |
"can't unlink %s from mount tree", mnt->mnt_dir);
|
|
Packit |
231b91 |
|
|
Packit |
231b91 |
switch (errno) {
|
|
Packit |
231b91 |
case EINVAL:
|
|
Packit |
231b91 |
warn(ap->logopt,
|
|
Packit |
231b91 |
"bad superblock or not mounted");
|
|
Packit |
231b91 |
break;
|
|
Packit |
231b91 |
|
|
Packit |
231b91 |
case ENOENT:
|
|
Packit |
231b91 |
case EFAULT:
|
|
Packit |
231b91 |
ret = 0;
|
|
Packit |
231b91 |
warn(ap->logopt, "bad path for mount");
|
|
Packit |
231b91 |
break;
|
|
Packit |
231b91 |
}
|
|
Packit |
231b91 |
}
|
|
Packit |
231b91 |
}
|
|
Packit |
350d1f |
fclose(tab);
|
|
Packit |
231b91 |
|
|
Packit |
231b91 |
return ret;
|
|
Packit |
231b91 |
}
|
|
Packit |
231b91 |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Get list of mounts under path in longest->shortest order
|
|
Packit |
8480eb |
*/
|
|
Packit |
758966 |
struct mnt_list *get_mnt_list(const char *path, int include)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
FILE *tab;
|
|
Packit |
8480eb |
size_t pathlen = strlen(path);
|
|
Packit |
8480eb |
struct mntent mnt_wrk;
|
|
Packit |
8480eb |
char buf[PATH_MAX * 3];
|
|
Packit |
8480eb |
struct mntent *mnt;
|
|
Packit |
8480eb |
struct mnt_list *ent, *mptr, *last;
|
|
Packit |
8480eb |
struct mnt_list *list = NULL;
|
|
Packit |
8480eb |
size_t len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!path || !pathlen || pathlen > PATH_MAX)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
|
|
Packit |
758966 |
tab = open_setmntent_r(_PROC_MOUNTS);
|
|
Packit |
8480eb |
if (!tab) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, PATH_MAX - 1);
|
|
Packit |
8480eb |
logerr("setmntent: %s", estr);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while ((mnt = getmntent_r(tab, &mnt_wrk, buf, PATH_MAX * 3))) {
|
|
Packit |
8480eb |
len = strlen(mnt->mnt_dir);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if ((!include && len <= pathlen) ||
|
|
Packit |
8480eb |
strncmp(mnt->mnt_dir, path, pathlen) != 0)
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
|
|
Packit |
2c5386 |
/* Not a subdirectory of requested mp? */
|
|
Packit |
2c5386 |
/* mp_len == 1 => everything is subdir */
|
|
Packit |
8480eb |
if (pathlen > 1 && len > pathlen &&
|
|
Packit |
8480eb |
mnt->mnt_dir[pathlen] != '/')
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ent = malloc(sizeof(*ent));
|
|
Packit |
8480eb |
if (!ent) {
|
|
Packit |
8480eb |
endmntent(tab);
|
|
Packit |
8480eb |
free_mnt_list(list);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
memset(ent, 0, sizeof(*ent));
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mptr = list;
|
|
Packit |
8480eb |
last = NULL;
|
|
Packit |
8480eb |
while (mptr) {
|
|
Packit |
2c5386 |
if (len >= strlen(mptr->mp))
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
last = mptr;
|
|
Packit |
8480eb |
mptr = mptr->next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (mptr == list)
|
|
Packit |
8480eb |
list = ent;
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
last->next = ent;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ent->next = mptr;
|
|
Packit |
8480eb |
|
|
Packit |
2c5386 |
ent->mp = malloc(len + 1);
|
|
Packit |
2c5386 |
if (!ent->mp) {
|
|
Packit |
8480eb |
endmntent(tab);
|
|
Packit |
8480eb |
free_mnt_list(list);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
2c5386 |
strcpy(ent->mp, mnt->mnt_dir);
|
|
Packit |
8480eb |
|
|
Packit |
817ac7 |
if (!strcmp(mnt->mnt_type, "autofs"))
|
|
Packit |
817ac7 |
ent->flags |= MNTS_AUTOFS;
|
|
Packit |
817ac7 |
|
|
Packit |
817ac7 |
if (ent->flags & MNTS_AUTOFS) {
|
|
Packit |
817ac7 |
if (strstr(mnt->mnt_opts, "indirect"))
|
|
Packit |
817ac7 |
ent->flags |= MNTS_INDIRECT;
|
|
Packit |
817ac7 |
else if (strstr(mnt->mnt_opts, "direct"))
|
|
Packit |
817ac7 |
ent->flags |= MNTS_DIRECT;
|
|
Packit |
817ac7 |
else if (strstr(mnt->mnt_opts, "offset"))
|
|
Packit |
817ac7 |
ent->flags |= MNTS_OFFSET;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
endmntent(tab);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return list;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void free_mnt_list(struct mnt_list *list)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct mnt_list *next;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!list)
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
next = list;
|
|
Packit |
8480eb |
while (next) {
|
|
Packit |
8480eb |
struct mnt_list *this = next;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
next = this->next;
|
|
Packit |
8480eb |
|
|
Packit |
2c5386 |
if (this->mp)
|
|
Packit |
2c5386 |
free(this->mp);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free(this);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
758966 |
static int table_is_mounted(const char *mp, unsigned int type)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct mntent *mnt;
|
|
Packit |
8480eb |
struct mntent mnt_wrk;
|
|
Packit |
8480eb |
char buf[PATH_MAX * 3];
|
|
Packit |
2c5386 |
size_t mp_len = strlen(mp);
|
|
Packit |
8480eb |
FILE *tab;
|
|
Packit |
8480eb |
int ret = 0;
|
|
Packit |
8480eb |
|
|
Packit |
2c5386 |
if (!mp || !mp_len || mp_len >= PATH_MAX)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
6b92cd |
tab = open_fopen_r(_PROC_MOUNTS);
|
|
Packit |
8480eb |
if (!tab) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, PATH_MAX - 1);
|
|
Packit |
6b92cd |
logerr("fopen: %s", estr);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
6b92cd |
while ((mnt = local_getmntent_r(tab, &mnt_wrk, buf, PATH_MAX * 3))) {
|
|
Packit |
8480eb |
size_t len = strlen(mnt->mnt_dir);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (type) {
|
|
Packit |
8480eb |
unsigned int autofs_fs;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
autofs_fs = !strcmp(mnt->mnt_type, "autofs");
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (type & MNTS_REAL)
|
|
Packit |
8480eb |
if (autofs_fs)
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (type & MNTS_AUTOFS)
|
|
Packit |
8480eb |
if (!autofs_fs)
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
2c5386 |
if (mp_len == len && !strncmp(mp, mnt->mnt_dir, mp_len)) {
|
|
Packit |
8480eb |
ret = 1;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
6b92cd |
fclose(tab);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
758966 |
static int ioctl_is_mounted(const char *mp, unsigned int type)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct ioctl_ops *ops = get_ioctl_ops();
|
|
Packit |
8480eb |
unsigned int mounted;
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* If the ioctl fails fall back to the potentially resource
|
|
Packit |
8480eb |
* intensive mount table check.
|
|
Packit |
8480eb |
*/
|
|
Packit |
2c5386 |
ret = ops->ismountpoint(LOGOPT_NONE, -1, mp, &mounted);
|
|
Packit |
8480eb |
if (ret == -1)
|
|
Packit |
758966 |
return table_is_mounted(mp, type);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (mounted) {
|
|
Packit |
8480eb |
switch (type) {
|
|
Packit |
8480eb |
case MNTS_ALL:
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
case MNTS_AUTOFS:
|
|
Packit |
8480eb |
return (mounted & DEV_IOCTL_IS_AUTOFS);
|
|
Packit |
8480eb |
case MNTS_REAL:
|
|
Packit |
8480eb |
return (mounted & DEV_IOCTL_IS_OTHER);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
758966 |
int is_mounted(const char *mp, unsigned int type)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct ioctl_ops *ops = get_ioctl_ops();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ops->ismountpoint)
|
|
Packit |
758966 |
return ioctl_is_mounted(mp, type);
|
|
Packit |
8480eb |
else
|
|
Packit |
758966 |
return table_is_mounted(mp, type);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Since we have to look at the entire mount tree for direct
|
|
Packit |
8480eb |
* mounts (all mounts under "/") and we may have a large number
|
|
Packit |
8480eb |
* of entries to traverse again and again we need to
|
|
Packit |
8480eb |
* use a more efficient method than the routines above.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* Thre tree_... routines allow us to read the mount tree
|
|
Packit |
8480eb |
* once and pass it to subsequent functions for use. Since
|
|
Packit |
8480eb |
* it's a tree structure searching should be a low overhead
|
|
Packit |
8480eb |
* operation.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
void tree_free_mnt_tree(struct mnt_list *tree)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct list_head *head, *p;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!tree)
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tree_free_mnt_tree(tree->left);
|
|
Packit |
8480eb |
tree_free_mnt_tree(tree->right);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
head = &tree->self;
|
|
Packit |
8480eb |
p = head->next;
|
|
Packit |
8480eb |
while (p != head) {
|
|
Packit |
8480eb |
struct mnt_list *this;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
this = list_entry(p, struct mnt_list, self);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
p = p->next;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
list_del(&this->self);
|
|
Packit |
8480eb |
|
|
Packit |
2c5386 |
free(this->mp);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free(this);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
2c5386 |
free(tree->mp);
|
|
Packit |
8480eb |
free(tree);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Make tree of system mounts in /proc/mounts.
|
|
Packit |
8480eb |
*/
|
|
Packit |
758966 |
struct mnt_list *tree_make_mnt_tree(const char *path)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
FILE *tab;
|
|
Packit |
8480eb |
struct mntent mnt_wrk;
|
|
Packit |
8480eb |
char buf[PATH_MAX * 3];
|
|
Packit |
8480eb |
struct mntent *mnt;
|
|
Packit |
8480eb |
struct mnt_list *ent, *mptr;
|
|
Packit |
8480eb |
struct mnt_list *tree = NULL;
|
|
Packit |
8480eb |
size_t plen;
|
|
Packit |
8480eb |
int eq;
|
|
Packit |
8480eb |
|
|
Packit |
758966 |
tab = open_setmntent_r(_PROC_MOUNTS);
|
|
Packit |
8480eb |
if (!tab) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, PATH_MAX - 1);
|
|
Packit |
8480eb |
logerr("setmntent: %s", estr);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
plen = strlen(path);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while ((mnt = getmntent_r(tab, &mnt_wrk, buf, PATH_MAX * 3))) {
|
|
Packit |
8480eb |
size_t len = strlen(mnt->mnt_dir);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Not matching path */
|
|
Packit |
8480eb |
if (strncmp(mnt->mnt_dir, path, plen))
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Not a subdirectory of requested path */
|
|
Packit |
8480eb |
if (plen > 1 && len > plen && mnt->mnt_dir[plen] != '/')
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ent = malloc(sizeof(*ent));
|
|
Packit |
8480eb |
if (!ent) {
|
|
Packit |
8480eb |
endmntent(tab);
|
|
Packit |
8480eb |
tree_free_mnt_tree(tree);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
memset(ent, 0, sizeof(*ent));
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&ent->self);
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&ent->list);
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&ent->entries);
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&ent->sublist);
|
|
Packit |
8480eb |
|
|
Packit |
2c5386 |
ent->mp = malloc(len + 1);
|
|
Packit |
2c5386 |
if (!ent->mp) {
|
|
Packit |
8480eb |
endmntent(tab);
|
|
Packit |
8480eb |
free(ent);
|
|
Packit |
8480eb |
tree_free_mnt_tree(tree);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
2c5386 |
strcpy(ent->mp, mnt->mnt_dir);
|
|
Packit |
8480eb |
|
|
Packit |
817ac7 |
if (!strcmp(mnt->mnt_type, "autofs"))
|
|
Packit |
817ac7 |
ent->flags |= MNTS_AUTOFS;
|
|
Packit |
8480eb |
|
|
Packit |
817ac7 |
if (ent->flags & MNTS_AUTOFS) {
|
|
Packit |
817ac7 |
if (strstr(mnt->mnt_opts, "indirect"))
|
|
Packit |
817ac7 |
ent->flags |= MNTS_INDIRECT;
|
|
Packit |
817ac7 |
else if (strstr(mnt->mnt_opts, "direct"))
|
|
Packit |
817ac7 |
ent->flags |= MNTS_DIRECT;
|
|
Packit |
817ac7 |
else if (strstr(mnt->mnt_opts, "offset"))
|
|
Packit |
817ac7 |
ent->flags |= MNTS_OFFSET;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mptr = tree;
|
|
Packit |
8480eb |
while (mptr) {
|
|
Packit |
2c5386 |
int elen = strlen(ent->mp);
|
|
Packit |
2c5386 |
int mlen = strlen(mptr->mp);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (elen < mlen) {
|
|
Packit |
8480eb |
if (mptr->left) {
|
|
Packit |
8480eb |
mptr = mptr->left;
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
mptr->left = ent;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
} else if (elen > mlen) {
|
|
Packit |
8480eb |
if (mptr->right) {
|
|
Packit |
8480eb |
mptr = mptr->right;
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
mptr->right = ent;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
2c5386 |
eq = strcmp(ent->mp, mptr->mp);
|
|
Packit |
8480eb |
if (eq < 0) {
|
|
Packit |
8480eb |
if (mptr->left)
|
|
Packit |
8480eb |
mptr = mptr->left;
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
mptr->left = ent;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
} else if (eq > 0) {
|
|
Packit |
8480eb |
if (mptr->right)
|
|
Packit |
8480eb |
mptr = mptr->right;
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
mptr->right = ent;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
list_add_tail(&ent->self, &mptr->self);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!tree)
|
|
Packit |
8480eb |
tree = ent;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
endmntent(tab);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return tree;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Get list of mounts under "path" in longest->shortest order
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
int tree_get_mnt_list(struct mnt_list *mnts, struct list_head *list, const char *path, int include)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
size_t mlen, plen;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!mnts)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
plen = strlen(path);
|
|
Packit |
2c5386 |
mlen = strlen(mnts->mp);
|
|
Packit |
8480eb |
if (mlen < plen)
|
|
Packit |
8480eb |
return tree_get_mnt_list(mnts->right, list, path, include);
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
struct list_head *self, *p;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tree_get_mnt_list(mnts->left, list, path, include);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if ((!include && mlen <= plen) ||
|
|
Packit |
2c5386 |
strncmp(mnts->mp, path, plen))
|
|
Packit |
8480eb |
goto skip;
|
|
Packit |
8480eb |
|
|
Packit |
2c5386 |
if (plen > 1 && mlen > plen && mnts->mp[plen] != '/')
|
|
Packit |
8480eb |
goto skip;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&mnts->list);
|
|
Packit |
8480eb |
list_add(&mnts->list, list);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
self = &mnts->self;
|
|
Packit |
8480eb |
list_for_each(p, self) {
|
|
Packit |
8480eb |
struct mnt_list *this;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
this = list_entry(p, struct mnt_list, self);
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&this->list);
|
|
Packit |
8480eb |
list_add(&this->list, list);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
skip:
|
|
Packit |
8480eb |
tree_get_mnt_list(mnts->right, list, path, include);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (list_empty(list))
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Get list of mounts under "path" in longest->shortest order
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
int tree_get_mnt_sublist(struct mnt_list *mnts, struct list_head *list, const char *path, int include)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
size_t mlen, plen;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!mnts)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
plen = strlen(path);
|
|
Packit |
2c5386 |
mlen = strlen(mnts->mp);
|
|
Packit |
8480eb |
if (mlen < plen)
|
|
Packit |
8480eb |
return tree_get_mnt_sublist(mnts->right, list, path, include);
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
struct list_head *self, *p;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tree_get_mnt_sublist(mnts->left, list, path, include);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if ((!include && mlen <= plen) ||
|
|
Packit |
2c5386 |
strncmp(mnts->mp, path, plen))
|
|
Packit |
8480eb |
goto skip;
|
|
Packit |
8480eb |
|
|
Packit |
2c5386 |
if (plen > 1 && mlen > plen && mnts->mp[plen] != '/')
|
|
Packit |
8480eb |
goto skip;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&mnts->sublist);
|
|
Packit |
8480eb |
list_add(&mnts->sublist, list);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
self = &mnts->self;
|
|
Packit |
8480eb |
list_for_each(p, self) {
|
|
Packit |
8480eb |
struct mnt_list *this;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
this = list_entry(p, struct mnt_list, self);
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&this->sublist);
|
|
Packit |
8480eb |
list_add(&this->sublist, list);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
skip:
|
|
Packit |
8480eb |
tree_get_mnt_sublist(mnts->right, list, path, include);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (list_empty(list))
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int tree_find_mnt_ents(struct mnt_list *mnts, struct list_head *list, const char *path)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int mlen, plen;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!mnts)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
plen = strlen(path);
|
|
Packit |
2c5386 |
mlen = strlen(mnts->mp);
|
|
Packit |
8480eb |
if (mlen < plen)
|
|
Packit |
8480eb |
return tree_find_mnt_ents(mnts->right, list, path);
|
|
Packit |
8480eb |
else if (mlen > plen)
|
|
Packit |
8480eb |
return tree_find_mnt_ents(mnts->left, list, path);
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
struct list_head *self, *p;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tree_find_mnt_ents(mnts->left, list, path);
|
|
Packit |
8480eb |
|
|
Packit |
2c5386 |
if (!strcmp(mnts->mp, path)) {
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&mnts->entries);
|
|
Packit |
8480eb |
list_add(&mnts->entries, list);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
self = &mnts->self;
|
|
Packit |
8480eb |
list_for_each(p, self) {
|
|
Packit |
8480eb |
struct mnt_list *this;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
this = list_entry(p, struct mnt_list, self);
|
|
Packit |
8480eb |
|
|
Packit |
2c5386 |
if (!strcmp(this->mp, path)) {
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&this->entries);
|
|
Packit |
8480eb |
list_add(&this->entries, list);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tree_find_mnt_ents(mnts->right, list, path);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!list_empty(list))
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void set_tsd_user_vars(unsigned int logopt, uid_t uid, gid_t gid)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct thread_stdenv_vars *tsv;
|
|
Packit |
8480eb |
struct passwd pw;
|
|
Packit |
8480eb |
struct passwd *ppw = &pw;
|
|
Packit |
8480eb |
struct passwd **pppw = &pp;;
|
|
Packit |
8480eb |
struct group gr;
|
|
Packit |
8480eb |
struct group *pgr;
|
|
Packit |
8480eb |
struct group **ppgr;
|
|
Packit |
8480eb |
char *pw_tmp, *gr_tmp;
|
|
Packit |
8480eb |
int status, tmplen, grplen;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Setup thread specific data values for macro
|
|
Packit |
8480eb |
* substution in map entries during the mount.
|
|
Packit |
8480eb |
* Best effort only as it must go ahead.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tsv = malloc(sizeof(struct thread_stdenv_vars));
|
|
Packit |
8480eb |
if (!tsv) {
|
|
Packit |
8480eb |
error(logopt, "failed alloc tsv storage");
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
memset(tsv, 0, sizeof(struct thread_stdenv_vars));
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tsv->uid = uid;
|
|
Packit |
8480eb |
tsv->gid = gid;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Try to get passwd info */
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tmplen = sysconf(_SC_GETPW_R_SIZE_MAX);
|
|
Packit |
8480eb |
if (tmplen < 0) {
|
|
Packit |
8480eb |
error(logopt, "failed to get buffer size for getpwuid_r");
|
|
Packit |
8480eb |
goto free_tsv;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pw_tmp = malloc(tmplen + 1);
|
|
Packit |
8480eb |
if (!pw_tmp) {
|
|
Packit |
8480eb |
error(logopt, "failed to malloc buffer for getpwuid_r");
|
|
Packit |
8480eb |
goto free_tsv;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = getpwuid_r(uid, ppw, pw_tmp, tmplen, pppw);
|
|
Packit |
8480eb |
if (status || !ppw) {
|
|
Packit |
8480eb |
error(logopt, "failed to get passwd info from getpwuid_r");
|
|
Packit |
8480eb |
free(pw_tmp);
|
|
Packit |
8480eb |
goto free_tsv;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tsv->user = strdup(pw.pw_name);
|
|
Packit |
8480eb |
if (!tsv->user) {
|
|
Packit |
8480eb |
error(logopt, "failed to malloc buffer for user");
|
|
Packit |
8480eb |
free(pw_tmp);
|
|
Packit |
8480eb |
goto free_tsv;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tsv->home = strdup(pw.pw_dir);
|
|
Packit |
8480eb |
if (!tsv->home) {
|
|
Packit |
8480eb |
error(logopt, "failed to malloc buffer for home");
|
|
Packit |
8480eb |
free(pw_tmp);
|
|
Packit |
8480eb |
goto free_tsv_user;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free(pw_tmp);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Try to get group info */
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
grplen = sysconf(_SC_GETGR_R_SIZE_MAX);
|
|
Packit |
8480eb |
if (grplen < 0) {
|
|
Packit |
8480eb |
error(logopt, "failed to get buffer size for getgrgid_r");
|
|
Packit |
8480eb |
goto free_tsv_home;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
gr_tmp = NULL;
|
|
Packit |
8480eb |
status = ERANGE;
|
|
Packit |
8480eb |
#ifdef ENABLE_LIMIT_GETGRGID_SIZE
|
|
Packit |
8480eb |
if (!maxgrpbuf)
|
|
Packit |
8480eb |
maxgrpbuf = detached_thread_stack_size * 0.9;
|
|
Packit |
8480eb |
#endif
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* If getting the group name fails go on without it. It's
|
|
Packit |
8480eb |
* used to set an environment variable for program maps
|
|
Packit |
8480eb |
* which may or may not use it so it isn't critical to
|
|
Packit |
8480eb |
* operation.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tmplen = grplen;
|
|
Packit |
8480eb |
while (1) {
|
|
Packit |
8480eb |
char *tmp = realloc(gr_tmp, tmplen + 1);
|
|
Packit |
8480eb |
if (!tmp) {
|
|
Packit |
8480eb |
error(logopt, "failed to malloc buffer for getgrgid_r");
|
|
Packit |
8480eb |
goto no_group;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
gr_tmp = tmp;
|
|
Packit |
8480eb |
pgr = &gr;
|
|
Packit |
8480eb |
ppgr = &pg;;
|
|
Packit |
8480eb |
status = getgrgid_r(gid, pgr, gr_tmp, tmplen, ppgr);
|
|
Packit |
8480eb |
if (status != ERANGE)
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
tmplen += grplen;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Don't tempt glibc to alloca() larger than is (likely)
|
|
Packit |
8480eb |
* available on the stack if limit-getgrgid-size is enabled.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (!maxgrpbuf || (tmplen < maxgrpbuf))
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Add a message so we know this happened */
|
|
Packit |
8480eb |
debug(logopt, "group buffer allocation would be too large");
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
no_group:
|
|
Packit |
8480eb |
if (status || !pgr)
|
|
Packit |
8480eb |
error(logopt, "failed to get group info from getgrgid_r");
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
tsv->group = strdup(gr.gr_name);
|
|
Packit |
8480eb |
if (!tsv->group)
|
|
Packit |
8480eb |
error(logopt, "failed to malloc buffer for group");
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (gr_tmp)
|
|
Packit |
8480eb |
free(gr_tmp);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_setspecific(key_thread_stdenv_vars, tsv);
|
|
Packit |
8480eb |
if (status) {
|
|
Packit |
8480eb |
error(logopt, "failed to set stdenv thread var");
|
|
Packit |
8480eb |
goto free_tsv_group;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free_tsv_group:
|
|
Packit |
8480eb |
if (tsv->group)
|
|
Packit |
8480eb |
free(tsv->group);
|
|
Packit |
8480eb |
free_tsv_home:
|
|
Packit |
8480eb |
free(tsv->home);
|
|
Packit |
8480eb |
free_tsv_user:
|
|
Packit |
8480eb |
free(tsv->user);
|
|
Packit |
8480eb |
free_tsv:
|
|
Packit |
8480eb |
free(tsv);
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
const char *mount_type_str(const unsigned int type)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
static const char *str_type[] = {
|
|
Packit |
8480eb |
"indirect",
|
|
Packit |
8480eb |
"direct",
|
|
Packit |
8480eb |
"offset"
|
|
Packit |
8480eb |
};
|
|
Packit |
8480eb |
unsigned int pos, i;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
for (pos = 0, i = type; pos < type_count; i >>= 1, pos++)
|
|
Packit |
8480eb |
if (i & 0x1)
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return (pos == type_count ? NULL : str_type[pos]);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void set_exp_timeout(struct autofs_point *ap,
|
|
Packit |
8480eb |
struct map_source *source, time_t timeout)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
ap->exp_timeout = timeout;
|
|
Packit |
8480eb |
if (source)
|
|
Packit |
8480eb |
source->exp_timeout = timeout;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
time_t get_exp_timeout(struct autofs_point *ap, struct map_source *source)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
time_t timeout = ap->exp_timeout;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (source && ap->type == LKP_DIRECT)
|
|
Packit |
8480eb |
timeout = source->exp_timeout;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return timeout;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void notify_mount_result(struct autofs_point *ap,
|
|
Packit |
8480eb |
const char *path, time_t timeout, const char *type)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
if (timeout)
|
|
Packit |
8480eb |
info(ap->logopt,
|
|
Packit |
8480eb |
"mounted %s on %s with timeout %u, freq %u seconds",
|
|
Packit |
8480eb |
type, path, (unsigned int) timeout,
|
|
Packit |
8480eb |
(unsigned int) ap->exp_runfreq);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
info(ap->logopt,
|
|
Packit |
8480eb |
"mounted %s on %s with timeouts disabled",
|
|
Packit |
8480eb |
type, path);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int do_remount_direct(struct autofs_point *ap, int fd, const char *path)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct ioctl_ops *ops = get_ioctl_ops();
|
|
Packit |
8480eb |
int status = REMOUNT_SUCCESS;
|
|
Packit |
8480eb |
uid_t uid;
|
|
Packit |
8480eb |
gid_t gid;
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ops->requester(ap->logopt, fd, path, &uid, &gid;;
|
|
Packit |
8480eb |
if (uid != -1 && gid != -1)
|
|
Packit |
8480eb |
set_tsd_user_vars(ap->logopt, uid, gid);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = lookup_nss_mount(ap, NULL, path, strlen(path));
|
|
Packit |
8480eb |
if (ret)
|
|
Packit |
8480eb |
info(ap->logopt, "re-connected to %s", path);
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
status = REMOUNT_FAIL;
|
|
Packit |
8480eb |
info(ap->logopt, "failed to re-connect %s", path);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return status;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int do_remount_indirect(struct autofs_point *ap, int fd, const char *path)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct ioctl_ops *ops = get_ioctl_ops();
|
|
Packit |
8480eb |
int status = REMOUNT_SUCCESS;
|
|
Packit |
8480eb |
struct dirent **de;
|
|
Packit |
8480eb |
char buf[PATH_MAX + 1];
|
|
Packit |
8480eb |
uid_t uid;
|
|
Packit |
8480eb |
gid_t gid;
|
|
Packit |
8480eb |
unsigned int mounted;
|
|
Packit |
8480eb |
int n, size;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
n = scandir(path, &de, 0, alphasort);
|
|
Packit |
8480eb |
if (n < 0)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
size = sizeof(buf);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (n--) {
|
|
Packit |
8480eb |
int ret, len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (strcmp(de[n]->d_name, ".") == 0 ||
|
|
Packit |
8480eb |
strcmp(de[n]->d_name, "..") == 0) {
|
|
Packit |
8480eb |
free(de[n]);
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = cat_path(buf, size, path, de[n]->d_name);
|
|
Packit |
8480eb |
if (!ret) {
|
|
Packit |
8480eb |
do {
|
|
Packit |
8480eb |
free(de[n]);
|
|
Packit |
8480eb |
} while (n--);
|
|
Packit |
8480eb |
free(de);
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ops->ismountpoint(ap->logopt, -1, buf, &mounted);
|
|
Packit |
8480eb |
if (!mounted) {
|
|
Packit |
8480eb |
struct dirent **de2;
|
|
Packit |
8480eb |
int i, j;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
i = j = scandir(buf, &de2, 0, alphasort);
|
|
Packit |
8480eb |
if (i < 0) {
|
|
Packit |
8480eb |
free(de[n]);
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
while (i--)
|
|
Packit |
8480eb |
free(de2[i]);
|
|
Packit |
8480eb |
free(de2);
|
|
Packit |
8480eb |
if (j <= 2) {
|
|
Packit |
8480eb |
free(de[n]);
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ops->requester(ap->logopt, fd, buf, &uid, &gid;;
|
|
Packit |
8480eb |
if (uid != -1 && gid != -1)
|
|
Packit |
8480eb |
set_tsd_user_vars(ap->logopt, uid, gid);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
len = strlen(de[n]->d_name);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = lookup_nss_mount(ap, NULL, de[n]->d_name, len);
|
|
Packit |
8480eb |
if (ret)
|
|
Packit |
8480eb |
info(ap->logopt, "re-connected to %s", buf);
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
status = REMOUNT_FAIL;
|
|
Packit |
8480eb |
info(ap->logopt, "failed to re-connect %s", buf);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
free(de[n]);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
free(de);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return status;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int remount_active_mount(struct autofs_point *ap,
|
|
Packit |
8480eb |
struct mapent *me, const char *path, dev_t devid,
|
|
Packit |
8480eb |
const unsigned int type, int *ioctlfd)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct ioctl_ops *ops = get_ioctl_ops();
|
|
Packit |
8480eb |
const char *str_type = mount_type_str(type);
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
unsigned int mounted;
|
|
Packit |
8480eb |
time_t timeout;
|
|
Packit |
8480eb |
struct stat st;
|
|
Packit |
8480eb |
int fd;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*ioctlfd = -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Open failed, no mount present */
|
|
Packit |
8480eb |
ops->open(ap->logopt, &fd, devid, path);
|
|
Packit |
8480eb |
if (fd == -1)
|
|
Packit |
8480eb |
return REMOUNT_OPEN_FAIL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!me)
|
|
Packit |
8480eb |
timeout = get_exp_timeout(ap, NULL);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
timeout = get_exp_timeout(ap, me->source);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Re-reading the map, set timeout and return */
|
|
Packit |
8480eb |
if (ap->state == ST_READMAP) {
|
|
Packit |
8480eb |
debug(ap->logopt, "already mounted, update timeout");
|
|
Packit |
8480eb |
ops->timeout(ap->logopt, fd, timeout);
|
|
Packit |
8480eb |
ops->close(ap->logopt, fd);
|
|
Packit |
8480eb |
return REMOUNT_READ_MAP;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(ap->logopt, "trying to re-connect to mount %s", path);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Mounted so set pipefd and timeout etc. */
|
|
Packit |
8480eb |
if (ops->catatonic(ap->logopt, fd) == -1) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
error(ap->logopt, "set catatonic failed: %s", estr);
|
|
Packit |
8480eb |
debug(ap->logopt, "couldn't re-connect to mount %s", path);
|
|
Packit |
8480eb |
ops->close(ap->logopt, fd);
|
|
Packit |
8480eb |
return REMOUNT_OPEN_FAIL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (ops->setpipefd(ap->logopt, fd, ap->kpipefd) == -1) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
error(ap->logopt, "set pipefd failed: %s", estr);
|
|
Packit |
8480eb |
debug(ap->logopt, "couldn't re-connect to mount %s", path);
|
|
Packit |
8480eb |
ops->close(ap->logopt, fd);
|
|
Packit |
8480eb |
return REMOUNT_OPEN_FAIL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
ops->timeout(ap->logopt, fd, timeout);
|
|
Packit |
8480eb |
if (fstat(fd, &st) == -1) {
|
|
Packit |
8480eb |
error(ap->logopt,
|
|
Packit |
8480eb |
"failed to stat %s mount %s", str_type, path);
|
|
Packit |
8480eb |
debug(ap->logopt, "couldn't re-connect to mount %s", path);
|
|
Packit |
8480eb |
ops->close(ap->logopt, fd);
|
|
Packit |
8480eb |
return REMOUNT_STAT_FAIL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (type != t_indirect)
|
|
Packit |
8480eb |
cache_set_ino_index(me->mc, path, st.st_dev, st.st_ino);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
ap->dev = st.st_dev;
|
|
Packit |
8480eb |
notify_mount_result(ap, path, timeout, str_type);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*ioctlfd = fd;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Any mounts on or below? */
|
|
Packit |
8480eb |
if (ops->ismountpoint(ap->logopt, fd, path, &mounted) == -1) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
error(ap->logopt, "ismountpoint %s failed: %s", path, estr);
|
|
Packit |
8480eb |
debug(ap->logopt, "couldn't re-connect to mount %s", path);
|
|
Packit |
8480eb |
ops->close(ap->logopt, fd);
|
|
Packit |
8480eb |
return REMOUNT_FAIL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (!mounted) {
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* If we're an indirect mount we pass back the fd.
|
|
Packit |
8480eb |
* But if were a direct or offset mount with no active
|
|
Packit |
8480eb |
* mount we don't retain an open file descriptor.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (type != t_indirect) {
|
|
Packit |
8480eb |
ops->close(ap->logopt, fd);
|
|
Packit |
8480eb |
*ioctlfd = -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* What can I do if we can't remount the existing
|
|
Packit |
8480eb |
* mount(s) (possibly a partial failure), everything
|
|
Packit |
8480eb |
* following will be broken?
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (type == t_indirect)
|
|
Packit |
8480eb |
do_remount_indirect(ap, fd, path);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
do_remount_direct(ap, fd, path);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(ap->logopt, "re-connected to mount %s", path);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return REMOUNT_SUCCESS;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int try_remount(struct autofs_point *ap, struct mapent *me, unsigned int type)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct ioctl_ops *ops = get_ioctl_ops();
|
|
Packit |
8480eb |
const char *path;
|
|
Packit |
8480eb |
int ret, fd;
|
|
Packit |
8480eb |
dev_t devid;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (type == t_indirect)
|
|
Packit |
8480eb |
path = ap->path;
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
path = me->key;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = ops->mount_device(ap->logopt, path, type, &devid);
|
|
Packit |
8480eb |
if (ret == -1 || ret == 0)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = remount_active_mount(ap, me, path, devid, type, &fd;;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* The directory must exist since we found a device
|
|
Packit |
8480eb |
* number for the mount but we can't know if we created
|
|
Packit |
8480eb |
* it or not. However, if this is an indirect mount with
|
|
Packit |
8480eb |
* the nobrowse option we need to remove the mount point
|
|
Packit |
8480eb |
* directory at umount anyway.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (type == t_indirect) {
|
|
Packit |
8480eb |
if (ap->flags & MOUNT_FLAG_GHOST)
|
|
Packit |
8480eb |
ap->flags &= ~MOUNT_FLAG_DIR_CREATED;
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
ap->flags |= MOUNT_FLAG_DIR_CREATED;
|
|
Packit |
8480eb |
} else
|
|
Packit |
8480eb |
me->flags &= ~MOUNT_FLAG_DIR_CREATED;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Either we opened the mount or we're re-reading the map.
|
|
Packit |
8480eb |
* If we opened the mount and ioctlfd is not -1 we have
|
|
Packit |
8480eb |
* a descriptor for the indirect mount so we need to
|
|
Packit |
8480eb |
* record that in the mount point struct. Otherwise we're
|
|
Packit |
8480eb |
* re-reading the map.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (ret == REMOUNT_READ_MAP)
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
else if (ret == REMOUNT_SUCCESS) {
|
|
Packit |
8480eb |
if (fd != -1) {
|
|
Packit |
8480eb |
if (type == t_indirect)
|
|
Packit |
8480eb |
ap->ioctlfd = fd;
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
me->ioctlfd = fd;
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Indirect mount requires a valid fd */
|
|
Packit |
8480eb |
if (type != t_indirect)
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Since we got the device number above a mount exists so
|
|
Packit |
8480eb |
* any other failure warrants a failure return here.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* When exiting mounts need be set catatonic, regardless of whether they
|
|
Packit |
8480eb |
* are busy on not, to avoid a hang on access once the daemon has gone
|
|
Packit |
8480eb |
* away.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
static int set_mount_catatonic(struct autofs_point *ap, struct mapent *me, int ioctlfd)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct ioctl_ops *ops = get_ioctl_ops();
|
|
Packit |
8480eb |
unsigned int opened = 0;
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
char *path;
|
|
Packit |
8480eb |
int fd = -1;
|
|
Packit |
8480eb |
int error;
|
|
Packit |
8480eb |
dev_t dev;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
path = ap->path;
|
|
Packit |
8480eb |
dev = ap->dev;
|
|
Packit |
8480eb |
if (me && (ap->type == LKP_DIRECT || *me->key == '/')) {
|
|
Packit |
8480eb |
path = me->key;
|
|
Packit |
8480eb |
dev = me->dev;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ioctlfd >= 0)
|
|
Packit |
8480eb |
fd = ioctlfd;
|
|
Packit |
8480eb |
else if (me && me->ioctlfd >= 0)
|
|
Packit |
8480eb |
fd = me->ioctlfd;
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
error = ops->open(ap->logopt, &fd, dev, path);
|
|
Packit |
8480eb |
if (error == -1) {
|
|
Packit |
8480eb |
int err = errno;
|
|
Packit |
8480eb |
char *estr;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (errno == ENOENT)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
error(ap->logopt,
|
|
Packit |
8480eb |
"failed to open ioctlfd for %s, error: %s",
|
|
Packit |
8480eb |
path, estr);
|
|
Packit |
8480eb |
return err;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
opened = 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (fd >= 0) {
|
|
Packit |
8480eb |
error = ops->catatonic(ap->logopt, fd);
|
|
Packit |
8480eb |
if (error == -1) {
|
|
Packit |
8480eb |
int err = errno;
|
|
Packit |
8480eb |
char *estr;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
error(ap->logopt,
|
|
Packit |
8480eb |
"failed to set %s catatonic, error: %s",
|
|
Packit |
8480eb |
path, estr);
|
|
Packit |
8480eb |
if (opened)
|
|
Packit |
8480eb |
ops->close(ap->logopt, fd);
|
|
Packit |
8480eb |
return err;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (opened)
|
|
Packit |
8480eb |
ops->close(ap->logopt, fd);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(ap->logopt, "set %s catatonic", path);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void set_multi_mount_tree_catatonic(struct autofs_point *ap, struct mapent *me)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
if (!list_empty(&me->multi_list)) {
|
|
Packit |
8480eb |
struct list_head *head = &me->multi_list;
|
|
Packit |
8480eb |
struct list_head *p;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
list_for_each(p, head) {
|
|
Packit |
8480eb |
struct mapent *this;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
this = list_entry(p, struct mapent, multi_list);
|
|
Packit |
8480eb |
set_mount_catatonic(ap, this, this->ioctlfd);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void set_indirect_mount_tree_catatonic(struct autofs_point *ap)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct master_mapent *entry = ap->entry;
|
|
Packit |
8480eb |
struct map_source *map;
|
|
Packit |
8480eb |
struct mapent_cache *mc;
|
|
Packit |
8480eb |
struct mapent *me;
|
|
Packit |
8480eb |
|
|
Packit |
758966 |
if (!is_mounted(ap->path, MNTS_AUTOFS))
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
map = entry->maps;
|
|
Packit |
8480eb |
while (map) {
|
|
Packit |
8480eb |
mc = map->mc;
|
|
Packit |
8480eb |
cache_readlock(mc);
|
|
Packit |
8480eb |
me = cache_enumerate(mc, NULL);
|
|
Packit |
8480eb |
while (me) {
|
|
Packit |
8480eb |
/* Skip negative map entries and wildcard entries */
|
|
Packit |
8480eb |
if (!me->mapent)
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!strcmp(me->key, "*"))
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Only need to set offset mounts catatonic */
|
|
Packit |
8480eb |
if (me->multi && me->multi == me)
|
|
Packit |
8480eb |
set_multi_mount_tree_catatonic(ap, me);
|
|
Packit |
8480eb |
next:
|
|
Packit |
8480eb |
me = cache_enumerate(mc, me);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
map = map->next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* By the time this function is called ap->ioctlfd will have
|
|
Packit |
8480eb |
* been closed so don't try and use it.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
set_mount_catatonic(ap, NULL, -1);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void set_direct_mount_tree_catatonic(struct autofs_point *ap, struct mapent *me)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
/* Set offset mounts catatonic for this mapent */
|
|
Packit |
8480eb |
if (me->multi && me->multi == me)
|
|
Packit |
8480eb |
set_multi_mount_tree_catatonic(ap, me);
|
|
Packit |
8480eb |
set_mount_catatonic(ap, me, me->ioctlfd);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int umount_ent(struct autofs_point *ap, const char *path)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int rv;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
rv = spawn_umount(ap->logopt, path, NULL);
|
|
Packit |
8480eb |
/* We are doing a forced shutcwdown down so unlink busy mounts */
|
|
Packit |
8480eb |
if (rv && (ap->state == ST_SHUTDOWN_FORCE || ap->state == ST_SHUTDOWN)) {
|
|
Packit |
8480eb |
if (ap->state == ST_SHUTDOWN_FORCE) {
|
|
Packit |
8480eb |
info(ap->logopt, "forcing umount of %s", path);
|
|
Packit |
8480eb |
rv = spawn_umount(ap->logopt, "-l", path, NULL);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Verify that we actually unmounted the thing. This is a
|
|
Packit |
8480eb |
* belt and suspenders approach to not eating user data.
|
|
Packit |
8480eb |
* We have seen cases where umount succeeds, but there is
|
|
Packit |
8480eb |
* still a file system mounted on the mount point. How
|
|
Packit |
8480eb |
* this happens has not yet been determined, but we want to
|
|
Packit |
8480eb |
* make sure to return failure here, if that is the case,
|
|
Packit |
8480eb |
* so that we do not try to call rmdir_path on the
|
|
Packit |
8480eb |
* directory.
|
|
Packit |
8480eb |
*/
|
|
Packit |
758966 |
if (!rv && is_mounted(path, MNTS_REAL)) {
|
|
Packit |
8480eb |
crit(ap->logopt,
|
|
Packit |
8480eb |
"the umount binary reported that %s was "
|
|
Packit |
8480eb |
"unmounted, but there is still something "
|
|
Packit |
8480eb |
"mounted on this path.", path);
|
|
Packit |
8480eb |
rv = -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return rv;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int umount_amd_ext_mount(struct autofs_point *ap, struct amd_entry *entry)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int rv = 1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->umount) {
|
|
Packit |
8480eb |
char *prog, *str;
|
|
Packit |
8480eb |
char **argv;
|
|
Packit |
8480eb |
int argc = -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
str = strdup(entry->umount);
|
|
Packit |
8480eb |
if (!str)
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
prog = NULL;
|
|
Packit |
8480eb |
argv = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
argc = construct_argv(str, &prog, &argv);
|
|
Packit |
8480eb |
if (argc == -1) {
|
|
Packit |
8480eb |
free(str);
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!ext_mount_remove(&entry->ext_mount, entry->fs)) {
|
|
Packit |
8480eb |
rv =0;
|
|
Packit |
8480eb |
goto out_free;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
rv = spawnv(ap->logopt, prog, (const char * const *) argv);
|
|
Packit |
8480eb |
if (rv == -1 || (WIFEXITED(rv) && WEXITSTATUS(rv)))
|
|
Packit |
8480eb |
error(ap->logopt,
|
|
Packit |
8480eb |
"failed to umount program mount at %s", entry->fs);
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
rv = 0;
|
|
Packit |
8480eb |
debug(ap->logopt,
|
|
Packit |
8480eb |
"umounted program mount at %s", entry->fs);
|
|
Packit |
8480eb |
rmdir_path(ap, entry->fs, ap->dev);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
out_free:
|
|
Packit |
8480eb |
free_argv(argc, (const char **) argv);
|
|
Packit |
8480eb |
free(str);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ext_mount_remove(&entry->ext_mount, entry->fs)) {
|
|
Packit |
8480eb |
rv = umount_ent(ap, entry->fs);
|
|
Packit |
8480eb |
if (rv)
|
|
Packit |
8480eb |
error(ap->logopt,
|
|
Packit |
8480eb |
"failed to umount external mount %s", entry->fs);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
debug(ap->logopt,
|
|
Packit |
8480eb |
"umounted external mount %s", entry->fs);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
out:
|
|
Packit |
8480eb |
return rv;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int do_mount_autofs_offset(struct autofs_point *ap,
|
|
Packit |
8480eb |
struct mapent *oe, const char *root,
|
|
Packit |
8480eb |
char *offset)
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int mounted = 0;
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(ap->logopt, "mount offset %s at %s", oe->key, root);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = mount_autofs_offset(ap, oe, root, offset);
|
|
Packit |
8480eb |
if (ret >= MOUNT_OFFSET_OK)
|
|
Packit |
8480eb |
mounted++;
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
if (ret != MOUNT_OFFSET_IGNORE)
|
|
Packit |
8480eb |
warn(ap->logopt, "failed to mount offset");
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
debug(ap->logopt, "ignoring \"nohide\" trigger %s",
|
|
Packit |
8480eb |
oe->key);
|
|
Packit |
8480eb |
free(oe->mapent);
|
|
Packit |
8480eb |
oe->mapent = NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return mounted;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int mount_multi_triggers(struct autofs_point *ap, struct mapent *me,
|
|
Packit |
8480eb |
const char *root, unsigned int start, const char *base)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char path[PATH_MAX + 1];
|
|
Packit |
8480eb |
char *offset = path;
|
|
Packit |
8480eb |
struct mapent *oe;
|
|
Packit |
8480eb |
struct list_head *pos = NULL;
|
|
Packit |
8480eb |
unsigned int fs_path_len;
|
|
Packit |
8480eb |
int mounted;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
fs_path_len = start + strlen(base);
|
|
Packit |
8480eb |
if (fs_path_len > PATH_MAX)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mounted = 0;
|
|
Packit |
8480eb |
offset = cache_get_offset(base, offset, start, &me->multi_list, &pos;;
|
|
Packit |
8480eb |
while (offset) {
|
|
Packit |
8480eb |
int plen = fs_path_len + strlen(offset);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (plen > PATH_MAX) {
|
|
Packit |
8480eb |
warn(ap->logopt, "path loo long");
|
|
Packit |
8480eb |
goto cont;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
oe = cache_lookup_offset(base, offset, start, &me->multi_list);
|
|
Packit |
8480eb |
if (!oe || !oe->mapent)
|
|
Packit |
8480eb |
goto cont;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mounted += do_mount_autofs_offset(ap, oe, root, offset);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* If re-constructing a multi-mount it's necessary to walk
|
|
Packit |
8480eb |
* into nested mounts, unlike the usual "mount only what's
|
|
Packit |
8480eb |
* needed as you go" behavior.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (ap->state == ST_READMAP && ap->flags & MOUNT_FLAG_REMOUNT) {
|
|
Packit |
8480eb |
if (oe->ioctlfd != -1 ||
|
|
Packit |
758966 |
is_mounted(oe->key, MNTS_REAL)) {
|
|
Packit |
8480eb |
char oe_root[PATH_MAX + 1];
|
|
Packit |
8480eb |
strcpy(oe_root, root);
|
|
Packit |
8480eb |
strcat(oe_root, offset);
|
|
Packit |
8480eb |
mount_multi_triggers(ap, oe, oe_root, strlen(oe_root), base);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
cont:
|
|
Packit |
8480eb |
offset = cache_get_offset(base,
|
|
Packit |
8480eb |
offset, start, &me->multi_list, &pos;;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return mounted;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int rmdir_path_offset(struct autofs_point *ap, struct mapent *oe)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *dir, *path;
|
|
Packit |
8480eb |
unsigned int split;
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ap->type == LKP_DIRECT)
|
|
Packit |
8480eb |
return rmdir_path(ap, oe->key, oe->multi->dev);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
dir = strdup(oe->key);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ap->flags & MOUNT_FLAG_GHOST)
|
|
Packit |
8480eb |
split = strlen(ap->path) + strlen(oe->multi->key) + 1;
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
split = strlen(ap->path);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
dir[split] = '\0';
|
|
Packit |
8480eb |
path = &dir[split + 1];
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (chdir(dir) == -1) {
|
|
Packit |
8480eb |
error(ap->logopt, "failed to chdir to %s", dir);
|
|
Packit |
8480eb |
free(dir);
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = rmdir_path(ap, path, ap->dev);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free(dir);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (chdir("/") == -1)
|
|
Packit |
8480eb |
error(ap->logopt, "failed to chdir to /");
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int umount_multi_triggers(struct autofs_point *ap, struct mapent *me, char *root, const char *base)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char path[PATH_MAX + 1];
|
|
Packit |
8480eb |
char *offset;
|
|
Packit |
8480eb |
struct mapent *oe;
|
|
Packit |
8480eb |
struct list_head *mm_root, *pos;
|
|
Packit |
8480eb |
const char o_root[] = "/";
|
|
Packit |
8480eb |
const char *mm_base;
|
|
Packit |
8480eb |
int left, start;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
left = 0;
|
|
Packit |
8480eb |
start = strlen(root);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mm_root = &me->multi->multi_list;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!base)
|
|
Packit |
8480eb |
mm_base = o_root;
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
mm_base = base;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pos = NULL;
|
|
Packit |
8480eb |
offset = path;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
|
|
Packit |
8480eb |
char *oe_base;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list);
|
|
Packit |
8480eb |
/* root offset is a special case */
|
|
Packit |
8480eb |
if (!oe || (strlen(oe->key) - start) == 1)
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Check for and umount subtree offsets resulting from
|
|
Packit |
8480eb |
* nonstrict mount fail.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
oe_base = oe->key + strlen(root);
|
|
Packit |
8480eb |
left += umount_multi_triggers(ap, oe, root, oe_base);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (oe->ioctlfd != -1 ||
|
|
Packit |
758966 |
is_mounted(oe->key, MNTS_REAL)) {
|
|
Packit |
8480eb |
left++;
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(ap->logopt, "umount offset %s", oe->key);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (umount_autofs_offset(ap, oe)) {
|
|
Packit |
8480eb |
warn(ap->logopt, "failed to umount offset");
|
|
Packit |
8480eb |
left++;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
struct stat st;
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!(oe->flags & MOUNT_FLAG_DIR_CREATED))
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* An error due to partial directory removal is
|
|
Packit |
8480eb |
* ok so only try and remount the offset if the
|
|
Packit |
8480eb |
* actual mount point still exists.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
ret = rmdir_path_offset(ap, oe);
|
|
Packit |
8480eb |
if (ret == -1 && !stat(oe->key, &st)) {
|
|
Packit |
8480eb |
ret = do_mount_autofs_offset(ap, oe, root, offset);
|
|
Packit |
8480eb |
if (ret)
|
|
Packit |
8480eb |
left++;
|
|
Packit |
8480eb |
/* But we did origianlly create this */
|
|
Packit |
8480eb |
oe->flags |= MOUNT_FLAG_DIR_CREATED;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!left && me->multi == me) {
|
|
Packit |
8480eb |
struct mapent_cache *mc = me->mc;
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Special case.
|
|
Packit |
8480eb |
* If we can't umount the root container then we can't
|
|
Packit |
8480eb |
* delete the offsets from the cache and we need to put
|
|
Packit |
8480eb |
* the offset triggers back.
|
|
Packit |
8480eb |
*/
|
|
Packit |
758966 |
if (is_mounted(root, MNTS_REAL)) {
|
|
Packit |
8480eb |
info(ap->logopt, "unmounting dir = %s", root);
|
|
Packit |
8480eb |
if (umount_ent(ap, root) &&
|
|
Packit |
758966 |
is_mounted(root, MNTS_REAL)) {
|
|
Packit |
8480eb |
if (mount_multi_triggers(ap, me, root, strlen(root), "/") < 0)
|
|
Packit |
8480eb |
warn(ap->logopt,
|
|
Packit |
8480eb |
"failed to remount offset triggers");
|
|
Packit |
8480eb |
return ++left;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* We're done - clean out the offsets */
|
|
Packit |
8480eb |
status = cache_delete_offset_list(mc, me->key);
|
|
Packit |
8480eb |
if (status != CHE_OK)
|
|
Packit |
8480eb |
warn(ap->logopt, "couldn't delete offset list");
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return left;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int clean_stale_multi_triggers(struct autofs_point *ap,
|
|
Packit |
8480eb |
struct mapent *me, char *top, const char *base)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *root;
|
|
Packit |
8480eb |
char mm_top[PATH_MAX + 1];
|
|
Packit |
8480eb |
char path[PATH_MAX + 1];
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
char *offset;
|
|
Packit |
8480eb |
struct mapent *oe;
|
|
Packit |
8480eb |
struct list_head *mm_root, *pos;
|
|
Packit |
8480eb |
const char o_root[] = "/";
|
|
Packit |
8480eb |
const char *mm_base;
|
|
Packit |
8480eb |
int left, start;
|
|
Packit |
8480eb |
time_t age;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (top)
|
|
Packit |
8480eb |
root = top;
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
if (!strchr(me->multi->key, '/'))
|
|
Packit |
8480eb |
/* Indirect multi-mount root */
|
|
Packit |
8480eb |
/* sprintf okay - if it's mounted, it's
|
|
Packit |
8480eb |
* PATH_MAX or less bytes */
|
|
Packit |
8480eb |
sprintf(mm_top, "%s/%s", ap->path, me->multi->key);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
strcpy(mm_top, me->multi->key);
|
|
Packit |
8480eb |
root = mm_top;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
left = 0;
|
|
Packit |
8480eb |
start = strlen(root);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mm_root = &me->multi->multi_list;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!base)
|
|
Packit |
8480eb |
mm_base = o_root;
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
mm_base = base;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pos = NULL;
|
|
Packit |
8480eb |
offset = path;
|
|
Packit |
8480eb |
age = me->multi->age;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
|
|
Packit |
8480eb |
char *oe_base;
|
|
Packit |
8480eb |
char *key;
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list);
|
|
Packit |
8480eb |
/* root offset is a special case */
|
|
Packit |
8480eb |
if (!oe || (strlen(oe->key) - start) == 1)
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Check for and umount stale subtree offsets */
|
|
Packit |
8480eb |
oe_base = oe->key + strlen(root);
|
|
Packit |
8480eb |
ret = clean_stale_multi_triggers(ap, oe, root, oe_base);
|
|
Packit |
8480eb |
left += ret;
|
|
Packit |
8480eb |
if (ret)
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (oe->age == age)
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* If an offset that has an active mount has been removed
|
|
Packit |
8480eb |
* from the multi-mount we don't want to attempt to trigger
|
|
Packit |
8480eb |
* mounts for it. Obviously this is because it has been
|
|
Packit |
8480eb |
* removed, but less obvious is the potential strange
|
|
Packit |
8480eb |
* behaviour that can result if we do try and mount it
|
|
Packit |
8480eb |
* again after it's been expired. For example, if an NFS
|
|
Packit |
8480eb |
* file system is no longer exported and is later umounted
|
|
Packit |
8480eb |
* it can be mounted again without any error message but
|
|
Packit |
8480eb |
* shows as an empty directory. That's going to confuse
|
|
Packit |
8480eb |
* people for sure.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* If the mount cannot be umounted (the process is now
|
|
Packit |
8480eb |
* using a stale mount) the offset needs to be invalidated
|
|
Packit |
8480eb |
* so no further mounts will be attempted but the offset
|
|
Packit |
8480eb |
* cache entry must remain so expires can continue to
|
|
Packit |
8480eb |
* attempt to umount it. If the mount can be umounted and
|
|
Packit |
8480eb |
* the offset is removed, at least for NFS we will get
|
|
Packit |
8480eb |
* ESTALE errors when attempting list the directory.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (oe->ioctlfd != -1 ||
|
|
Packit |
758966 |
is_mounted(oe->key, MNTS_REAL)) {
|
|
Packit |
8480eb |
if (umount_ent(ap, oe->key) &&
|
|
Packit |
758966 |
is_mounted(oe->key, MNTS_REAL)) {
|
|
Packit |
8480eb |
debug(ap->logopt,
|
|
Packit |
8480eb |
"offset %s has active mount, invalidate",
|
|
Packit |
8480eb |
oe->key);
|
|
Packit |
8480eb |
if (oe->mapent) {
|
|
Packit |
8480eb |
free(oe->mapent);
|
|
Packit |
8480eb |
oe->mapent = NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
left++;
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
key = strdup(oe->key);
|
|
Packit |
8480eb |
if (!key) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
error(ap->logopt, "malloc: %s", estr);
|
|
Packit |
8480eb |
left++;
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(ap->logopt, "umount offset %s", oe->key);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (umount_autofs_offset(ap, oe)) {
|
|
Packit |
8480eb |
warn(ap->logopt, "failed to umount offset %s", key);
|
|
Packit |
8480eb |
left++;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
struct stat st;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Mount point not ours to delete ? */
|
|
Packit |
8480eb |
if (!(oe->flags & MOUNT_FLAG_DIR_CREATED)) {
|
|
Packit |
8480eb |
debug(ap->logopt, "delete offset key %s", key);
|
|
Packit |
8480eb |
if (cache_delete_offset(oe->mc, key) == CHE_FAIL)
|
|
Packit |
8480eb |
error(ap->logopt,
|
|
Packit |
8480eb |
"failed to delete offset key %s", key);
|
|
Packit |
8480eb |
free(key);
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* An error due to partial directory removal is
|
|
Packit |
8480eb |
* ok so only try and remount the offset if the
|
|
Packit |
8480eb |
* actual mount point still exists.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
ret = rmdir_path_offset(ap, oe);
|
|
Packit |
8480eb |
if (ret == -1 && !stat(oe->key, &st)) {
|
|
Packit |
8480eb |
ret = do_mount_autofs_offset(ap, oe, root, offset);
|
|
Packit |
8480eb |
if (ret) {
|
|
Packit |
8480eb |
left++;
|
|
Packit |
8480eb |
/* But we did origianlly create this */
|
|
Packit |
8480eb |
oe->flags |= MOUNT_FLAG_DIR_CREATED;
|
|
Packit |
8480eb |
free(key);
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Fall through if the trigger can't be mounted
|
|
Packit |
8480eb |
* again, since there is no offset there can't
|
|
Packit |
8480eb |
* be any mount requests so remove the map
|
|
Packit |
8480eb |
* entry from the cache. There's now a dead
|
|
Packit |
8480eb |
* offset mount, but what else can we do ....
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(ap->logopt, "delete offset key %s", key);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (cache_delete_offset(oe->mc, key) == CHE_FAIL)
|
|
Packit |
8480eb |
error(ap->logopt,
|
|
Packit |
8480eb |
"failed to delete offset key %s", key);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
free(key);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return left;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|