|
Packit |
8480eb |
/* ----------------------------------------------------------------------- *
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* automount.c - Linux automounter daemon
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* Copyright 1997 Transmeta Corporation - All Rights Reserved
|
|
Packit |
8480eb |
* Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org>
|
|
Packit |
8480eb |
* Copyright 2001-2005 Ian Kent <raven@themaw.net>
|
|
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.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
8480eb |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
8480eb |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
8480eb |
* GNU General Public License for more details.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* ----------------------------------------------------------------------- */
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#include <dirent.h>
|
|
Packit |
8480eb |
#include <getopt.h>
|
|
Packit |
8480eb |
#include <signal.h>
|
|
Packit |
8480eb |
#include <stdio.h>
|
|
Packit |
8480eb |
#include <stdlib.h>
|
|
Packit |
8480eb |
#include <string.h>
|
|
Packit |
8480eb |
#include <sys/ioctl.h>
|
|
Packit |
8480eb |
#include <ctype.h>
|
|
Packit |
8480eb |
#include <sys/types.h>
|
|
Packit |
8480eb |
#include <sys/wait.h>
|
|
Packit |
8480eb |
#include <sys/stat.h>
|
|
Packit |
8480eb |
#include <sys/time.h>
|
|
Packit |
8480eb |
#include <sys/resource.h>
|
|
Packit |
8480eb |
#include <sys/poll.h>
|
|
Packit |
8480eb |
#include <dirent.h>
|
|
Packit |
8480eb |
#include <sys/vfs.h>
|
|
Packit |
8480eb |
#include <sys/utsname.h>
|
|
Packit Service |
b3e495 |
#ifdef WITH_SYSTEMD
|
|
Packit Service |
b3e495 |
#include <systemd/sd-daemon.h>
|
|
Packit Service |
b3e495 |
#endif
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#include "automount.h"
|
|
Packit |
8480eb |
#if defined(LIBXML2_WORKAROUND) || defined(TIRPC_WORKAROUND)
|
|
Packit |
8480eb |
#include <dlfcn.h>
|
|
Packit |
8480eb |
#ifdef WITH_LDAP
|
|
Packit |
8480eb |
#include <libxml/parser.h>
|
|
Packit |
8480eb |
#endif
|
|
Packit |
8480eb |
#endif
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
const char *program; /* Initialized with argv[0] */
|
|
Packit |
8480eb |
const char *version = VERSION_STRING; /* Program version */
|
|
Packit |
8480eb |
const char *libdir = AUTOFS_LIB_DIR; /* Location of library modules */
|
|
Packit |
8480eb |
const char *mapdir = AUTOFS_MAP_DIR; /* Location of mount maps */
|
|
Packit |
8480eb |
const char *confdir = AUTOFS_CONF_DIR; /* Location of autofs config file */
|
|
Packit |
8480eb |
|
|
Packit Service |
a565d0 |
unsigned int mp_mode = 0755;
|
|
Packit Service |
a565d0 |
|
|
Packit |
8480eb |
unsigned int nfs_mount_uses_string_options = 0;
|
|
Packit |
8480eb |
static struct nfs_mount_vers vers, check = {1, 1, 1};
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* autofs fifo name prefix */
|
|
Packit Service |
42268b |
const char *fifodir = AUTOFS_FIFO_DIR "/autofs.fifo";
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
const char *global_options; /* Global option, from command line */
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static char *pid_file = NULL; /* File in which to keep pid */
|
|
Packit |
8480eb |
unsigned int global_selection_options;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
long global_negative_timeout = -1;
|
|
Packit |
8480eb |
int do_force_unlink = 0; /* Forceably unlink mount tree at startup */
|
|
Packit |
8480eb |
|
|
Packit Service |
b3e495 |
static int start_pipefd[2] = {-1, -1};
|
|
Packit |
8480eb |
static int st_stat = 1;
|
|
Packit |
8480eb |
static int *pst_stat = &st_stat;
|
|
Packit |
8480eb |
static pthread_t state_mach_thid;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static sigset_t block_sigs;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Pre-calculated kernel packet length */
|
|
Packit |
8480eb |
static size_t kpkt_len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Attributes for creating detached and joinable threads */
|
|
Packit |
8480eb |
pthread_attr_t th_attr;
|
|
Packit |
8480eb |
pthread_attr_t th_attr_detached;
|
|
Packit |
8480eb |
size_t detached_thread_stack_size = PTHREAD_STACK_MIN * 144;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct master_readmap_cond mrc = {
|
|
Packit |
8480eb |
PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, NULL, 0, 0, 0, 0};
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct startup_cond suc = {
|
|
Packit |
8480eb |
PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0};
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_key_t key_thread_stdenv_vars;
|
|
Packit |
8480eb |
pthread_key_t key_thread_attempt_id = (pthread_key_t) 0L;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#define MAX_OPEN_FILES 10240
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int aquire_flag_file(void);
|
|
Packit |
8480eb |
void release_flag_file(void);
|
|
Packit |
8480eb |
static int umount_all(struct autofs_point *ap, int force);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
extern struct master *master_list;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* simple string hash based on public domain sdbm library */
|
|
Packit |
8480eb |
static unsigned long sdbm_hash(const char *str, unsigned long seed)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
unsigned long hash = seed;
|
|
Packit |
8480eb |
char c;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while ((c = *str++))
|
|
Packit |
8480eb |
hash = c + (hash << 6) + (hash << 16) - hash;
|
|
Packit |
8480eb |
return hash;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void set_thread_mount_request_log_id(struct pending_args *mt)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char attempt_id_comp[20];
|
|
Packit |
8480eb |
unsigned long *attempt_id;
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!defaults_get_use_mount_request_log_id())
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
attempt_id = pthread_getspecific(key_thread_attempt_id);
|
|
Packit |
8480eb |
if (attempt_id == NULL) {
|
|
Packit |
8480eb |
attempt_id = (unsigned long *) calloc(1, sizeof(unsigned long));
|
|
Packit |
8480eb |
if (attempt_id == NULL)
|
|
Packit |
8480eb |
fatal(ENOMEM);
|
|
Packit |
8480eb |
snprintf(attempt_id_comp, 20, "%ld", mt->wait_queue_token);
|
|
Packit |
8480eb |
*attempt_id = sdbm_hash(attempt_id_comp, 0);
|
|
Packit |
8480eb |
snprintf(attempt_id_comp, 20, "%u", mt->pid);
|
|
Packit |
8480eb |
*attempt_id = sdbm_hash(attempt_id_comp, *attempt_id);
|
|
Packit |
8480eb |
*attempt_id = sdbm_hash(mt->name, *attempt_id);
|
|
Packit |
8480eb |
status = pthread_setspecific(key_thread_attempt_id, attempt_id);
|
|
Packit |
8480eb |
if (status != 0)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int is_remote_fstype(unsigned int fs_type)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int ret = 0;
|
|
Packit |
8480eb |
switch (fs_type) {
|
|
Packit |
8480eb |
case SMB_SUPER_MAGIC:
|
|
Packit |
8480eb |
case CIFS_MAGIC_NUMBER:
|
|
Packit |
8480eb |
case NCP_SUPER_MAGIC:
|
|
Packit |
8480eb |
case NFS_SUPER_MAGIC:
|
|
Packit |
8480eb |
ret = 1;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
};
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int do_mkdir(const char *parent, const char *path, mode_t mode)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
mode_t mask;
|
|
Packit |
8480eb |
struct stat st, root;
|
|
Packit |
8480eb |
struct statfs fs;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* If path exists we're done */
|
|
Packit |
8480eb |
status = stat(path, &st);
|
|
Packit |
8480eb |
if (status == 0) {
|
|
Packit |
8480eb |
errno = EEXIST;
|
|
Packit |
8480eb |
if (!S_ISDIR(st.st_mode))
|
|
Packit |
8480eb |
errno = ENOTDIR;
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* We don't want to create the path on a remote file system
|
|
Packit |
8480eb |
* unless it's the root file system.
|
|
Packit |
8480eb |
* An empty parent means it's the root directory and always ok.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (*parent) {
|
|
Packit |
8480eb |
status = statfs(parent, &fs);
|
|
Packit |
8480eb |
if (status == -1)
|
|
Packit |
8480eb |
goto fail;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (is_remote_fstype(fs.f_type)) {
|
|
Packit |
8480eb |
status = stat(parent, &st);
|
|
Packit |
8480eb |
if (status == -1)
|
|
Packit |
8480eb |
goto fail;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = stat("/", &root);
|
|
Packit |
8480eb |
if (status == -1)
|
|
Packit |
8480eb |
goto fail;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (st.st_dev != root.st_dev)
|
|
Packit |
8480eb |
goto fail;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mask = umask(0022);
|
|
Packit |
8480eb |
status = mkdir(path, mode);
|
|
Packit |
8480eb |
(void) umask(mask);
|
|
Packit |
8480eb |
if (status == -1)
|
|
Packit |
8480eb |
goto fail;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
fail:
|
|
Packit |
8480eb |
errno = EACCES;
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int mkdir_path(const char *path, mode_t mode)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char buf[PATH_MAX];
|
|
Packit |
8480eb |
char parent[PATH_MAX];
|
|
Packit |
8480eb |
const char *cp = path, *lcp = path;
|
|
Packit |
8480eb |
char *bp = buf, *pp = parent;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*parent = '\0';
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
do {
|
|
Packit |
8480eb |
if (cp != path && (*cp == '/' || *cp == '\0')) {
|
|
Packit |
8480eb |
memcpy(bp, lcp, cp - lcp);
|
|
Packit |
8480eb |
bp += cp - lcp;
|
|
Packit |
8480eb |
*bp = '\0';
|
|
Packit |
8480eb |
if (!do_mkdir(parent, buf, mode)) {
|
|
Packit |
8480eb |
if (*cp != '\0') {
|
|
Packit |
8480eb |
memcpy(pp, lcp, cp - lcp);
|
|
Packit |
8480eb |
pp += cp - lcp;
|
|
Packit |
8480eb |
*pp = '\0';
|
|
Packit |
8480eb |
lcp = cp;
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
memcpy(pp, lcp, cp - lcp);
|
|
Packit |
8480eb |
pp += cp - lcp;
|
|
Packit |
8480eb |
*pp = '\0';
|
|
Packit |
8480eb |
lcp = cp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
} while (*cp++ != '\0');
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Remove as much as possible of a path */
|
|
Packit |
8480eb |
int rmdir_path(struct autofs_point *ap, const char *path, dev_t dev)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int len = strlen(path);
|
|
Packit |
8480eb |
char buf[PATH_MAX];
|
|
Packit |
8480eb |
char *cp;
|
|
Packit |
8480eb |
int first = 1;
|
|
Packit |
8480eb |
struct stat st;
|
|
Packit |
8480eb |
struct statfs fs;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
strcpy(buf, path);
|
|
Packit |
8480eb |
cp = buf + len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
do {
|
|
Packit |
8480eb |
*cp = '\0';
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Before removing anything, perform some sanity checks to
|
|
Packit |
8480eb |
* ensure that we are looking at files in the automount
|
|
Packit |
8480eb |
* file system.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
memset(&st, 0, sizeof(st));
|
|
Packit |
8480eb |
if (lstat(buf, &st) != 0) {
|
|
Packit |
8480eb |
crit(ap->logopt, "lstat of %s failed", buf);
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Termination condition removing full path within autofs fs */
|
|
Packit |
8480eb |
if (st.st_dev != dev)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (statfs(buf, &fs) != 0) {
|
|
Packit |
8480eb |
error(ap->logopt, "could not stat fs of %s", buf);
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (fs.f_type != (__SWORD_TYPE) AUTOFS_SUPER_MAGIC) {
|
|
Packit |
8480eb |
crit(ap->logopt, "attempt to remove directory from a "
|
|
Packit |
8480eb |
"non-autofs filesystem!");
|
|
Packit |
8480eb |
crit(ap->logopt,
|
|
Packit |
8480eb |
"requester dev == %llu, \"%s\" owner dev == %llu",
|
|
Packit |
8480eb |
dev, buf, st.st_dev);
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Last element of path may be a symbolic link; all others
|
|
Packit |
8480eb |
* are directories (and the last directory element is
|
|
Packit |
8480eb |
* processed first, hence the variable name)
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (rmdir(buf) == -1) {
|
|
Packit |
8480eb |
if (first && errno == ENOTDIR) {
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Ensure that we will only remove
|
|
Packit |
8480eb |
* symbolic links.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (S_ISLNK(st.st_mode)) {
|
|
Packit |
8480eb |
if (unlink(buf) == -1)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
crit(ap->logopt,
|
|
Packit |
8480eb |
"file \"%s\" is neither a directory"
|
|
Packit |
8480eb |
" nor a symbolic link. mode %d",
|
|
Packit |
8480eb |
buf, st.st_mode);
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* If we fail to remove a directory for any reason,
|
|
Packit |
8480eb |
* we need to return an error.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
first = 0;
|
|
Packit |
8480eb |
} while ((cp = strrchr(buf, '/')) != NULL && cp != buf);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Like ftw, except fn gets called twice: before a directory is
|
|
Packit |
8480eb |
entered, and after. If the before call returns 0, the directory
|
|
Packit |
8480eb |
isn't entered. */
|
|
Packit |
8480eb |
static int walk_tree(const char *base, int (*fn) (struct autofs_point *ap,
|
|
Packit |
8480eb |
const char *file,
|
|
Packit |
8480eb |
const struct stat * st,
|
|
Packit |
8480eb |
int, void *), int incl,
|
|
Packit |
8480eb |
struct autofs_point *ap,
|
|
Packit |
8480eb |
void *arg)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char buf[PATH_MAX + 1];
|
|
Packit |
8480eb |
struct stat st, *pst = &st;
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
|
|
Packit Service |
42268b |
if (!is_mounted(_PATH_MOUNTED, base, MNTS_REAL))
|
|
Packit |
8480eb |
ret = lstat(base, pst);
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
pst = NULL;
|
|
Packit |
8480eb |
ret = 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ret != -1 && (fn) (ap, base, pst, 0, arg)) {
|
|
Packit |
8480eb |
if (S_ISDIR(st.st_mode)) {
|
|
Packit |
8480eb |
struct dirent **de;
|
|
Packit |
8480eb |
int n;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
n = scandir(base, &de, 0, alphasort);
|
|
Packit |
8480eb |
if (n < 0)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (n--) {
|
|
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 |
if (!cat_path(buf, sizeof(buf), base, de[n]->d_name)) {
|
|
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 |
walk_tree(buf, fn, 1, ap, arg);
|
|
Packit |
8480eb |
free(de[n]);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
free(de);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (incl)
|
|
Packit |
8480eb |
(fn) (ap, base, pst, 1, arg);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int rm_unwanted_fn(struct autofs_point *ap,
|
|
Packit |
8480eb |
const char *file, const struct stat *st,
|
|
Packit |
8480eb |
int when, void *arg)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
dev_t dev = *(dev_t *) arg;
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
struct stat newst;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!st)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (when == 0) {
|
|
Packit |
8480eb |
if (st->st_dev != dev)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (lstat(file, &newst)) {
|
|
Packit |
8480eb |
crit(ap->logopt,
|
|
Packit |
8480eb |
"unable to stat file, possible race condition");
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (newst.st_dev != dev) {
|
|
Packit |
8480eb |
crit(ap->logopt,
|
|
Packit |
8480eb |
"file %s has the wrong device, possible race condition",
|
|
Packit |
8480eb |
file);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (S_ISDIR(newst.st_mode)) {
|
|
Packit |
8480eb |
debug(ap->logopt, "removing directory %s", file);
|
|
Packit |
8480eb |
if (rmdir(file)) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
warn(ap->logopt,
|
|
Packit |
8480eb |
"unable to remove directory %s: %s", file, estr);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
} else if (S_ISREG(newst.st_mode)) {
|
|
Packit |
8480eb |
crit(ap->logopt, "attempting to remove files from a mounted "
|
|
Packit |
8480eb |
"directory. file %s", file);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
} else if (S_ISLNK(newst.st_mode)) {
|
|
Packit |
8480eb |
debug(ap->logopt, "removing symlink %s", file);
|
|
Packit |
8480eb |
unlink(file);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void rm_unwanted(struct autofs_point *ap, const char *path, int incl)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
walk_tree(path, rm_unwanted_fn, incl, ap, &ap->dev);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct counter_args {
|
|
Packit |
8480eb |
unsigned int count;
|
|
Packit |
8480eb |
dev_t dev;
|
|
Packit |
8480eb |
};
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int counter_fn(struct autofs_point *ap, const char *file,
|
|
Packit |
8480eb |
const struct stat *st, int when, void *arg)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct counter_args *counter = (struct counter_args *) arg;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!st || (S_ISLNK(st->st_mode) || (S_ISDIR(st->st_mode)
|
|
Packit |
8480eb |
&& st->st_dev != counter->dev))) {
|
|
Packit |
8480eb |
counter->count++;
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Count mounted filesystems and symlinks */
|
|
Packit |
8480eb |
int count_mounts(struct autofs_point *ap, const char *path, dev_t dev)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct counter_args counter;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
counter.count = 0;
|
|
Packit |
8480eb |
counter.dev = dev;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (walk_tree(path, counter_fn, 1, ap, &counter) == -1)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return counter.count;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void check_rm_dirs(struct autofs_point *ap, const char *path, int incl)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* If we're a submount the kernel can't know we're trying to
|
|
Packit |
8480eb |
* shutdown and so cannot block processes walking into the
|
|
Packit |
8480eb |
* mount point directory. If this is the call to umount_multi()
|
|
Packit |
8480eb |
* made during shutdown (incl == 0) we have to leave any mount
|
|
Packit |
8480eb |
* point directories in place so we can recover if needed. The
|
|
Packit |
8480eb |
* umount itself will clean these directories up for us
|
|
Packit |
8480eb |
* automagically.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (!incl && ap->submount)
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if ((!(ap->flags & MOUNT_FLAG_GHOST)) ||
|
|
Packit |
8480eb |
(ap->state == ST_SHUTDOWN_PENDING ||
|
|
Packit |
8480eb |
ap->state == ST_SHUTDOWN_FORCE ||
|
|
Packit |
8480eb |
ap->state == ST_SHUTDOWN))
|
|
Packit |
8480eb |
rm_unwanted(ap, path, incl);
|
|
Packit |
8480eb |
else if ((ap->flags & MOUNT_FLAG_GHOST) && (ap->type == LKP_INDIRECT))
|
|
Packit |
8480eb |
rm_unwanted(ap, path, 0);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Try to purge cache entries kept around due to existing mounts */
|
|
Packit |
8480eb |
static void update_map_cache(struct autofs_point *ap, const char *path)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct map_source *map;
|
|
Packit |
8480eb |
struct mapent_cache *mc;
|
|
Packit |
8480eb |
const char *key;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ap->type == LKP_INDIRECT)
|
|
Packit |
8480eb |
key = strrchr(path, '/') + 1;
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
key = path;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
map = ap->entry->maps;
|
|
Packit |
8480eb |
while (map) {
|
|
Packit |
8480eb |
struct mapent *me = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Skip current, in-use cache */
|
|
Packit |
8480eb |
if (ap->entry->age <= map->age) {
|
|
Packit |
8480eb |
map = map->next;
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mc = map->mc;
|
|
Packit |
8480eb |
/* If the lock is busy try later */
|
|
Packit |
8480eb |
if (cache_try_writelock(mc)) {
|
|
Packit |
8480eb |
me = cache_lookup_distinct(mc, key);
|
|
Packit |
8480eb |
if (me && me->ioctlfd == -1)
|
|
Packit |
8480eb |
cache_delete(mc, key);
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
map = map->next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsigned int is_autofs_fs)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct mapent_cache *mc;
|
|
Packit |
8480eb |
struct mapent *me;
|
|
Packit |
8480eb |
unsigned int is_mm_root = 0;
|
|
Packit |
8480eb |
int left;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
me = lookup_source_mapent(ap, path, LKP_DISTINCT);
|
|
Packit |
8480eb |
if (!me) {
|
|
Packit |
8480eb |
char *ind_key;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ind_key = strrchr(path, '/');
|
|
Packit |
8480eb |
if (ind_key)
|
|
Packit |
8480eb |
ind_key++;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
me = lookup_source_mapent(ap, ind_key, LKP_NORMAL);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (me) {
|
|
Packit |
8480eb |
mc = me->mc;
|
|
Packit |
8480eb |
is_mm_root = (me->multi == me);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
left = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (me && me->multi) {
|
|
Packit |
8480eb |
char root[PATH_MAX];
|
|
Packit |
8480eb |
char *base;
|
|
Packit |
8480eb |
int cur_state;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_cleanup_push(cache_lock_cleanup, mc);
|
|
Packit |
8480eb |
|
|
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(root, "%s/%s", ap->path, me->multi->key);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
strcpy(root, me->multi->key);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (is_mm_root)
|
|
Packit |
8480eb |
base = NULL;
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
base = me->key + strlen(root);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
|
|
Packit |
8480eb |
/* Lock the closest parent nesting point for umount */
|
|
Packit |
8480eb |
cache_multi_writelock(me->parent);
|
|
Packit |
8480eb |
if (umount_multi_triggers(ap, me, root, base)) {
|
|
Packit |
8480eb |
warn(ap->logopt,
|
|
Packit |
8480eb |
"some offset mounts still present under %s", path);
|
|
Packit |
8480eb |
left++;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
cache_multi_unlock(me->parent);
|
|
Packit |
8480eb |
if (ap->entry->maps &&
|
|
Packit |
8480eb |
(ap->entry->maps->flags & MAP_FLAG_FORMAT_AMD))
|
|
Packit |
8480eb |
cache_pop_mapent(me);
|
|
Packit |
8480eb |
pthread_setcancelstate(cur_state, NULL);
|
|
Packit |
8480eb |
pthread_cleanup_pop(0);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (me)
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (left || is_autofs_fs)
|
|
Packit |
8480eb |
return left;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* If this is the root of a multi-mount we've had to umount
|
|
Packit |
8480eb |
* it already to ensure it's ok to remove any offset triggers.
|
|
Packit |
8480eb |
*/
|
|
Packit Service |
42268b |
if (!is_mm_root && is_mounted(_PATH_MOUNTED, path, MNTS_REAL)) {
|
|
Packit |
8480eb |
struct amd_entry *entry;
|
|
Packit |
8480eb |
debug(ap->logopt, "unmounting dir = %s", path);
|
|
Packit |
8480eb |
if (umount_ent(ap, path) &&
|
|
Packit Service |
42268b |
is_mounted(_PATH_MOUNTED, path, MNTS_REAL)) {
|
|
Packit |
8480eb |
warn(ap->logopt, "could not umount dir %s", path);
|
|
Packit |
8480eb |
left++;
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Check for an external mount and umount if possible */
|
|
Packit |
8480eb |
mounts_mutex_lock(ap);
|
|
Packit |
8480eb |
entry = __master_find_amdmount(ap, path);
|
|
Packit |
8480eb |
if (!entry) {
|
|
Packit |
8480eb |
mounts_mutex_unlock(ap);
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
list_del(&entry->entries);
|
|
Packit |
8480eb |
mounts_mutex_unlock(ap);
|
|
Packit |
8480eb |
umount_amd_ext_mount(ap, entry);
|
|
Packit |
8480eb |
free_amd_entry(entry);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
done:
|
|
Packit |
8480eb |
return left;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* umount all filesystems mounted under path. If incl is true, then
|
|
Packit |
8480eb |
it also tries to umount path itself */
|
|
Packit |
8480eb |
int umount_multi(struct autofs_point *ap, const char *path, int incl)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int is_autofs_fs;
|
|
Packit |
8480eb |
struct stat st;
|
|
Packit |
8480eb |
int left;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(ap->logopt, "path %s incl %d", path, incl);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (lstat(path, &st)) {
|
|
Packit |
8480eb |
warn(ap->logopt,
|
|
Packit |
8480eb |
"failed to stat directory or symlink %s", path);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* if this is a symlink we can handle it now */
|
|
Packit |
8480eb |
if (S_ISLNK(st.st_mode)) {
|
|
Packit |
8480eb |
struct amd_entry *entry;
|
|
Packit |
8480eb |
if (st.st_dev != ap->dev) {
|
|
Packit |
8480eb |
crit(ap->logopt,
|
|
Packit |
8480eb |
"symlink %s has the wrong device, "
|
|
Packit |
8480eb |
"possible race condition", path);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
debug(ap->logopt, "removing symlink %s", path);
|
|
Packit |
8480eb |
if (unlink(path)) {
|
|
Packit |
8480eb |
error(ap->logopt,
|
|
Packit |
8480eb |
"failed to remove symlink %s", path);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
/* Check for an external mount and attempt umount if needed */
|
|
Packit |
8480eb |
mounts_mutex_lock(ap);
|
|
Packit |
8480eb |
entry = __master_find_amdmount(ap, path);
|
|
Packit |
8480eb |
if (!entry) {
|
|
Packit |
8480eb |
mounts_mutex_unlock(ap);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
list_del(&entry->entries);
|
|
Packit |
8480eb |
mounts_mutex_unlock(ap);
|
|
Packit |
8480eb |
umount_amd_ext_mount(ap, entry);
|
|
Packit |
8480eb |
free_amd_entry(entry);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
is_autofs_fs = 0;
|
|
Packit |
8480eb |
if (master_find_submount(ap, path))
|
|
Packit |
8480eb |
is_autofs_fs = 1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
left = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* If we are a submount we need to umount any offsets our
|
|
Packit |
8480eb |
* parent may have mounted over top of us.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (ap->submount)
|
|
Packit |
8480eb |
left += umount_subtree_mounts(ap->parent, path, 1);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
left += umount_subtree_mounts(ap, path, is_autofs_fs);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Delete detritus like unwanted mountpoints and symlinks */
|
|
Packit |
8480eb |
if (left == 0 &&
|
|
Packit |
8480eb |
ap->state != ST_READMAP &&
|
|
Packit |
8480eb |
!count_mounts(ap, path, ap->dev)) {
|
|
Packit |
8480eb |
update_map_cache(ap, path);
|
|
Packit |
8480eb |
check_rm_dirs(ap, path, incl);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return left;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int umount_all(struct autofs_point *ap, int force)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int left;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
left = umount_multi(ap, ap->path, 0);
|
|
Packit |
8480eb |
if (force && left)
|
|
Packit |
8480eb |
warn(ap->logopt, "could not unmount %d dirs under %s",
|
|
Packit |
8480eb |
left, ap->path);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return left;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int umount_autofs(struct autofs_point *ap, const char *root, int force)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int ret = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ap->state == ST_INIT)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Since lookup.c is lazy about closing lookup modules
|
|
Packit |
8480eb |
* to prevent unneeded opens, we need to clean them up
|
|
Packit |
8480eb |
* before umount.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
lookup_close_lookup(ap);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ap->type == LKP_INDIRECT) {
|
|
Packit |
8480eb |
if (umount_all(ap, force) && !force)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
ret = umount_autofs_indirect(ap, root);
|
|
Packit |
8480eb |
} else
|
|
Packit |
8480eb |
ret = umount_autofs_direct(ap);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static size_t get_kpkt_len(void)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
size_t pkt_len = sizeof(struct autofs_v5_packet);
|
|
Packit |
8480eb |
struct utsname un;
|
|
Packit |
8480eb |
int kern_vers;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
kern_vers = linux_version_code();
|
|
Packit |
8480eb |
if (kern_vers >= KERNEL_VERSION(3, 3, 0))
|
|
Packit |
8480eb |
return pkt_len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
uname(&un;;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (pkt_len % 8) {
|
|
Packit |
8480eb |
if (strcmp(un.machine, "alpha") == 0 ||
|
|
Packit |
8480eb |
strcmp(un.machine, "ia64") == 0 ||
|
|
Packit |
8480eb |
strcmp(un.machine, "x86_64") == 0 ||
|
|
Packit |
8480eb |
strcmp(un.machine, "parisc64") == 0 ||
|
|
Packit |
8480eb |
strcmp(un.machine, "ppc64") == 0)
|
|
Packit |
8480eb |
pkt_len += 4;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return pkt_len;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int fullread(int fd, void *ptr, size_t len)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *buf = (char *) ptr;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (len > 0) {
|
|
Packit |
8480eb |
ssize_t r = read(fd, buf, len);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (r == -1) {
|
|
Packit |
8480eb |
if (errno == EINTR)
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
buf += r;
|
|
Packit |
8480eb |
len -= r;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return len;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static char *automount_path_to_fifo(unsigned logopt, const char *path)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *fifo_name, *p;
|
|
Packit |
8480eb |
int name_len = strlen(path) + strlen(fifodir) + 1;
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
fifo_name = malloc(name_len);
|
|
Packit |
8480eb |
if (!fifo_name)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
ret = snprintf(fifo_name, name_len, "%s%s", fifodir, path);
|
|
Packit |
8480eb |
if (ret >= name_len) {
|
|
Packit |
8480eb |
info(logopt,
|
|
Packit |
8480eb |
"fifo path for \"%s\" truncated to \"%s\". This may "
|
|
Packit |
8480eb |
"lead to --set-log-priority commands being sent to the "
|
|
Packit |
8480eb |
"wrong automount daemon.", path, fifo_name);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* An automount path can be made up of subdirectories. So, to
|
|
Packit |
8480eb |
* create the fifo name, we will just replace instances of '/' with
|
|
Packit |
8480eb |
* '-'.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
p = fifo_name + strlen(fifodir);
|
|
Packit |
8480eb |
while (*p != '\0') {
|
|
Packit |
8480eb |
if (*p == '/')
|
|
Packit |
8480eb |
*p = '-';
|
|
Packit |
8480eb |
p++;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(logopt, "fifo name %s",fifo_name);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return fifo_name;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int create_logpri_fifo(struct autofs_point *ap)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int ret = -1;
|
|
Packit |
8480eb |
int fd;
|
|
Packit |
8480eb |
char *fifo_name;
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
fifo_name = automount_path_to_fifo(ap->logopt, ap->path);
|
|
Packit |
8480eb |
if (!fifo_name) {
|
|
Packit |
8480eb |
crit(ap->logopt, "Failed to allocate memory!");
|
|
Packit |
8480eb |
goto out_free; /* free(NULL) is okay */
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = unlink(fifo_name);
|
|
Packit |
8480eb |
if (ret != 0 && errno != ENOENT) {
|
|
Packit |
8480eb |
crit(ap->logopt,
|
|
Packit |
8480eb |
"Failed to unlink FIFO. Is the automount daemon "
|
|
Packit |
8480eb |
"already running?");
|
|
Packit |
8480eb |
goto out_free;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = mkfifo(fifo_name, S_IRUSR|S_IWUSR);
|
|
Packit |
8480eb |
if (ret != 0) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
crit(ap->logopt,
|
|
Packit |
8480eb |
"mkfifo for %s failed: %s", fifo_name, estr);
|
|
Packit |
8480eb |
goto out_free;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
fd = open_fd(fifo_name, O_RDWR|O_NONBLOCK);
|
|
Packit |
8480eb |
if (fd < 0) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
crit(ap->logopt,
|
|
Packit |
8480eb |
"Failed to open %s: %s", fifo_name, estr);
|
|
Packit |
8480eb |
unlink(fifo_name);
|
|
Packit |
8480eb |
ret = -1;
|
|
Packit |
8480eb |
goto out_free;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ap->logpri_fifo = fd;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
out_free:
|
|
Packit |
8480eb |
free(fifo_name);
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int destroy_logpri_fifo(struct autofs_point *ap)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int ret = -1;
|
|
Packit |
8480eb |
int fd = ap->logpri_fifo;
|
|
Packit |
8480eb |
char *fifo_name;
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (fd == -1)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
fifo_name = automount_path_to_fifo(ap->logopt, ap->path);
|
|
Packit |
8480eb |
if (!fifo_name) {
|
|
Packit |
8480eb |
crit(ap->logopt, "Failed to allocate memory!");
|
|
Packit |
8480eb |
goto out_free; /* free(NULL) is okay */
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ap->logpri_fifo = -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = close(fd);
|
|
Packit |
8480eb |
if (ret != 0) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
warn(ap->logopt,
|
|
Packit |
8480eb |
"close for fifo %s: %s", fifo_name, estr);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = unlink(fifo_name);
|
|
Packit |
8480eb |
if (ret != 0) {
|
|
Packit |
8480eb |
warn(ap->logopt,
|
|
Packit |
8480eb |
"Failed to unlink FIFO. Was the fifo created OK?");
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
out_free:
|
|
Packit |
8480eb |
free(fifo_name);
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void handle_fifo_message(struct autofs_point *ap, int fd)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
char buffer[PIPE_BUF];
|
|
Packit |
8480eb |
char *end;
|
|
Packit |
8480eb |
long pri;
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
memset(buffer, 0, sizeof(buffer));
|
|
Packit |
8480eb |
ret = read(fd, &buffer, sizeof(buffer));
|
|
Packit |
8480eb |
if (ret < 0) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
warn(ap->logopt, "read on fifo returned error: %s", estr);
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ret != 2) {
|
|
Packit |
8480eb |
debug(ap->logopt, "expected 2 bytes, received %d.", ret);
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
errno = 0;
|
|
Packit |
8480eb |
pri = strtol(buffer, &end, 10);
|
|
Packit |
8480eb |
if ((pri == LONG_MIN || pri == LONG_MAX) && errno == ERANGE) {
|
|
Packit |
8480eb |
debug(ap->logopt, "strtol reported an %s. Failed to set "
|
|
Packit |
8480eb |
"log priority.", pri == LONG_MIN ? "underflow" : "overflow");
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if ((pri == 0 && errno == EINVAL) || end == buffer) {
|
|
Packit |
8480eb |
debug(ap->logopt, "priority is expected to be an integer "
|
|
Packit |
8480eb |
"in the range 0-7 inclusive.");
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (pri > LOG_DEBUG || pri < LOG_EMERG) {
|
|
Packit |
8480eb |
debug(ap->logopt, "invalid log priority (%ld) received "
|
|
Packit |
8480eb |
"on fifo", pri);
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* OK, the message passed all of the sanity checks. The
|
|
Packit |
8480eb |
* automounter actually only supports three log priorities.
|
|
Packit |
8480eb |
* Everything is logged at log level debug, deamon messages
|
|
Packit |
8480eb |
* and everything except debug messages are logged with the
|
|
Packit |
8480eb |
* verbose setting and only error and critical messages are
|
|
Packit |
8480eb |
* logged when debugging isn't enabled.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (pri >= LOG_WARNING) {
|
|
Packit |
8480eb |
if (pri == LOG_DEBUG) {
|
|
Packit |
8480eb |
set_log_debug_ap(ap);
|
|
Packit |
8480eb |
info(ap->logopt, "Debug logging set for %s", ap->path);
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
set_log_verbose_ap(ap);
|
|
Packit |
8480eb |
info(ap->logopt, "Verbose logging set for %s", ap->path);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
if (ap->logopt & LOGOPT_ANY)
|
|
Packit |
8480eb |
info(ap->logopt, "Basic logging set for %s", ap->path);
|
|
Packit |
8480eb |
set_log_norm_ap(ap);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int set_log_priority(const char *path, int priority)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int fd;
|
|
Packit |
8480eb |
char *fifo_name;
|
|
Packit |
8480eb |
char buf[2];
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (priority > LOG_DEBUG || priority < LOG_EMERG) {
|
|
Packit |
8480eb |
fprintf(stderr, "Log priority %d is invalid.\n", priority);
|
|
Packit |
8480eb |
fprintf(stderr, "Please specify a number in the range 0-7.\n");
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* This is an ascii based protocol, so we want the string
|
|
Packit |
8480eb |
* representation of the integer log priority.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
snprintf(buf, sizeof(buf), "%d", priority);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
fifo_name = automount_path_to_fifo(LOGOPT_NONE, path);
|
|
Packit |
8480eb |
if (!fifo_name) {
|
|
Packit |
8480eb |
fprintf(stderr, "%s: Failed to allocate memory!\n",
|
|
Packit |
8480eb |
__FUNCTION__);
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Specify O_NONBLOCK so that the open will fail if there is no
|
|
Packit |
8480eb |
* daemon reading from the other side of the FIFO.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
fd = open_fd(fifo_name, O_WRONLY|O_NONBLOCK);
|
|
Packit |
8480eb |
if (fd < 0) {
|
|
Packit |
8480eb |
fprintf(stderr, "%s: open of %s failed with %s\n",
|
|
Packit |
8480eb |
__FUNCTION__, fifo_name, strerror(errno));
|
|
Packit |
8480eb |
fprintf(stderr, "%s: perhaps the fifo wasn't setup,"
|
|
Packit |
8480eb |
" please check your log for more information\n", __FUNCTION__);
|
|
Packit |
8480eb |
free(fifo_name);
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (write(fd, buf, sizeof(buf)) != sizeof(buf)) {
|
|
Packit |
8480eb |
fprintf(stderr, "Failed to change logging priority. ");
|
|
Packit |
8480eb |
fprintf(stderr, "write to fifo failed: %s.\n",
|
|
Packit |
8480eb |
strerror(errno));
|
|
Packit |
8480eb |
close(fd);
|
|
Packit |
8480eb |
free(fifo_name);
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
close(fd);
|
|
Packit |
8480eb |
free(fifo_name);
|
|
Packit |
8480eb |
fprintf(stdout, "Successfully set log priority for %s.\n", path);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int get_pkt(struct autofs_point *ap, union autofs_v5_packet_union *pkt)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct pollfd fds[3];
|
|
Packit |
8480eb |
int pollfds = 3;
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
size_t read;
|
|
Packit |
8480eb |
char *estr;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
fds[0].fd = ap->pipefd;
|
|
Packit |
8480eb |
fds[0].events = POLLIN;
|
|
Packit |
8480eb |
fds[1].fd = ap->state_pipe[0];
|
|
Packit |
8480eb |
fds[1].events = POLLIN;
|
|
Packit |
8480eb |
fds[2].fd = ap->logpri_fifo;
|
|
Packit |
8480eb |
fds[2].events = POLLIN;
|
|
Packit |
8480eb |
if (fds[2].fd == -1)
|
|
Packit |
8480eb |
pollfds--;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
for (;;) {
|
|
Packit |
8480eb |
if (poll(fds, pollfds, -1) == -1) {
|
|
Packit |
8480eb |
if (errno == EINTR)
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
logerr("poll failed: %s", estr);
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (fds[1].revents & POLLIN) {
|
|
Packit |
8480eb |
enum states next_state;
|
|
Packit |
8480eb |
size_t read_size = sizeof(next_state);
|
|
Packit |
8480eb |
int state_pipe;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
next_state = ST_INVAL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
st_mutex_lock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
state_pipe = ap->state_pipe[0];
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
read = fullread(state_pipe, &next_state, read_size);
|
|
Packit |
8480eb |
if (read) {
|
|
Packit |
8480eb |
estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
error(ap->logopt,
|
|
Packit |
8480eb |
"read error on state pipe, "
|
|
Packit |
8480eb |
"read %u, error %s",
|
|
Packit |
8480eb |
read, estr);
|
|
Packit |
8480eb |
st_mutex_unlock();
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
st_mutex_unlock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (next_state == ST_SHUTDOWN)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (fds[0].revents & POLLIN) {
|
|
Packit |
8480eb |
read = fullread(ap->pipefd, pkt, kpkt_len);
|
|
Packit |
8480eb |
if (read) {
|
|
Packit |
8480eb |
estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
error(ap->logopt,
|
|
Packit |
8480eb |
"read error on request pipe, "
|
|
Packit |
8480eb |
"read %u, expected %u error %s",
|
|
Packit |
8480eb |
read, kpkt_len, estr);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return read;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (fds[2].fd != -1 && fds[2].revents & POLLIN) {
|
|
Packit |
8480eb |
debug(ap->logopt, "message pending on control fifo.");
|
|
Packit |
8480eb |
handle_fifo_message(ap, fds[2].fd);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int do_expire(struct autofs_point *ap, const char *name, int namelen)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char buf[PATH_MAX];
|
|
Packit |
8480eb |
int len, ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (*name != '/') {
|
|
Packit |
8480eb |
len = ncat_path(buf, sizeof(buf), ap->path, name, namelen);
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
len = snprintf(buf, PATH_MAX, "%s", name);
|
|
Packit |
8480eb |
if (len >= PATH_MAX)
|
|
Packit |
8480eb |
len = 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!len) {
|
|
Packit |
8480eb |
crit(ap->logopt, "path too long for buffer");
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
info(ap->logopt, "expiring path %s", buf);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_cleanup_push(master_source_lock_cleanup, ap->entry);
|
|
Packit |
8480eb |
master_source_readlock(ap->entry);
|
|
Packit |
8480eb |
ret = umount_multi(ap, buf, 1);
|
|
Packit |
8480eb |
if (ret == 0)
|
|
Packit |
8480eb |
info(ap->logopt, "expired %s", buf);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
warn(ap->logopt, "couldn't complete expire of %s", buf);
|
|
Packit |
8480eb |
pthread_cleanup_pop(1);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int autofs_init_ap(struct autofs_point *ap)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int pipefd[2];
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if ((ap->state != ST_INIT)) {
|
|
Packit |
8480eb |
/* This can happen if an autofs process is already running*/
|
|
Packit |
8480eb |
error(ap->logopt, "bad state %d", ap->state);
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ap->pipefd = ap->kpipefd = ap->ioctlfd = -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Pipe for kernel communications */
|
|
Packit |
8480eb |
if (open_pipe(pipefd) < 0) {
|
|
Packit |
8480eb |
crit(ap->logopt,
|
|
Packit |
8480eb |
"failed to create commumication pipe for autofs path %s",
|
|
Packit |
8480eb |
ap->path);
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ap->pipefd = pipefd[0];
|
|
Packit |
8480eb |
ap->kpipefd = pipefd[1];
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Pipe state changes from signal handler to main loop */
|
|
Packit |
8480eb |
if (open_pipe(ap->state_pipe) < 0) {
|
|
Packit |
8480eb |
crit(ap->logopt,
|
|
Packit |
8480eb |
"failed create state pipe for autofs path %s", ap->path);
|
|
Packit |
8480eb |
close(ap->pipefd);
|
|
Packit |
8480eb |
close(ap->kpipefd); /* Close kernel pipe end */
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (create_logpri_fifo(ap) < 0) {
|
|
Packit |
8480eb |
logmsg("could not create FIFO for path %s\n", ap->path);
|
|
Packit |
8480eb |
logmsg("dynamic log level changes not available for %s", ap->path);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int mount_autofs(struct autofs_point *ap, const char *root)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int status = 0;
|
|
Packit |
8480eb |
|
|
Packit Service |
42268b |
if (autofs_init_ap(ap) != 0)
|
|
Packit Service |
42268b |
return -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ap->type == LKP_DIRECT)
|
|
Packit |
8480eb |
status = mount_autofs_direct(ap);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
status = mount_autofs_indirect(ap, root);
|
|
Packit |
8480eb |
|
|
Packit Service |
42268b |
if (status < 0)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
st_add_task(ap, ST_READY);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int handle_packet(struct autofs_point *ap)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
union autofs_v5_packet_union pkt;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (get_pkt(ap, &pkt))
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(ap->logopt, "type = %d", pkt.hdr.type);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
switch (pkt.hdr.type) {
|
|
Packit |
8480eb |
case autofs_ptype_missing_indirect:
|
|
Packit |
8480eb |
return handle_packet_missing_indirect(ap, &pkt.v5_packet);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case autofs_ptype_missing_direct:
|
|
Packit |
8480eb |
return handle_packet_missing_direct(ap, &pkt.v5_packet);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case autofs_ptype_expire_indirect:
|
|
Packit |
8480eb |
return handle_packet_expire_indirect(ap, &pkt.v5_packet);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case autofs_ptype_expire_direct:
|
|
Packit |
8480eb |
return handle_packet_expire_direct(ap, &pkt.v5_packet);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
error(ap->logopt, "unknown packet type %d", pkt.hdr.type);
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit Service |
42268b |
static void become_daemon(unsigned foreground, unsigned daemon_check)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
FILE *pidfp;
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
int res;
|
|
Packit |
8480eb |
pid_t pid;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Don't BUSY any directories unnecessarily */
|
|
Packit |
8480eb |
if (chdir("/")) {
|
|
Packit |
8480eb |
fprintf(stderr, "%s: failed change working directory.\n",
|
|
Packit |
8480eb |
program);
|
|
Packit |
8480eb |
exit(0);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Detach from foreground process */
|
|
Packit Service |
42268b |
if (foreground) {
|
|
Packit Service |
42268b |
if (daemon_check && !aquire_flag_file()) {
|
|
Packit |
8480eb |
fprintf(stderr, "%s: program is already running.\n",
|
|
Packit |
8480eb |
program);
|
|
Packit |
8480eb |
exit(1);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
log_to_stderr();
|
|
Packit |
8480eb |
} else {
|
|
Packit Service |
b3e495 |
if (open_pipe(start_pipefd) < 0) {
|
|
Packit Service |
b3e495 |
fprintf(stderr, "%s: failed to create start_pipefd.\n",
|
|
Packit Service |
b3e495 |
program);
|
|
Packit Service |
b3e495 |
exit(0);
|
|
Packit Service |
b3e495 |
}
|
|
Packit Service |
b3e495 |
|
|
Packit |
8480eb |
pid = fork();
|
|
Packit |
8480eb |
if (pid > 0) {
|
|
Packit |
8480eb |
close(start_pipefd[1]);
|
|
Packit |
8480eb |
res = read(start_pipefd[0], pst_stat, sizeof(*pst_stat));
|
|
Packit |
8480eb |
if (res < 0)
|
|
Packit |
8480eb |
exit(1);
|
|
Packit |
8480eb |
exit(*pst_stat);
|
|
Packit |
8480eb |
} else if (pid < 0) {
|
|
Packit |
8480eb |
fprintf(stderr, "%s: Could not detach process\n",
|
|
Packit |
8480eb |
program);
|
|
Packit |
8480eb |
exit(1);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
close(start_pipefd[0]);
|
|
Packit |
8480eb |
|
|
Packit Service |
42268b |
if (daemon_check && !aquire_flag_file()) {
|
|
Packit |
8480eb |
fprintf(stderr, "%s: program is already running.\n",
|
|
Packit |
8480eb |
program);
|
|
Packit |
8480eb |
/* Return success if already running */
|
|
Packit |
8480eb |
st_stat = 0;
|
|
Packit |
8480eb |
res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
|
|
Packit |
8480eb |
if (res < 0)
|
|
Packit |
8480eb |
exit(1);
|
|
Packit |
8480eb |
close(start_pipefd[1]);
|
|
Packit |
8480eb |
exit(*pst_stat);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Make our own process group for "magic" reason: processes that share
|
|
Packit |
8480eb |
* our pgrp see the raw filesystem behind the magic.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (setsid() == -1) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
fprintf(stderr, "setsid: %s", estr);
|
|
Packit |
8480eb |
res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
|
|
Packit |
8480eb |
close(start_pipefd[1]);
|
|
Packit |
8480eb |
exit(*pst_stat);
|
|
Packit |
8480eb |
}
|
|
Packit Service |
42268b |
log_to_syslog();
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Write pid file if requested */
|
|
Packit |
8480eb |
if (pid_file) {
|
|
Packit |
8480eb |
if ((pidfp = fopen(pid_file, "wt"))) {
|
|
Packit |
8480eb |
fprintf(pidfp, "%lu\n", (unsigned long) getpid());
|
|
Packit |
8480eb |
fclose(pidfp);
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
logerr("failed to write pid file %s: %s",
|
|
Packit |
8480eb |
pid_file, estr);
|
|
Packit |
8480eb |
pid_file = NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static unsigned long getnumopt(char *str, char option)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
unsigned long val;
|
|
Packit |
8480eb |
char *end;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
val = strtoul(str, &end, 0);
|
|
Packit |
8480eb |
if (!*str || *end) {
|
|
Packit |
8480eb |
fprintf(stderr,
|
|
Packit |
8480eb |
"%s: option -%c requires a numeric argument, got %s\n",
|
|
Packit |
8480eb |
program, option, str);
|
|
Packit |
8480eb |
exit(1);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return val;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void do_master_cleanup_unlock(void *arg)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_unlock(&mrc.mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void *do_notify_state(void *arg)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct master *master;
|
|
Packit |
8480eb |
int sig;
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
sig = *(int *) arg;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_lock(&mrc.mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master = mrc.master;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(master->logopt, "signal %d", sig);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mrc.signaled = 1;
|
|
Packit |
8480eb |
status = pthread_cond_signal(&mrc.cond);
|
|
Packit |
8480eb |
if (status) {
|
|
Packit |
8480eb |
error(master->logopt,
|
|
Packit |
8480eb |
"failed to signal state notify condition");
|
|
Packit |
8480eb |
status = pthread_mutex_unlock(&mrc.mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
pthread_exit(NULL);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_unlock(&mrc.mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_notify_state_change(master, sig);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static pthread_t do_signals(struct master *master, int sig)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
pthread_t thid;
|
|
Packit |
8480eb |
int r_sig = sig;
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_lock(&mrc.mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_create(&thid, &th_attr_detached, do_notify_state, &r_sig);
|
|
Packit |
8480eb |
if (status) {
|
|
Packit |
8480eb |
error(master->logopt,
|
|
Packit |
8480eb |
"mount state notify thread create failed");
|
|
Packit |
8480eb |
status = pthread_mutex_unlock(&mrc.mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mrc.thid = thid;
|
|
Packit |
8480eb |
mrc.master = master;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_cleanup_push(do_master_cleanup_unlock, NULL);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mrc.signaled = 0;
|
|
Packit |
8480eb |
while (!mrc.signaled) {
|
|
Packit |
8480eb |
status = pthread_cond_wait(&mrc.cond, &mrc.mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_cleanup_pop(1);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return thid;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void *do_read_master(void *arg)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct master *master;
|
|
Packit |
8480eb |
unsigned int logopt;
|
|
Packit |
8480eb |
time_t age;
|
|
Packit |
8480eb |
int readall = 1;
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_lock(&mrc.mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master = mrc.master;
|
|
Packit |
8480eb |
age = mrc.age;
|
|
Packit |
8480eb |
logopt = master->logopt;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mrc.signaled = 1;
|
|
Packit |
8480eb |
status = pthread_cond_signal(&mrc.cond);
|
|
Packit |
8480eb |
if (status) {
|
|
Packit |
8480eb |
error(logopt,
|
|
Packit |
8480eb |
"failed to signal master read map condition");
|
|
Packit |
8480eb |
master->reading = 0;
|
|
Packit |
8480eb |
status = pthread_mutex_unlock(&mrc.mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
pthread_exit(NULL);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_unlock(&mrc.mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
defaults_read_config(1);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
info(logopt, "re-reading master map %s", master->name);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = master_read_master(master, age, readall);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master->reading = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int do_hup_signal(struct master *master)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
unsigned int logopt = master->logopt;
|
|
Packit |
8480eb |
time_t age = monotonic_time(NULL);
|
|
Packit |
8480eb |
pthread_t thid;
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_lock(&mrc.mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
nfs_mount_uses_string_options = check_nfs_mount_version(&vers, &check);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_mutex_lock();
|
|
Packit |
8480eb |
/* Already doing a map read or shutdown or no mounts */
|
|
Packit |
8480eb |
if (master->reading) {
|
|
Packit |
8480eb |
status = pthread_mutex_unlock(&mrc.mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
master_mutex_unlock();
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
master->reading = 1;
|
|
Packit |
8480eb |
master_mutex_unlock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_create(&thid, &th_attr_detached, do_read_master, NULL);
|
|
Packit |
8480eb |
if (status) {
|
|
Packit |
8480eb |
error(logopt,
|
|
Packit |
8480eb |
"master read map thread create failed");
|
|
Packit |
8480eb |
master->reading = 0;
|
|
Packit |
8480eb |
status = pthread_mutex_unlock(&mrc.mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mrc.thid = thid;
|
|
Packit |
8480eb |
mrc.master = master;
|
|
Packit |
8480eb |
mrc.age = age;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_cleanup_push(do_master_cleanup_unlock, NULL);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mrc.signaled = 0;
|
|
Packit |
8480eb |
while (!mrc.signaled) {
|
|
Packit |
8480eb |
status = pthread_cond_wait(&mrc.cond, &mrc.mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_cleanup_pop(1);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Deal with all the signal-driven events in the state machine */
|
|
Packit |
8480eb |
static void *statemachine(void *arg)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
sigset_t signalset;
|
|
Packit |
8480eb |
int sig;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
memcpy(&signalset, &block_sigs, sizeof(signalset));
|
|
Packit |
8480eb |
sigdelset(&signalset, SIGCHLD);
|
|
Packit |
8480eb |
sigdelset(&signalset, SIGCONT);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (1) {
|
|
Packit |
8480eb |
sigwait(&signalset, &sig);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
switch (sig) {
|
|
Packit |
8480eb |
case SIGTERM:
|
|
Packit |
8480eb |
case SIGINT:
|
|
Packit |
8480eb |
case SIGUSR2:
|
|
Packit |
8480eb |
master_mutex_lock();
|
|
Packit |
8480eb |
if (list_empty(&master_list->completed)) {
|
|
Packit |
8480eb |
if (list_empty(&master_list->mounts)) {
|
|
Packit |
8480eb |
master_mutex_unlock();
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
if (master_done(master_list)) {
|
|
Packit |
8480eb |
master_mutex_unlock();
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
master_mutex_unlock();
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
master_mutex_unlock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case SIGUSR1:
|
|
Packit |
8480eb |
do_signals(master_list, sig);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case SIGHUP:
|
|
Packit |
8480eb |
do_hup_signal(master_list);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
default:
|
|
Packit |
8480eb |
logerr("got unexpected signal %d!", sig);
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void return_start_status(void *arg)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct startup_cond *sc;
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
sc = (struct startup_cond *) arg;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
sc->done = 1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Startup condition mutex must be locked during
|
|
Packit |
8480eb |
* the startup process.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
status = pthread_cond_signal(&sc->cond);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_unlock(&sc->mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int handle_mounts_startup_cond_init(struct startup_cond *suc)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_init(&suc->mutex, NULL);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
return status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_cond_init(&suc->cond, NULL);
|
|
Packit |
8480eb |
if (status) {
|
|
Packit |
8480eb |
status = pthread_mutex_destroy(&suc->mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
return status;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_lock(&suc->mutex);
|
|
Packit |
8480eb |
if (status) {
|
|
Packit |
8480eb |
status = pthread_mutex_destroy(&suc->mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
status = pthread_cond_destroy(&suc->cond);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void handle_mounts_startup_cond_destroy(void *arg)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct startup_cond *suc = (struct startup_cond *) arg;
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_unlock(&suc->mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_destroy(&suc->mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_cond_destroy(&suc->cond);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void handle_mounts_cleanup(void *arg)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct autofs_point *ap;
|
|
Packit |
8480eb |
char path[PATH_MAX + 1];
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
unsigned int clean = 0, submount, logopt;
|
|
Packit |
8480eb |
unsigned int pending = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ap = (struct autofs_point *) arg;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
logopt = ap->logopt;
|
|
Packit |
8480eb |
submount = ap->submount;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
strcpy(path, ap->path);
|
|
Packit |
8480eb |
if (!submount && strcmp(ap->path, "/-") &&
|
|
Packit |
8480eb |
ap->flags & MOUNT_FLAG_DIR_CREATED)
|
|
Packit |
8480eb |
clean = 1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (submount) {
|
|
Packit |
8480eb |
struct amd_entry *am;
|
|
Packit |
8480eb |
/* We are finishing up */
|
|
Packit |
8480eb |
ap->parent->submnt_count--;
|
|
Packit |
8480eb |
list_del_init(&ap->mounts);
|
|
Packit |
8480eb |
am = __master_find_amdmount(ap->parent, ap->path);
|
|
Packit |
8480eb |
if (am) {
|
|
Packit |
8480eb |
list_del_init(&am->entries);
|
|
Packit |
8480eb |
free_amd_entry(am);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Don't signal the handler if we have already done so */
|
|
Packit |
8480eb |
if (!list_empty(&master_list->completed))
|
|
Packit |
8480eb |
pending = 1;
|
|
Packit |
8480eb |
master_remove_mapent(ap->entry);
|
|
Packit |
8480eb |
master_source_unlock(ap->entry);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
destroy_logpri_fifo(ap);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Submounts are detached threads and don't belong to the
|
|
Packit |
8480eb |
* master map entry list so we need to free their resources
|
|
Packit |
8480eb |
* here.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (submount) {
|
|
Packit |
8480eb |
mounts_mutex_unlock(ap->parent);
|
|
Packit |
8480eb |
master_source_unlock(ap->parent->entry);
|
|
Packit |
8480eb |
master_free_mapent_sources(ap->entry, 1);
|
|
Packit |
8480eb |
master_free_mapent(ap->entry);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (clean) {
|
|
Packit |
8480eb |
if (rmdir(path) == -1) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
warn(logopt, "failed to remove dir %s: %s",
|
|
Packit |
8480eb |
path, estr);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
info(logopt, "shut down path %s", path);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* If we are not a submount send a signal to the signal handler
|
|
Packit |
8480eb |
* so it can join with any completed handle_mounts() threads and
|
|
Packit |
8480eb |
* perform final cleanup.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (!submount && !pending)
|
|
Packit |
8480eb |
pthread_kill(state_mach_thid, SIGTERM);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_mutex_unlock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int submount_source_writelock_nested(struct autofs_point *ap)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct autofs_point *parent = ap->parent;
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_rwlock_trywrlock(&parent->entry->source_lock);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mounts_mutex_lock(parent);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_rwlock_trywrlock(&ap->entry->source_lock);
|
|
Packit |
8480eb |
if (status) {
|
|
Packit |
8480eb |
mounts_mutex_unlock(parent);
|
|
Packit |
8480eb |
master_source_unlock(parent->entry);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
done:
|
|
Packit |
8480eb |
if (status && status != EBUSY) {
|
|
Packit |
8480eb |
logmsg("submount nested master_mapent source write lock failed");
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return status;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void submount_source_unlock_nested(struct autofs_point *ap)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct autofs_point *parent = ap->parent;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_source_unlock(ap->entry);
|
|
Packit |
8480eb |
mounts_mutex_unlock(parent);
|
|
Packit |
8480eb |
master_source_unlock(parent->entry);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int handle_mounts_exit(struct autofs_point *ap)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int ret, cur_state;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* If we're a submount we need to ensure our parent
|
|
Packit |
8480eb |
* doesn't try to mount us again until our shutdown
|
|
Packit |
8480eb |
* is complete and that any outstanding mounts are
|
|
Packit |
8480eb |
* completed before we try to shutdown.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_mutex_lock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!ap->submount)
|
|
Packit |
8480eb |
master_source_writelock(ap->entry);
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* If a mount request arrives before the locks are
|
|
Packit |
8480eb |
* aquired just return to ready state.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
ret = submount_source_writelock_nested(ap);
|
|
Packit |
8480eb |
if (ret) {
|
|
Packit |
8480eb |
warn(ap->logopt,
|
|
Packit |
8480eb |
"can't shutdown submount: mount in progress");
|
|
Packit |
8480eb |
/* Return to ST_READY is done immediately */
|
|
Packit |
8480eb |
st_add_task(ap, ST_READY);
|
|
Packit |
8480eb |
master_mutex_unlock();
|
|
Packit |
8480eb |
pthread_setcancelstate(cur_state, NULL);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ap->state != ST_SHUTDOWN) {
|
|
Packit |
8480eb |
if (!ap->submount)
|
|
Packit |
8480eb |
alarm_add(ap, ap->exp_runfreq);
|
|
Packit |
8480eb |
/* Return to ST_READY is done immediately */
|
|
Packit |
8480eb |
st_add_task(ap, ST_READY);
|
|
Packit |
8480eb |
if (ap->submount)
|
|
Packit |
8480eb |
submount_source_unlock_nested(ap);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
master_source_unlock(ap->entry);
|
|
Packit |
8480eb |
master_mutex_unlock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_setcancelstate(cur_state, NULL);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
alarm_delete(ap);
|
|
Packit |
8480eb |
st_remove_tasks(ap);
|
|
Packit |
8480eb |
st_wait_task(ap, ST_ANY, 0);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* For a direct mount map all mounts have already gone
|
|
Packit |
8480eb |
* by the time we get here and since we only ever
|
|
Packit |
8480eb |
* umount direct mounts at shutdown there is no need
|
|
Packit |
8480eb |
* to check for possible recovery.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (ap->type == LKP_DIRECT) {
|
|
Packit |
8480eb |
umount_autofs(ap, NULL, 1);
|
|
Packit |
8480eb |
handle_mounts_cleanup(ap);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* If umount_autofs returns non-zero it wasn't able
|
|
Packit |
8480eb |
* to complete the umount and has left the mount intact
|
|
Packit |
8480eb |
* so we can continue. This can happen if a lookup
|
|
Packit |
8480eb |
* occurs while we're trying to umount.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
ret = umount_autofs(ap, NULL, 1);
|
|
Packit |
8480eb |
if (!ret) {
|
|
Packit |
8480eb |
set_indirect_mount_tree_catatonic(ap);
|
|
Packit |
8480eb |
handle_mounts_cleanup(ap);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Failed shutdown returns to ready */
|
|
Packit |
8480eb |
warn(ap->logopt, "can't shutdown: filesystem %s still busy", ap->path);
|
|
Packit |
8480eb |
if (!ap->submount)
|
|
Packit |
8480eb |
alarm_add(ap, ap->exp_runfreq);
|
|
Packit |
8480eb |
/* Return to ST_READY is done immediately */
|
|
Packit |
8480eb |
st_add_task(ap, ST_READY);
|
|
Packit |
8480eb |
if (ap->submount)
|
|
Packit |
8480eb |
submount_source_unlock_nested(ap);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
master_source_unlock(ap->entry);
|
|
Packit |
8480eb |
master_mutex_unlock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_setcancelstate(cur_state, NULL);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void *handle_mounts(void *arg)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct startup_cond *suc;
|
|
Packit |
8480eb |
struct autofs_point *ap;
|
|
Packit |
8480eb |
int cancel_state, status = 0;
|
|
Packit |
8480eb |
char *root;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
suc = (struct startup_cond *) arg;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ap = suc->ap;
|
|
Packit |
8480eb |
root = strdup(suc->root);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_cleanup_push(return_start_status, suc);
|
|
Packit |
8480eb |
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel_state);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_lock(&suc->mutex);
|
|
Packit |
8480eb |
if (status) {
|
|
Packit |
8480eb |
logerr("failed to lock startup condition mutex!");
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!root) {
|
|
Packit |
8480eb |
crit(ap->logopt, "failed to alloc string root");
|
|
Packit |
8480eb |
suc->status = 1;
|
|
Packit |
8480eb |
pthread_setcancelstate(cancel_state, NULL);
|
|
Packit |
8480eb |
pthread_exit(NULL);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (mount_autofs(ap, root) < 0) {
|
|
Packit Service |
42268b |
crit(ap->logopt, "mount of %s failed!", ap->path);
|
|
Packit |
8480eb |
suc->status = 1;
|
|
Packit |
8480eb |
umount_autofs(ap, root, 1);
|
|
Packit |
8480eb |
free(root);
|
|
Packit |
8480eb |
pthread_setcancelstate(cancel_state, NULL);
|
|
Packit |
8480eb |
pthread_exit(NULL);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free(root);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ap->flags & MOUNT_FLAG_NOBIND)
|
|
Packit |
8480eb |
info(ap->logopt, "bind mounts disabled");
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ap->flags & MOUNT_FLAG_GHOST && ap->type != LKP_DIRECT)
|
|
Packit |
8480eb |
info(ap->logopt, "ghosting enabled");
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
suc->status = 0;
|
|
Packit |
8480eb |
pthread_cleanup_pop(1);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* We often start several automounters at the same time. Add some
|
|
Packit |
8480eb |
randomness so we don't all expire at the same time. */
|
|
Packit |
8480eb |
if (!ap->submount && ap->exp_runfreq)
|
|
Packit |
8480eb |
alarm_add(ap, ap->exp_runfreq + rand() % ap->exp_runfreq);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_setcancelstate(cancel_state, NULL);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (1) {
|
|
Packit |
8480eb |
if (handle_packet(ap)) {
|
|
Packit |
8480eb |
if (handle_mounts_exit(ap))
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* If we get here a packet has been received and handled
|
|
Packit |
8480eb |
* and the autofs mount point has not been shutdown. But
|
|
Packit |
8480eb |
* if the autofs mount point has been set to ST_SHUTDOWN
|
|
Packit |
8480eb |
* we should attempt to perform the shutdown cleanup and
|
|
Packit |
8480eb |
* exit if successful.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (ap->state == ST_SHUTDOWN) {
|
|
Packit |
8480eb |
if (handle_mounts_exit(ap))
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void key_thread_stdenv_vars_destroy(void *arg)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct thread_stdenv_vars *tsv;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tsv = (struct thread_stdenv_vars *) arg;
|
|
Packit |
8480eb |
if (tsv->user)
|
|
Packit |
8480eb |
free(tsv->user);
|
|
Packit |
8480eb |
if (tsv->group)
|
|
Packit |
8480eb |
free(tsv->group);
|
|
Packit |
8480eb |
if (tsv->home)
|
|
Packit |
8480eb |
free(tsv->home);
|
|
Packit |
8480eb |
free(tsv);
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void usage(void)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
fprintf(stderr,
|
|
Packit |
8480eb |
"Usage: %s [options] [master_map_name]\n"
|
|
Packit |
8480eb |
" -h --help this text\n"
|
|
Packit |
8480eb |
" -p --pid-file f write process id to file f\n"
|
|
Packit |
8480eb |
" -t --timeout n auto-unmount in n seconds (0-disable)\n"
|
|
Packit |
8480eb |
" -v --verbose be verbose\n"
|
|
Packit |
8480eb |
" -d --debug log debuging info\n"
|
|
Packit Service |
42268b |
" -D --define define global macro variable\n"
|
|
Packit |
8480eb |
" -f --foreground do not fork into background\n"
|
|
Packit |
8480eb |
" -r --random-multimount-selection\n"
|
|
Packit |
8480eb |
" use ramdom replicated server selection\n"
|
|
Packit |
8480eb |
" -m --dumpmaps [<map type> <map name>]\n"
|
|
Packit |
8480eb |
" dump automounter maps and exit\n"
|
|
Packit |
8480eb |
" -n --negative-timeout n\n"
|
|
Packit |
8480eb |
" set the timeout for failed key lookups.\n"
|
|
Packit |
8480eb |
" -O --global-options\n"
|
|
Packit |
8480eb |
" specify global mount options\n"
|
|
Packit |
8480eb |
" -l --set-log-priority priority path [path,...]\n"
|
|
Packit |
8480eb |
" set daemon log verbosity\n"
|
|
Packit |
8480eb |
" -C --dont-check-daemon\n"
|
|
Packit |
8480eb |
" don't check if daemon is already running\n"
|
|
Packit |
8480eb |
" -F --force forceably clean up known automounts at start\n"
|
|
Packit |
8480eb |
" -V --version print version, build config and exit\n"
|
|
Packit |
8480eb |
, program);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void show_build_info(void)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int count = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
printf("\nLinux automount version %s\n", version);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
printf("\nDirectories:\n");
|
|
Packit |
8480eb |
printf("\tconfig dir:\t%s\n", confdir);
|
|
Packit |
8480eb |
printf("\tmaps dir:\t%s\n", mapdir);
|
|
Packit |
8480eb |
printf("\tmodules dir:\t%s\n", libdir);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
printf("\nCompile options:\n ");
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#ifndef ENABLE_MOUNT_LOCKING
|
|
Packit |
8480eb |
printf("DISABLE_MOUNT_LOCKING ");
|
|
Packit |
8480eb |
count = 22;
|
|
Packit |
8480eb |
#endif
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#ifdef ENABLE_FORCED_SHUTDOWN
|
|
Packit |
8480eb |
printf("ENABLE_FORCED_SHUTDOWN ");
|
|
Packit |
8480eb |
count = count + 23;
|
|
Packit |
8480eb |
#endif
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#ifdef ENABLE_IGNORE_BUSY_MOUNTS
|
|
Packit |
8480eb |
printf("ENABLE_IGNORE_BUSY_MOUNTS ");
|
|
Packit |
8480eb |
count = count + 26;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (count > 60) {
|
|
Packit |
8480eb |
printf("\n ");
|
|
Packit |
8480eb |
count = 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
#endif
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#ifdef WITH_HESIOD
|
|
Packit |
8480eb |
printf("WITH_HESIOD ");
|
|
Packit |
8480eb |
count = count + 12;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (count > 60) {
|
|
Packit |
8480eb |
printf("\n ");
|
|
Packit |
8480eb |
count = 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
#endif
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#ifdef WITH_LDAP
|
|
Packit |
8480eb |
printf("WITH_LDAP ");
|
|
Packit |
8480eb |
count = count + 10;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (count > 60) {
|
|
Packit |
8480eb |
printf("\n ");
|
|
Packit |
8480eb |
count = 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
#endif
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#ifdef WITH_SASL
|
|
Packit |
8480eb |
printf("WITH_SASL ");
|
|
Packit |
8480eb |
count = count + 10;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (count > 60) {
|
|
Packit |
8480eb |
printf("\n ");
|
|
Packit |
8480eb |
count = 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
#endif
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#ifdef WITH_DMALLOC
|
|
Packit |
8480eb |
printf("WITH_DMALLOC ");
|
|
Packit |
8480eb |
count = count + 13;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (count > 60) {
|
|
Packit |
8480eb |
printf("\n ");
|
|
Packit |
8480eb |
count = 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
#endif
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#ifdef LIBXML2_WORKAROUND
|
|
Packit |
8480eb |
printf("LIBXML2_WORKAROUND ");
|
|
Packit |
8480eb |
count = count + 19;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (count > 60) {
|
|
Packit |
8480eb |
printf("\n ");
|
|
Packit |
8480eb |
count = 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
#endif
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#ifdef WITH_LIBTIRPC
|
|
Packit |
8480eb |
printf("WITH_LIBTIRPC ");
|
|
Packit |
8480eb |
count = count + 14;
|
|
Packit |
8480eb |
#endif
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
printf("\n\n");
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
typedef struct _code {
|
|
Packit |
8480eb |
char *c_name;
|
|
Packit |
8480eb |
int c_val;
|
|
Packit |
8480eb |
} CODE;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
CODE prioritynames[] = {
|
|
Packit |
8480eb |
{ "alert", LOG_ALERT },
|
|
Packit |
8480eb |
{ "crit", LOG_CRIT },
|
|
Packit |
8480eb |
{ "debug", LOG_DEBUG },
|
|
Packit |
8480eb |
{ "emerg", LOG_EMERG },
|
|
Packit |
8480eb |
{ "err", LOG_ERR },
|
|
Packit |
8480eb |
{ "error", LOG_ERR }, /* DEPRECATED */
|
|
Packit |
8480eb |
{ "info", LOG_INFO },
|
|
Packit |
8480eb |
{ "notice", LOG_NOTICE },
|
|
Packit |
8480eb |
{ "panic", LOG_EMERG }, /* DEPRECATED */
|
|
Packit |
8480eb |
{ "warn", LOG_WARNING }, /* DEPRECATED */
|
|
Packit |
8480eb |
{ "warning", LOG_WARNING },
|
|
Packit |
8480eb |
{ NULL, -1 },
|
|
Packit |
8480eb |
};
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int convert_log_priority(char *priority_name)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
CODE *priority_mapping;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
for (priority_mapping = prioritynames;
|
|
Packit |
8480eb |
priority_mapping->c_name != NULL;
|
|
Packit |
8480eb |
priority_mapping++) {
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!strcasecmp(priority_name, priority_mapping->c_name))
|
|
Packit |
8480eb |
return priority_mapping->c_val;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void remove_empty_args(char **argv, int *argc)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int next_to_last = *argc - 1;
|
|
Packit |
8480eb |
int i, j;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
for (i = j = 1; i < *argc; i++) {
|
|
Packit |
8480eb |
if (*argv[i]) {
|
|
Packit |
8480eb |
j++;
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (i < *argc && argv[i] && !*argv[i]) i++;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (i == *argc)
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (i == next_to_last) {
|
|
Packit |
8480eb |
if (*argv[i])
|
|
Packit |
8480eb |
argv[j++] = argv[i];
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
argv[j++] = argv[i];
|
|
Packit |
8480eb |
argv[i--] = "";
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
*argc = j;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void do_master_list_reset(struct master *master)
|
|
Packit |
8480eb |
{
|
|
Packit Service |
bd6ddb |
struct list_head *head, *p, *n;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_mutex_lock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
head = &master->mounts;
|
|
Packit Service |
bd6ddb |
n = head->next;
|
|
Packit Service |
bd6ddb |
while (n != head) {
|
|
Packit |
8480eb |
struct master_mapent *entry;
|
|
Packit |
8480eb |
|
|
Packit Service |
bd6ddb |
p = n;
|
|
Packit Service |
bd6ddb |
n = p->next;
|
|
Packit Service |
bd6ddb |
|
|
Packit |
8480eb |
entry = list_entry(p, struct master_mapent, list);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!list_empty(&entry->list))
|
|
Packit |
8480eb |
list_del(&entry->list);
|
|
Packit |
8480eb |
master_free_mapent_sources(entry, 1);
|
|
Packit |
8480eb |
master_free_mapent(entry);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_mutex_unlock();
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int do_master_read_master(struct master *master, int wait)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
sigset_t signalset;
|
|
Packit |
8480eb |
/* Wait must be at least 1 second */
|
|
Packit |
8480eb |
unsigned int retry_wait = 2;
|
|
Packit |
8480eb |
unsigned int elapsed = 0;
|
|
Packit |
8480eb |
int max_wait = wait;
|
|
Packit |
8480eb |
int ret = 0;
|
|
Packit |
8480eb |
time_t age;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
sigemptyset(&signalset);
|
|
Packit |
8480eb |
sigaddset(&signalset, SIGTERM);
|
|
Packit |
8480eb |
sigaddset(&signalset, SIGINT);
|
|
Packit |
8480eb |
sigaddset(&signalset, SIGHUP);
|
|
Packit |
8480eb |
sigprocmask(SIG_UNBLOCK, &signalset, NULL);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (1) {
|
|
Packit |
8480eb |
struct timespec t = { retry_wait, 0 };
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
do_master_list_reset(master);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
age = monotonic_time(NULL);
|
|
Packit |
8480eb |
if (master_read_master(master, age, 0)) {
|
|
Packit |
8480eb |
ret = 1;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (nanosleep(&t, NULL) == -1)
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (max_wait > 0) {
|
|
Packit |
8480eb |
elapsed += retry_wait;
|
|
Packit |
8480eb |
if (elapsed >= max_wait) {
|
|
Packit |
8480eb |
logmsg("problem reading master map, "
|
|
Packit |
8480eb |
"maximum wait exceeded");
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
sigprocmask(SIG_BLOCK, &signalset, NULL);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int main(int argc, char *argv[])
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int res, opt, status;
|
|
Packit |
8480eb |
int logpri = -1;
|
|
Packit Service |
42268b |
unsigned ghost, logging, daemon_check;
|
|
Packit Service |
42268b |
unsigned dumpmaps, foreground, have_global_options;
|
|
Packit |
8480eb |
unsigned master_read;
|
|
Packit |
8480eb |
int master_wait;
|
|
Packit |
8480eb |
time_t timeout;
|
|
Packit |
8480eb |
time_t age = monotonic_time(NULL);
|
|
Packit |
8480eb |
struct rlimit rlim;
|
|
Packit Service |
42268b |
const char *options = "+hp:t:vmdD:fVrO:l:n:CFM";
|
|
Packit |
8480eb |
static const struct option long_options[] = {
|
|
Packit |
8480eb |
{"help", 0, 0, 'h'},
|
|
Packit |
8480eb |
{"pid-file", 1, 0, 'p'},
|
|
Packit |
8480eb |
{"timeout", 1, 0, 't'},
|
|
Packit |
8480eb |
{"verbose", 0, 0, 'v'},
|
|
Packit |
8480eb |
{"debug", 0, 0, 'd'},
|
|
Packit |
8480eb |
{"define", 1, 0, 'D'},
|
|
Packit |
8480eb |
{"foreground", 0, 0, 'f'},
|
|
Packit |
8480eb |
{"random-multimount-selection", 0, 0, 'r'},
|
|
Packit |
8480eb |
{"negative-timeout", 1, 0, 'n'},
|
|
Packit |
8480eb |
{"dumpmaps", 0, 0, 'm'},
|
|
Packit |
8480eb |
{"global-options", 1, 0, 'O'},
|
|
Packit |
8480eb |
{"version", 0, 0, 'V'},
|
|
Packit |
8480eb |
{"set-log-priority", 1, 0, 'l'},
|
|
Packit |
8480eb |
{"dont-check-daemon", 0, 0, 'C'},
|
|
Packit |
8480eb |
{"force", 0, 0, 'F'},
|
|
Packit |
8480eb |
{"master-wait", 1, 0, 'M'},
|
|
Packit |
8480eb |
{0, 0, 0, 0}
|
|
Packit |
8480eb |
};
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
sigfillset(&block_sigs);
|
|
Packit |
8480eb |
/* allow for the dropping of core files */
|
|
Packit |
8480eb |
sigdelset(&block_sigs, SIGABRT);
|
|
Packit |
8480eb |
sigdelset(&block_sigs, SIGBUS);
|
|
Packit |
8480eb |
sigdelset(&block_sigs, SIGSEGV);
|
|
Packit |
8480eb |
sigdelset(&block_sigs, SIGILL);
|
|
Packit |
8480eb |
sigdelset(&block_sigs, SIGFPE);
|
|
Packit |
8480eb |
sigdelset(&block_sigs, SIGTRAP);
|
|
Packit |
8480eb |
sigprocmask(SIG_BLOCK, &block_sigs, NULL);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
program = argv[0];
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
defaults_read_config(0);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
nfs_mount_uses_string_options = check_nfs_mount_version(&vers, &check);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
kpkt_len = get_kpkt_len();
|
|
Packit |
8480eb |
master_wait = defaults_get_master_wait();
|
|
Packit |
8480eb |
timeout = defaults_get_timeout();
|
|
Packit Service |
42268b |
ghost = defaults_get_browse_mode();
|
|
Packit |
8480eb |
logging = defaults_get_logging();
|
|
Packit |
8480eb |
global_selection_options = 0;
|
|
Packit |
8480eb |
global_options = NULL;
|
|
Packit Service |
42268b |
have_global_options = 0;
|
|
Packit Service |
42268b |
foreground = 0;
|
|
Packit Service |
42268b |
dumpmaps = 0;
|
|
Packit Service |
42268b |
daemon_check = 1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
remove_empty_args(argv, &argc);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
opterr = 0;
|
|
Packit |
8480eb |
while ((opt = getopt_long(argc, argv, options, long_options, NULL)) != EOF) {
|
|
Packit |
8480eb |
switch (opt) {
|
|
Packit |
8480eb |
case 'h':
|
|
Packit |
8480eb |
usage();
|
|
Packit |
8480eb |
exit(0);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case 'p':
|
|
Packit |
8480eb |
pid_file = optarg;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case 't':
|
|
Packit |
8480eb |
timeout = getnumopt(optarg, opt);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case 'v':
|
|
Packit |
8480eb |
logging |= LOGOPT_VERBOSE;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case 'd':
|
|
Packit |
8480eb |
logging |= LOGOPT_DEBUG;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case 'D':
|
|
Packit |
8480eb |
macro_parse_globalvar(optarg);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case 'f':
|
|
Packit Service |
42268b |
foreground = 1;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case 'V':
|
|
Packit |
8480eb |
show_build_info();
|
|
Packit |
8480eb |
exit(0);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case 'r':
|
|
Packit |
8480eb |
global_selection_options |= MOUNT_FLAG_RANDOM_SELECT;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case 'n':
|
|
Packit |
8480eb |
global_negative_timeout = getnumopt(optarg, opt);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case 'm':
|
|
Packit Service |
42268b |
dumpmaps = 1;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case 'M':
|
|
Packit |
8480eb |
master_wait = getnumopt(optarg, opt);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case 'O':
|
|
Packit Service |
42268b |
if (!have_global_options) {
|
|
Packit |
8480eb |
global_options = strdup(optarg);
|
|
Packit Service |
42268b |
have_global_options = 1;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
printf("%s: global options already specified.\n",
|
|
Packit |
8480eb |
program);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case 'l':
|
|
Packit |
8480eb |
if (isalpha(*optarg)) {
|
|
Packit |
8480eb |
logpri = convert_log_priority(optarg);
|
|
Packit |
8480eb |
if (logpri < 0) {
|
|
Packit |
8480eb |
fprintf(stderr, "Invalid log priority:"
|
|
Packit |
8480eb |
" %s\n", optarg);
|
|
Packit |
8480eb |
exit(1);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
} else if (isdigit(*optarg)) {
|
|
Packit |
8480eb |
logpri = getnumopt(optarg, opt);
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
fprintf(stderr, "non-alphanumeric character "
|
|
Packit |
8480eb |
"found in log priority. Aborting.\n");
|
|
Packit |
8480eb |
exit(1);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case 'C':
|
|
Packit Service |
42268b |
daemon_check = 0;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case 'F':
|
|
Packit Service |
42268b |
do_force_unlink = 1;
|
|
Packit Service |
076792 |
break;
|
|
Packit Service |
076792 |
|
|
Packit |
8480eb |
case '?':
|
|
Packit |
8480eb |
case ':':
|
|
Packit |
8480eb |
printf("%s: Ambiguous or unknown options\n", program);
|
|
Packit |
8480eb |
exit(1);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (logging & LOGOPT_VERBOSE)
|
|
Packit |
8480eb |
set_log_verbose();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (logging & LOGOPT_DEBUG)
|
|
Packit |
8480eb |
set_log_debug();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (geteuid() != 0) {
|
|
Packit |
8480eb |
fprintf(stderr, "%s: this program must be run by root.\n",
|
|
Packit |
8480eb |
program);
|
|
Packit |
8480eb |
exit(1);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Remove the options */
|
|
Packit |
8480eb |
argv += optind;
|
|
Packit |
8480eb |
argc -= optind;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (logpri >= 0) {
|
|
Packit |
8480eb |
int exit_code = 0;
|
|
Packit |
8480eb |
int i;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* The remaining argv elements are the paths for which
|
|
Packit |
8480eb |
* log priorities must be changed.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
for (i = 0; i < argc; i++) {
|
|
Packit |
8480eb |
if (set_log_priority(argv[i], logpri) < 0)
|
|
Packit |
8480eb |
exit_code = 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (argc < 1) {
|
|
Packit |
8480eb |
fprintf(stderr,
|
|
Packit |
8480eb |
"--set-log-priority requires a path.\n");
|
|
Packit |
8480eb |
exit_code = 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
exit(exit_code);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit Service |
42268b |
#if 0
|
|
Packit Service |
42268b |
if (!load_autofs4_module()) {
|
|
Packit Service |
42268b |
fprintf(stderr, "%s: can't load %s filesystem module.\n",
|
|
Packit Service |
42268b |
program, FS_MODULE_NAME);
|
|
Packit Service |
42268b |
exit(1);
|
|
Packit Service |
42268b |
}
|
|
Packit Service |
42268b |
#endif
|
|
Packit Service |
42268b |
|
|
Packit |
8480eb |
/* Don't need the kernel module just to look at the configured maps */
|
|
Packit Service |
42268b |
if (!dumpmaps && (!query_kproto_ver() || get_kver_major() < 5)) {
|
|
Packit |
8480eb |
fprintf(stderr,
|
|
Packit |
8480eb |
"%s: test mount forbidden or "
|
|
Packit |
8480eb |
"incorrect kernel protocol version, "
|
|
Packit |
8480eb |
"kernel protocol version 5.00 or above required.\n",
|
|
Packit |
8480eb |
program);
|
|
Packit |
8480eb |
exit(1);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
res = getrlimit(RLIMIT_NOFILE, &rlim);
|
|
Packit |
8480eb |
if (res == -1 || rlim.rlim_max <= MAX_OPEN_FILES) {
|
|
Packit |
8480eb |
rlim.rlim_cur = MAX_OPEN_FILES;
|
|
Packit |
8480eb |
rlim.rlim_max = MAX_OPEN_FILES;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
res = setrlimit(RLIMIT_NOFILE, &rlim);
|
|
Packit |
8480eb |
if (res)
|
|
Packit |
8480eb |
printf("%s: can't increase open file limit - continuing",
|
|
Packit |
8480eb |
program);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#if ENABLE_CORES
|
|
Packit |
8480eb |
rlim.rlim_cur = RLIM_INFINITY;
|
|
Packit |
8480eb |
rlim.rlim_max = RLIM_INFINITY;
|
|
Packit |
8480eb |
res = setrlimit(RLIMIT_CORE, &rlim);
|
|
Packit |
8480eb |
if (res)
|
|
Packit |
8480eb |
printf("%s: can't increase core file limit - continuing",
|
|
Packit |
8480eb |
program);
|
|
Packit |
8480eb |
#endif
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Get processor information for predefined escapes */
|
|
Packit |
8480eb |
macro_init();
|
|
Packit |
8480eb |
|
|
Packit Service |
42268b |
if (dumpmaps) {
|
|
Packit |
8480eb |
struct master_mapent *entry;
|
|
Packit |
8480eb |
struct list_head *head, *p;
|
|
Packit |
8480eb |
struct mapent_cache *nc;
|
|
Packit |
8480eb |
const char *type = NULL;
|
|
Packit |
8480eb |
const char *name = NULL;
|
|
Packit |
8480eb |
const char *master = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (argc > 0) {
|
|
Packit |
8480eb |
if (argc >= 2) {
|
|
Packit |
8480eb |
type = argv[0];
|
|
Packit |
8480eb |
name = argv[1];
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (argc == 3)
|
|
Packit |
8480eb |
master = argv[2];
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (master)
|
|
Packit Service |
42268b |
master_list = master_new(NULL, timeout, ghost);
|
|
Packit |
8480eb |
else
|
|
Packit Service |
42268b |
master_list = master_new(master, timeout, ghost);
|
|
Packit |
8480eb |
if (!master_list) {
|
|
Packit |
8480eb |
printf("%s: can't create master map", program);
|
|
Packit |
8480eb |
macro_free_global_table();
|
|
Packit |
8480eb |
exit(1);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
log_to_stderr();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_init_scan();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
nc = cache_init_null_cache(master_list);
|
|
Packit |
8480eb |
if (!nc) {
|
|
Packit |
8480eb |
printf("%s: failed to init null map cache for %s",
|
|
Packit |
8480eb |
program, master_list->name);
|
|
Packit |
8480eb |
macro_free_global_table();
|
|
Packit |
8480eb |
exit(1);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
master_list->nc = nc;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
lookup_nss_read_master(master_list, 0);
|
|
Packit |
8480eb |
if (type) {
|
|
Packit |
8480eb |
const char *map = basename(name);
|
|
Packit |
8480eb |
if (!map)
|
|
Packit |
8480eb |
printf("%s: invalid map name %s\n",
|
|
Packit |
8480eb |
program, name);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
dump_map(master_list, type, map);
|
|
Packit |
8480eb |
} else
|
|
Packit |
8480eb |
master_show_mounts(master_list);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
head = &master_list->mounts;
|
|
Packit |
8480eb |
p = head->next;
|
|
Packit |
8480eb |
while (p != head) {
|
|
Packit |
8480eb |
entry = list_entry(p, struct master_mapent, list);
|
|
Packit |
8480eb |
p = p->next;
|
|
Packit |
8480eb |
master_free_mapent_sources(entry, 1);
|
|
Packit |
8480eb |
master_free_mapent(entry);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
master_kill(master_list);
|
|
Packit |
8480eb |
macro_free_global_table();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
exit(0);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (argc == 0)
|
|
Packit Service |
42268b |
master_list = master_new(NULL, timeout, ghost);
|
|
Packit |
8480eb |
else
|
|
Packit Service |
42268b |
master_list = master_new(argv[0], timeout, ghost);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!master_list) {
|
|
Packit |
8480eb |
printf("%s: can't create master map %s", program, argv[0]);
|
|
Packit |
8480eb |
macro_free_global_table();
|
|
Packit |
8480eb |
exit(1);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit Service |
42268b |
become_daemon(foreground, daemon_check);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (pthread_attr_init(&th_attr)) {
|
|
Packit |
8480eb |
logerr("%s: failed to init thread attribute struct!",
|
|
Packit |
8480eb |
program);
|
|
Packit Service |
b3e495 |
if (start_pipefd[1] != -1) {
|
|
Packit Service |
b3e495 |
res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
|
|
Packit Service |
b3e495 |
close(start_pipefd[1]);
|
|
Packit Service |
b3e495 |
}
|
|
Packit |
8480eb |
release_flag_file();
|
|
Packit |
8480eb |
macro_free_global_table();
|
|
Packit |
8480eb |
exit(1);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (pthread_attr_init(&th_attr_detached)) {
|
|
Packit |
8480eb |
logerr("%s: failed to init thread attribute struct!",
|
|
Packit |
8480eb |
program);
|
|
Packit Service |
b3e495 |
if (start_pipefd[1] != -1) {
|
|
Packit Service |
b3e495 |
res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
|
|
Packit Service |
b3e495 |
close(start_pipefd[1]);
|
|
Packit Service |
b3e495 |
}
|
|
Packit |
8480eb |
release_flag_file();
|
|
Packit |
8480eb |
macro_free_global_table();
|
|
Packit |
8480eb |
exit(1);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (pthread_attr_setdetachstate(
|
|
Packit |
8480eb |
&th_attr_detached, PTHREAD_CREATE_DETACHED)) {
|
|
Packit |
8480eb |
logerr("%s: failed to set detached thread attribute!",
|
|
Packit |
8480eb |
program);
|
|
Packit Service |
b3e495 |
if (start_pipefd[1] != -1) {
|
|
Packit Service |
b3e495 |
res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
|
|
Packit Service |
b3e495 |
close(start_pipefd[1]);
|
|
Packit Service |
b3e495 |
}
|
|
Packit |
8480eb |
release_flag_file();
|
|
Packit |
8480eb |
macro_free_global_table();
|
|
Packit |
8480eb |
exit(1);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#ifdef _POSIX_THREAD_ATTR_STACKSIZE
|
|
Packit |
8480eb |
if (pthread_attr_setstacksize(
|
|
Packit |
8480eb |
&th_attr_detached, detached_thread_stack_size)) {
|
|
Packit |
8480eb |
logerr("%s: failed to set stack size thread attribute!",
|
|
Packit |
8480eb |
program);
|
|
Packit Service |
b3e495 |
if (start_pipefd[1] != -1) {
|
|
Packit Service |
b3e495 |
res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
|
|
Packit Service |
b3e495 |
close(start_pipefd[1]);
|
|
Packit Service |
b3e495 |
}
|
|
Packit |
8480eb |
release_flag_file();
|
|
Packit |
8480eb |
macro_free_global_table();
|
|
Packit |
8480eb |
exit(1);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
#endif
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (pthread_attr_getstacksize(
|
|
Packit |
8480eb |
&th_attr_detached, &detached_thread_stack_size)) {
|
|
Packit |
8480eb |
logerr("%s: failed to get detached thread stack size!",
|
|
Packit |
8480eb |
program);
|
|
Packit Service |
b3e495 |
if (start_pipefd[1] != -1) {
|
|
Packit Service |
b3e495 |
res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
|
|
Packit Service |
b3e495 |
close(start_pipefd[1]);
|
|
Packit Service |
b3e495 |
}
|
|
Packit |
8480eb |
release_flag_file();
|
|
Packit |
8480eb |
macro_free_global_table();
|
|
Packit |
8480eb |
exit(1);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
info(logging, "Starting automounter version %s, master map %s",
|
|
Packit |
8480eb |
version, master_list->name);
|
|
Packit |
8480eb |
info(logging, "using kernel protocol version %d.%02d",
|
|
Packit |
8480eb |
get_kver_major(), get_kver_minor());
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_key_create(&key_thread_stdenv_vars,
|
|
Packit |
8480eb |
key_thread_stdenv_vars_destroy);
|
|
Packit |
8480eb |
if (status) {
|
|
Packit |
8480eb |
logerr("%s: failed to create thread data key for std env vars!",
|
|
Packit |
8480eb |
program);
|
|
Packit |
8480eb |
master_kill(master_list);
|
|
Packit Service |
b3e495 |
if (start_pipefd[1] != -1) {
|
|
Packit Service |
b3e495 |
res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
|
|
Packit Service |
b3e495 |
close(start_pipefd[1]);
|
|
Packit Service |
b3e495 |
}
|
|
Packit |
8480eb |
release_flag_file();
|
|
Packit |
8480eb |
macro_free_global_table();
|
|
Packit |
8480eb |
exit(1);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_key_create(&key_thread_attempt_id, free);
|
|
Packit |
8480eb |
if (status) {
|
|
Packit |
8480eb |
logerr("%s: failed to create thread data key for attempt ID!",
|
|
Packit |
8480eb |
program);
|
|
Packit |
8480eb |
master_kill(master_list);
|
|
Packit Service |
b3e495 |
if (start_pipefd[1] != -1) {
|
|
Packit Service |
b3e495 |
res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
|
|
Packit Service |
b3e495 |
close(start_pipefd[1]);
|
|
Packit Service |
b3e495 |
}
|
|
Packit |
8480eb |
release_flag_file();
|
|
Packit |
8480eb |
macro_free_global_table();
|
|
Packit |
8480eb |
exit(1);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
init_ioctl_ctl();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!alarm_start_handler()) {
|
|
Packit |
8480eb |
logerr("%s: failed to create alarm handler thread!", program);
|
|
Packit |
8480eb |
master_kill(master_list);
|
|
Packit Service |
b3e495 |
if (start_pipefd[1] != -1) {
|
|
Packit Service |
b3e495 |
res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
|
|
Packit Service |
b3e495 |
close(start_pipefd[1]);
|
|
Packit Service |
b3e495 |
}
|
|
Packit |
8480eb |
release_flag_file();
|
|
Packit |
8480eb |
macro_free_global_table();
|
|
Packit |
8480eb |
exit(1);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!st_start_handler()) {
|
|
Packit |
8480eb |
logerr("%s: failed to create FSM handler thread!", program);
|
|
Packit |
8480eb |
master_kill(master_list);
|
|
Packit Service |
b3e495 |
if (start_pipefd[1] != -1) {
|
|
Packit Service |
b3e495 |
res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
|
|
Packit Service |
b3e495 |
close(start_pipefd[1]);
|
|
Packit Service |
b3e495 |
}
|
|
Packit |
8480eb |
release_flag_file();
|
|
Packit |
8480eb |
macro_free_global_table();
|
|
Packit |
8480eb |
exit(1);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#if defined(WITH_LDAP) && defined(LIBXML2_WORKAROUND)
|
|
Packit |
8480eb |
void *dh_xml2 = dlopen("libxml2.so", RTLD_NOW);
|
|
Packit |
8480eb |
if (!dh_xml2)
|
|
Packit |
8480eb |
dh_xml2 = dlopen("libxml2.so.2", RTLD_NOW);
|
|
Packit |
8480eb |
if (dh_xml2)
|
|
Packit |
8480eb |
xmlInitParser();
|
|
Packit |
8480eb |
#endif
|
|
Packit |
8480eb |
#ifdef TIRPC_WORKAROUND
|
|
Packit |
8480eb |
void *dh_tirpc = dlopen("libtirpc.so", RTLD_NOW);
|
|
Packit |
8480eb |
if (!dh_tirpc)
|
|
Packit |
8480eb |
dh_tirpc = dlopen("libtirpc.so.1", RTLD_NOW);
|
|
Packit |
8480eb |
if (!dh_tirpc)
|
|
Packit |
8480eb |
dh_tirpc = dlopen("libtirpc.so.3", RTLD_NOW);
|
|
Packit |
8480eb |
#endif
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_read = master_read_master(master_list, age, 0);
|
|
Packit |
8480eb |
if (!master_read) {
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Read master map, waiting until it is available, unless
|
|
Packit |
8480eb |
* a signal is received, in which case exit returning an
|
|
Packit |
8480eb |
* error.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (!do_master_read_master(master_list, master_wait)) {
|
|
Packit |
8480eb |
logmsg("%s: warning: could not read at least one "
|
|
Packit |
8480eb |
"map source after waiting, continuing ...",
|
|
Packit |
8480eb |
program);
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Failed to read master map, continue with what
|
|
Packit |
8480eb |
* we have anyway.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
do_master_list_reset(master_list);
|
|
Packit Service |
42268b |
age = time(NULL);
|
|
Packit |
8480eb |
master_read_master(master_list, age, 1);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit Service |
42268b |
/*
|
|
Packit Service |
42268b |
* Mmm ... reset force unlink umount so we don't also do this
|
|
Packit Service |
42268b |
* in future when we receive a HUP signal.
|
|
Packit Service |
25eead |
*/
|
|
Packit Service |
42268b |
do_force_unlink = 0;
|
|
Packit |
8480eb |
|
|
Packit Service |
b3e495 |
if (start_pipefd[1] != -1) {
|
|
Packit Service |
b3e495 |
st_stat = 0;
|
|
Packit Service |
b3e495 |
res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
|
|
Packit Service |
b3e495 |
close(start_pipefd[1]);
|
|
Packit Service |
b3e495 |
}
|
|
Packit Service |
b3e495 |
|
|
Packit Service |
b3e495 |
#ifdef WITH_SYSTEMD
|
|
Packit Service |
b3e495 |
sd_notify(1, "READY=1");
|
|
Packit Service |
b3e495 |
#endif
|
|
Packit Service |
85fdcd |
|
|
Packit Service |
42268b |
state_mach_thid = pthread_self();
|
|
Packit Service |
42268b |
statemachine(NULL);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_kill(master_list);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (pid_file) {
|
|
Packit |
8480eb |
unlink(pid_file);
|
|
Packit |
8480eb |
pid_file = NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
defaults_conf_release();
|
|
Packit |
8480eb |
closelog();
|
|
Packit |
8480eb |
release_flag_file();
|
|
Packit |
8480eb |
macro_free_global_table();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#ifdef TIRPC_WORKAROUND
|
|
Packit |
8480eb |
if (dh_tirpc)
|
|
Packit |
8480eb |
dlclose(dh_tirpc);
|
|
Packit |
8480eb |
#endif
|
|
Packit |
8480eb |
#if defined(WITH_LDAP) && defined( LIBXML2_WORKAROUND)
|
|
Packit |
8480eb |
if (dh_xml2) {
|
|
Packit |
8480eb |
xmlCleanupParser();
|
|
Packit |
8480eb |
dlclose(dh_xml2);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
#endif
|
|
Packit |
8480eb |
close_ioctl_ctl();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
info(logging, "autofs stopped");
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
exit(0);
|
|
Packit |
8480eb |
}
|