static void check_wrong_config(const char *config_path)
{
- const char *base_dir, *symlink_path, *prev_path;
+ const char *base_dir, *symlink_path, *prev_path, *error;
base_dir = get_setting("master", "base_dir");
symlink_path = t_strconcat(base_dir, "/"PACKAGE".conf", NULL);
- if (t_readlink(symlink_path, &prev_path) < 0)
+ if (t_readlink(symlink_path, &prev_path, &error) < 0) {
+ i_error("t_readlink(%s) failed: %s", symlink_path, error);
return;
+ }
if (strcmp(prev_path, config_path) != 0) {
i_warning("Dovecot was last started using %s, "
master_instance_update_config_path(struct master_instance_list *list,
struct master_instance *inst)
{
- const char *path, *config_path;
+ const char *path, *config_path, *error;
/* update instance's config path if it has changed */
path = t_strconcat(inst->base_dir, "/"PACKAGE".conf", NULL);
- if (t_readlink(path, &config_path) == 0) {
- if (null_strcmp(inst->config_path, config_path) != 0) {
- inst->config_path = p_strdup(list->pool, config_path);
- list->config_paths_changed = TRUE;
- }
+ if (t_readlink(path, &config_path, &error) < 0) {
+ i_error("t_readlink(%s) failed: %s", path, error);
+ return;
+ }
+ if (null_strcmp(inst->config_path, config_path) != 0) {
+ inst->config_path = p_strdup(list->pool, config_path);
+ list->config_paths_changed = TRUE;
}
}
inst = master_instance_list_find_by_name(list, name);
if (inst != NULL) {
path = t_strdup_printf("%s/dovecot.conf", inst->base_dir);
- if (t_readlink(path, config_path_r) < 0)
- i_fatal("readlink(%s) failed: %m", path);
+ const char *error;
+ if (t_readlink(path, config_path_r, &error) < 0)
+ i_fatal("t_readlink(%s) failed: %s", path, error);
}
master_instance_list_deinit(&list);
return inst != NULL;
dbox_alt_path_has_changed(const char *root_dir, const char *alt_path,
const char *alt_path2, const char *alt_symlink_path)
{
- const char *linkpath;
+ const char *linkpath, *error;
- if (t_readlink(alt_symlink_path, &linkpath) < 0) {
+ if (t_readlink(alt_symlink_path, &linkpath, &error) < 0) {
if (errno == ENOENT)
return alt_path != NULL;
- i_error("readlink(%s) failed: %m", alt_symlink_path);
+ i_error("t_readlink(%s) failed: %s", alt_symlink_path, error);
return FALSE;
}
return 1;
T_BEGIN {
- const char *path, *linkpath;
+ const char *path, *linkpath, *error;
path = t_strconcat(dir_path, "/", d->d_name, NULL);
if (lstat(path, &st) < 0) {
ret = -1;
} else if (!S_ISLNK(st.st_mode)) {
ret = 0;
- } else if (t_readlink(path, &linkpath) < 0) {
- i_error("readlink(%s) failed: %m", path);
+ } else if (t_readlink(path, &linkpath, &error) < 0) {
+ i_error("t_readlink(%s) failed: %s", path, error);
ret = -1;
} else {
/* it's an alias only if it points to the same
return 0;
}
-int t_readlink(const char *path, const char **dest_r)
+int t_readlink(const char *path, const char **dest_r, const char **error_r)
{
+ i_assert(error_r != NULL);
+
/* @UNSAFE */
ssize_t ret;
char *dest;
size = nearest_power(size+1);
dest = t_buffer_get(size);
}
- if (ret < 0)
+ if (ret < 0) {
+ *error_r = t_strdup_printf("readlink() failed: %m");
return -1;
+ }
dest[ret] = '\0';
t_buffer_alloc(ret + 1);
#define PATH_UTIL_H
/* Returns path as absolute path. If it's not already absolute path,
- it's assumed to be relative to current working directory. */
+ * it's assumed to be relative to current working directory.
+ *
+ * In the t_abspath functions, the returned paths are not normalized. This
+ * means that './' and '../' are not resolved, but they left in the returned
+ * path as given in the parameters. Symbolic links are not resolved either.
+ */
const char *t_abspath(const char *path);
/* Like t_abspath(), but path is relative to given root. */
const char *t_abspath_to(const char *path, const char *root);
/* Returns current directory, allocated from data stack. */
int t_get_current_dir(const char **dir_r);
-/* Returns symlink destination, allocated from data stack. */
-int t_readlink(const char *path, const char **dest_r);
+
+/* Get symlink destination allocated from data stack. Returns 0 on success and
+ * -1 on failure. error_r is set on failure and cannot be NULL. */
+int t_readlink(const char *path, const char **dest_r, const char **error_r);
/* Update binpath to be absolute:
a) begins with '/' -> no change