+++ /dev/null
-/* Copyright (c) 2013-2016 Dovecot authors, see the included COPYING file */
-
-#include "lib.h"
-#include "master-service-settings.h"
-#include "mountpoint-list.h"
-#include "doveadm.h"
-#include "doveadm-print.h"
-
-extern struct doveadm_cmd doveadm_cmd_mount[];
-
-static void mount_cmd_help(doveadm_command_t *cmd) ATTR_NORETURN;
-
-static struct mountpoint_list *mountpoint_list_get(void)
-{
- const char *perm_path, *state_path;
-
- perm_path = t_strconcat(service_set->state_dir,
- "/"MOUNTPOINT_LIST_FNAME, NULL);
- state_path = t_strconcat(service_set->base_dir,
- "/"MOUNTPOINT_LIST_FNAME, NULL);
- return mountpoint_list_init(perm_path, state_path);
-}
-
-static void cmd_mount_list(int argc, char *argv[])
-{
- struct mountpoint_list *mountpoints;
- struct mountpoint_list_iter *iter;
- struct mountpoint_list_rec *rec;
- bool mounts_known;
-
- if (argc > 2)
- mount_cmd_help(cmd_mount_list);
-
- doveadm_print_init(DOVEADM_PRINT_TYPE_TABLE);
- doveadm_print_header_simple(" ");
- doveadm_print_header("path", "path", DOVEADM_PRINT_HEADER_FLAG_EXPAND);
- doveadm_print_header_simple("state");
-
- mountpoints = mountpoint_list_get();
- mounts_known = mountpoint_list_update_mounted(mountpoints) == 0;
- iter = mountpoint_list_iter_init(mountpoints);
- while ((rec = mountpoint_list_iter_next(iter)) != NULL) {
- if (argv[1] != NULL && strcmp(argv[1], rec->mount_path) != 0)
- continue;
-
- if (mounts_known && MOUNTPOINT_WRONGLY_NOT_MOUNTED(rec))
- doveadm_print("!");
- else
- doveadm_print(" ");
- doveadm_print(!rec->wildcard ? rec->mount_path :
- t_strconcat(rec->mount_path, "*", NULL));
-
- doveadm_print(rec->state);
- }
- mountpoint_list_iter_deinit(&iter);
- mountpoint_list_deinit(&mountpoints);
-}
-
-static bool mount_path_get_wildcard(const char **path)
-{
- unsigned int len;
-
- len = strlen(*path);
- if (len > 0 && (*path)[len-1] == '*') {
- *path = t_strndup(*path, len-1);
- return TRUE;
- } else {
- return FALSE;
- }
-}
-
-static void cmd_mount_add(int argc, char *argv[])
-{
- struct mountpoint_list *mountpoints;
- struct mountpoint_list_rec rec;
- int ret = 0;
-
- if (argc > 3)
- mount_cmd_help(cmd_mount_add);
-
- mountpoints = mountpoint_list_get();
- if (argv[1] == NULL) {
- ret = mountpoint_list_add_missing(mountpoints,
- MOUNTPOINT_STATE_DEFAULT,
- mountpoint_list_default_ignore_prefixes,
- mountpoint_list_default_ignore_types);
- } else {
- memset(&rec, 0, sizeof(rec));
- rec.mount_path = argv[1];
- rec.state = argv[2] != NULL ? argv[2] :
- MOUNTPOINT_STATE_DEFAULT;
-
- if (mount_path_get_wildcard(&rec.mount_path))
- rec.wildcard = TRUE;
- mountpoint_list_add(mountpoints, &rec);
- }
- if (mountpoint_list_save(mountpoints) < 0)
- ret = -1;
- mountpoint_list_deinit(&mountpoints);
- if (ret < 0)
- doveadm_exit_code = EX_TEMPFAIL;
-}
-
-static void cmd_mount_remove(int argc, char *argv[])
-{
- struct mountpoint_list *mountpoints;
- const char *mount_path;
-
- if (argc != 2)
- mount_cmd_help(cmd_mount_remove);
-
- mount_path = argv[1];
- (void)mount_path_get_wildcard(&mount_path);
-
- mountpoints = mountpoint_list_get();
- if (!mountpoint_list_remove(mountpoints, mount_path))
- i_error("Mountpoint not found: %s", mount_path);
- else
- (void)mountpoint_list_save(mountpoints);
- mountpoint_list_deinit(&mountpoints);
-}
-
-struct doveadm_cmd doveadm_cmd_mount[] = {
- { cmd_mount_list, "mount list", "[<path>]" },
- { cmd_mount_add, "mount add", "[<path> [<state>]]" },
- { cmd_mount_remove, "mount remove", "<path>" }
-};
-
-static void mount_cmd_help(doveadm_command_t *cmd)
-{
- unsigned int i;
-
- for (i = 0; i < N_ELEMENTS(doveadm_cmd_mount); i++) {
- if (doveadm_cmd_mount[i].cmd == cmd)
- help(&doveadm_cmd_mount[i]);
- }
- i_unreached();
-}
-
-void doveadm_register_mount_commands(void)
-{
- unsigned int i;
-
- for (i = 0; i < N_ELEMENTS(doveadm_cmd_mount); i++)
- doveadm_register_cmd(&doveadm_cmd_mount[i]);
-}
+++ /dev/null
-/* Copyright (c) 2013-2016 Dovecot authors, see the included COPYING file */
-
-#include "lib.h"
-#include "array.h"
-#include "istream.h"
-#include "file-copy.h"
-#include "safe-mkstemp.h"
-#include "str.h"
-#include "write-full.h"
-#include "mountpoint.h"
-#include "mountpoint-list.h"
-
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-struct mountpoint_list {
- pool_t pool;
- const char *perm_path, *state_path;
- ARRAY(struct mountpoint_list_rec *) recs;
- struct stat load_st;
- bool load_failed;
-};
-
-struct mountpoint_list_iter {
- struct mountpoint_list *list;
- unsigned int idx;
-};
-
-const char *const mountpoint_list_default_ignore_types[] = {
- "proc", /* Linux, Solaris */
- "procfs", /* AIX, BSD */
- "tmpfs", /* Linux */
- "sysfs", /* Linux */
- "debugfs", /* Linux */
- "securityfs", /* Linux */
- "devpts", /* Linux */
- "devtmpfs", /* Linux */
- "rpc_pipefs", /* Linux */
- "fusectl", /* Linux */
- "nfsd", /* Linux */
- "cgroup", /* Linux */
- "binfmt_misc", /* Linux */
- "devfs", /* Solaris, OSX, BSD */
- "ctfs", /* Solaris */
- "mntfs", /* Solaris */
- "objfs", /* Solaris */
- "sharefs", /* Solaris */
- "lofs", /* Solaris */
- "fd", /* Solaris */
- NULL
-};
-
-const char *const mountpoint_list_default_ignore_prefixes[] = {
- "/cdrom",
- "/media",
- "/sys",
- "/proc",
- "/var/run",
- "/var/tmp",
- "/tmp",
- "/run",
-#ifdef __APPLE__
- "/Volumes",
- "/private/tmp",
-#endif
- NULL
-};
-
-static struct mountpoint_list * ATTR_NULL(1)
-mountpoint_list_init_internal(const char *perm_path, const char *state_path)
-{
- struct mountpoint_list *list;
- pool_t pool;
-
- pool = pool_alloconly_create("mountpoint list", 1024);
- list = p_new(pool, struct mountpoint_list, 1);
- list->pool = pool;
- list->perm_path = p_strdup(pool, perm_path);
- list->state_path = p_strdup(pool, state_path);
- p_array_init(&list->recs, pool, 16);
-
- (void)mountpoint_list_refresh(list);
- return list;
-}
-
-struct mountpoint_list *
-mountpoint_list_init(const char *perm_path, const char *state_path)
-{
- return mountpoint_list_init_internal(perm_path, state_path);
-}
-
-struct mountpoint_list *
-mountpoint_list_init_readonly(const char *state_path)
-{
- return mountpoint_list_init_internal(NULL, state_path);
-}
-
-void mountpoint_list_deinit(struct mountpoint_list **_list)
-{
- struct mountpoint_list *list = *_list;
-
- *_list = NULL;
- pool_unref(&list->pool);
-}
-
-static int mountpoint_list_load(struct mountpoint_list *list)
-{
- struct mountpoint_list_rec rec;
- struct istream *input;
- char *p, *line;
- unsigned int len;
- int fd, ret = 0;
-
- memset(&rec, 0, sizeof(rec));
-
- fd = open(list->state_path, O_RDONLY);
- if (fd == -1) {
- if (errno != ENOENT) {
- i_error("open(%s) failed: %m", list->state_path);
- return -1;
- }
- if (list->perm_path == NULL) {
- /* we're in read-only mode */
- return 0;
- }
- if (file_copy(list->perm_path, list->state_path, FALSE) < 0)
- return -1;
- fd = open(list->perm_path, O_RDONLY);
- if (fd == -1) {
- if (errno == ENOENT) {
- /* perm_path didn't exist either */
- return 0;
- }
- i_error("open(%s) failed: %m", list->state_path);
- return -1;
- }
- }
- if (fstat(fd, &list->load_st) < 0)
- i_error("fstat(%s) failed: %m", list->state_path);
- input = i_stream_create_fd_autoclose(&fd, (size_t)-1);
- while ((line = i_stream_read_next_line(input)) != NULL) {
- p = strchr(line, ' ');
- if (p == NULL) {
- i_error("Corrupted line in %s: %s",
- list->state_path, line);
- ret = -1;
- break;
- }
- *p++ = '\0';
- rec.mount_path = p;
- rec.state = line;
- len = strlen(p);
- if (len > 0 && p[len-1] == '*') {
- p[len-1] = '\0';
- rec.wildcard = TRUE;
- }
- mountpoint_list_add(list, &rec);
- }
- if (input->stream_errno != 0) {
- i_error("read(%s) failed: %m", list->state_path);
- ret = -1;
- }
- i_stream_destroy(&input);
- return ret;
-}
-
-int mountpoint_list_refresh(struct mountpoint_list *list)
-{
- struct stat st;
-
- if (list->load_st.st_mtime != 0) {
- if (stat(list->state_path, &st) < 0) {
- if (errno == ENOENT)
- return 0;
- i_error("stat(%s) failed: %m", list->state_path);
- return -1;
- }
- if (st.st_mtime == list->load_st.st_mtime &&
- ST_MTIME_NSEC(st) == ST_MTIME_NSEC(list->load_st) &&
- st.st_ino == list->load_st.st_ino) {
- /* unchanged */
- return 0;
- }
- }
- array_clear(&list->recs);
- return mountpoint_list_load(list);
-}
-
-static int
-mountpoint_list_save_to(struct mountpoint_list *list, const char *path)
-{
- struct mountpoint_list_rec *const *recp;
- string_t *data, *temp_path = t_str_new(128);
- int fd;
-
- str_append(temp_path, path);
- str_append(temp_path, ".tmp.");
- fd = safe_mkstemp(temp_path, 0644, (uid_t)-1, (gid_t)-1);
- if (fd == -1) {
- i_error("safe_mkstemp(%s) failed: %m", str_c(temp_path));
- return -1;
- }
- data = t_str_new(256);
- array_foreach(&list->recs, recp) {
- str_append(data, (*recp)->state);
- str_append_c(data, ' ');
- str_append(data, (*recp)->mount_path);
- if ((*recp)->wildcard)
- str_append_c(data, '*');
- str_append_c(data, '\n');
- }
- if (write_full(fd, str_data(data), str_len(data)) < 0) {
- i_error("write(%s) failed: %m", str_c(temp_path));
- i_close_fd(&fd);
- } else if (fdatasync(fd) < 0) {
- i_error("fdatasync(%s) failed: %m", str_c(temp_path));
- i_close_fd(&fd);
- } else if (close(fd) < 0) {
- i_error("close(%s) failed: %m", str_c(temp_path));
- } else if (rename(str_c(temp_path), path) < 0) {
- i_error("rename(%s, %s) failed: %m", str_c(temp_path), path);
- } else {
- return 0;
- }
- i_unlink(str_c(temp_path));
- return -1;
-}
-
-int mountpoint_list_save(struct mountpoint_list *list)
-{
- int ret;
-
- i_assert(list->perm_path != NULL);
-
- if (list->load_failed)
- return -1;
-
- ret = mountpoint_list_save_to(list, list->state_path);
- if (mountpoint_list_save_to(list, list->perm_path) < 0)
- ret = -1;
- return ret;
-}
-
-void mountpoint_list_add(struct mountpoint_list *list,
- const struct mountpoint_list_rec *rec)
-{
- struct mountpoint_list_rec *new_rec;
-
- new_rec = mountpoint_list_find(list, rec->mount_path);
- if (new_rec == NULL) {
- new_rec = p_new(list->pool, struct mountpoint_list_rec, 1);
- new_rec->mount_path = p_strdup(list->pool, rec->mount_path);
- array_append(&list->recs, &new_rec, 1);
- }
- new_rec->state = p_strdup(list->pool, rec->state);
- new_rec->wildcard = rec->wildcard;
- new_rec->mounted = rec->mounted;
-}
-
-bool mountpoint_list_remove(struct mountpoint_list *list,
- const char *mount_path)
-{
- struct mountpoint_list_rec *const *recs;
- unsigned int i, count;
-
- recs = array_get(&list->recs, &count);
- for (i = 0; i < count; i++) {
- if (strcmp(recs[i]->mount_path, mount_path) == 0) {
- array_delete(&list->recs, i, 1);
- return TRUE;
- }
- }
- return FALSE;
-}
-
-static bool str_array_find_prefix(const char *const *prefixes, const char *str)
-{
- if (prefixes == NULL)
- return FALSE;
- for (; *prefixes != NULL; prefixes++) {
- if (strncmp(*prefixes, str, strlen(*prefixes)) == 0)
- return TRUE;
- }
- return FALSE;
-}
-
-int mountpoint_list_add_missing(struct mountpoint_list *list,
- const char *default_state,
- const char *const *ignore_prefixes,
- const char *const *ignore_types)
-{
- struct mountpoint_list_rec new_rec, *rec, *const *recp;
- struct mountpoint_iter *iter;
- const struct mountpoint *mnt;
-
- memset(&new_rec, 0, sizeof(new_rec));
- new_rec.state = default_state;
- new_rec.mounted = TRUE;
-
- array_foreach(&list->recs, recp)
- (*recp)->mounted = FALSE;
-
- /* get a sorted list of all current mountpoints */
- iter = mountpoint_iter_init();
- while ((mnt = mountpoint_iter_next(iter)) != NULL) {
- rec = mountpoint_list_find(list, mnt->mount_path);
- if (rec != NULL) {
- if (!rec->wildcard)
- rec->mounted = TRUE;
- } else if (!str_array_find(ignore_types, mnt->type) &&
- !str_array_find_prefix(ignore_prefixes,
- mnt->mount_path)) {
- new_rec.mount_path = mnt->mount_path;
- mountpoint_list_add(list, &new_rec);
- }
- }
- return mountpoint_iter_deinit(&iter);
-}
-
-int mountpoint_list_update_mounted(struct mountpoint_list *list)
-{
- struct mountpoint_list_rec *rec, *const *recp;
- struct mountpoint_iter *iter;
- const struct mountpoint *mnt;
-
- array_foreach(&list->recs, recp)
- (*recp)->mounted = FALSE;
-
- iter = mountpoint_iter_init();
- while ((mnt = mountpoint_iter_next(iter)) != NULL) {
- rec = mountpoint_list_find(list, mnt->mount_path);
- if (rec != NULL && !rec->wildcard)
- rec->mounted = TRUE;
- }
- return mountpoint_iter_deinit(&iter);
-}
-
-struct mountpoint_list_rec *
-mountpoint_list_find(struct mountpoint_list *list, const char *path)
-{
- struct mountpoint_list_rec **recp;
-
- array_foreach_modifiable(&list->recs, recp) {
- const char *prefix = (*recp)->mount_path;
- unsigned int prefix_len = strlen(prefix);
-
- if (strncmp(prefix, path, prefix_len) == 0 &&
- (path[prefix_len] == '/' || path[prefix_len] == '\0'))
- return *recp;
- }
- return NULL;
-}
-
-struct mountpoint_list_iter *
-mountpoint_list_iter_init(struct mountpoint_list *list)
-{
- struct mountpoint_list_iter *iter;
-
- iter = i_new(struct mountpoint_list_iter, 1);
- iter->list = list;
- return iter;
-}
-
-struct mountpoint_list_rec *
-mountpoint_list_iter_next(struct mountpoint_list_iter *iter)
-{
- struct mountpoint_list_rec *const *recp;
-
- if (iter->idx == array_count(&iter->list->recs))
- return NULL;
-
- recp = array_idx(&iter->list->recs, iter->idx++);
- return *recp;
-}
-
-void mountpoint_list_iter_deinit(struct mountpoint_list_iter **_iter)
-{
- struct mountpoint_list_iter *iter = *_iter;
-
- *_iter = NULL;
- i_free(iter);
-}
+++ /dev/null
-#ifndef MOUNTPOINT_LIST_H
-#define MOUNTPOINT_LIST_H
-
-#define MOUNTPOINT_LIST_FNAME "mounts"
-#define MOUNTPOINT_STATE_DEFAULT "online"
-#define MOUNTPOINT_STATE_IGNORE "ignore"
-
-#define MOUNTPOINT_WRONGLY_NOT_MOUNTED(rec) \
- (!(rec)->mounted && !(rec)->wildcard && \
- strcmp((rec)->state, MOUNTPOINT_STATE_IGNORE) != 0)
-
-struct mountpoint_list_rec {
- const char *mount_path;
- const char *state;
- /* _add_missing() skips all mountpoints below this mount_path */
- bool wildcard;
- /* TRUE, if _add_missing() saw this mount */
- bool mounted;
-};
-
-/* A default known good list of mountpoint types that don't contain emails
- (e.g. proc, tmpfs, etc.) */
-extern const char *const mountpoint_list_default_ignore_types[];
-/* A default known good list of directories which shouldn't contain emails
- (e.g. /media) */
-extern const char *const mountpoint_list_default_ignore_prefixes[];
-
-struct mountpoint_list *
-mountpoint_list_init(const char *perm_path, const char *state_path);
-struct mountpoint_list *
-mountpoint_list_init_readonly(const char *state_path);
-void mountpoint_list_deinit(struct mountpoint_list **list);
-
-/* Reload the mountpoints if they have changed. Returns 0 if ok,
- -1 if I/O error. */
-int mountpoint_list_refresh(struct mountpoint_list *list);
-/* Save the current list of mountpoints. Returns 0 if successful,
- -1 if I/O error. */
-int mountpoint_list_save(struct mountpoint_list *list);
-
-/* Add a mountpoint. If it already exists, replace the old one. */
-void mountpoint_list_add(struct mountpoint_list *list,
- const struct mountpoint_list_rec *rec);
-/* Remove a mountpoint. Returns TRUE if mountpoint was found and removed. */
-bool mountpoint_list_remove(struct mountpoint_list *list,
- const char *mount_path);
-/* Add all currently mounted missing mountpoints to the list and update all
- mountpoints' mounted state. The mountpoints that match existing wildcards
- aren't added. Mountpoints with paths under ignore_prefixes aren't added.
- Mountpoints with type in ignore_types list also aren't added.
- Returns 0 if we successfully iterated through all mountpoints, -1 if not. */
-int mountpoint_list_add_missing(struct mountpoint_list *list,
- const char *default_state,
- const char *const *ignore_prefixes,
- const char *const *ignore_types);
-/* Update "mounted" status for all mountpoints. */
-int mountpoint_list_update_mounted(struct mountpoint_list *list);
-
-/* Find a mountpoint record for given path. */
-struct mountpoint_list_rec *
-mountpoint_list_find(struct mountpoint_list *list, const char *path);
-
-/* Iterate through all mountpoints in the list. */
-struct mountpoint_list_iter *
-mountpoint_list_iter_init(struct mountpoint_list *list);
-struct mountpoint_list_rec *
-mountpoint_list_iter_next(struct mountpoint_list_iter *iter);
-void mountpoint_list_iter_deinit(struct mountpoint_list_iter **iter);
-
-#endif