static int32_t server_start(proxy_manager_t *manager)
{
proxy_server_t server;
+ struct stat st;
proxy_t *proxy;
+ const char *path;
+ char *wd;
+ int32_t err;
proxy = container_of(manager, proxy_t, manager);
server.manager = manager;
server.settings = &proxy->settings;
- return proxy_link_server(&server.link, &proxy->settings,
- accept_connection, check_stop);
+ path = proxy->settings.work_dir;
+ wd = realpath(path, NULL);
+ if (wd == NULL) {
+ return proxy_log(LOG_ERR, errno,
+ "Failed to resolve the working directory");
+ }
+
+ if (stat(wd, &st) < 0) {
+ err = proxy_log(LOG_ERR, errno,
+ "Failed to check the working directory");
+ goto done;
+ }
+
+ if (!S_ISDIR(st.st_mode)) {
+ err = proxy_log(LOG_ERR, EINVAL,
+ "The provided path for the working directory "
+ "is not a directory");
+ goto done;
+ }
+
+ proxy->settings.work_dir = wd;
+
+ err = proxy_link_server(&server.link, &proxy->settings,
+ accept_connection, check_stop);
+
+ proxy->settings.work_dir = path;
+
+done:
+ free(wd);
+
+ return err;
}
static void log_format(struct iovec *iov, char *buffer, size_t size,
}
static struct option main_opts[] = {
- {"socket", required_argument, NULL, 's'},
+ {"socket", required_argument, NULL, 's'},
+ {"work-dir", required_argument, NULL, 'w'},
{}
};
+static const char short_opts[] = ":s:w:";
+
int32_t main(int32_t argc, char *argv[])
{
struct timespec now;
proxy_log_register(&proxy.log_handler, log_print);
proxy.settings.socket_path = PROXY_SOCKET;
+ proxy.settings.work_dir = ".";
env = getenv(PROXY_SOCKET_ENV);
if (env != NULL) {
proxy.settings.socket_path = env;
}
- while ((val = getopt_long(argc, argv, ":s:", main_opts, NULL)) >= 0) {
+ while ((val = getopt_long(argc, argv, short_opts, main_opts, NULL)) >= 0) {
if (val == 's') {
proxy.settings.socket_path = optarg;
+ } else if (val == 'w') {
+ proxy.settings.work_dir = optarg;
} else if (val == ':') {
proxy_log(LOG_ERR, ENODATA,
"Argument missing for '%s'\n", optopt);
return 1;
}
-static int32_t proxy_config_destination_prepare(void)
+static int32_t proxy_config_destination_prepare(proxy_settings_t *settings)
{
int32_t fd;
- fd = openat(AT_FDCWD, ".", O_TMPFILE | O_WRONLY, 0600);
+ fd = open(settings->work_dir, O_TMPFILE | O_WRONLY, 0600);
if (fd < 0) {
return proxy_log(LOG_ERR, errno, "openat() failed");
}
return size;
}
-static int32_t proxy_config_destination_commit(int32_t fd, const char *name)
+static int32_t proxy_config_destination_commit(proxy_settings_t *settings,
+ int32_t fd, const char *path)
{
- char path[32];
+ char fd_path[32];
int32_t len;
if (fsync(fd) < 0) {
return proxy_log(LOG_ERR, errno, "fsync() failed");
}
- if (linkat(fd, "", AT_FDCWD, name, AT_EMPTY_PATH) < 0) {
+ if (linkat(fd, "", AT_FDCWD, path, AT_EMPTY_PATH) < 0) {
if (errno == EEXIST) {
return 0;
}
* filesystem. */
}
- len = proxy_snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
+ len = proxy_snprintf(fd_path, sizeof(fd_path), "/proc/self/fd/%d", fd);
if (len < 0) {
return len;
}
- if (linkat(AT_FDCWD, path, AT_FDCWD, name, AT_SYMLINK_FOLLOW) < 0) {
+ if (linkat(AT_FDCWD, fd_path, AT_FDCWD, path, AT_SYMLINK_FOLLOW) < 0) {
if (errno != EEXIST) {
return proxy_log(LOG_ERR, errno, "linkat() failed");
}
/* Copies and checksums a given configuration to a file and makes sure that it
* has not been modified. */
-static int32_t proxy_config_prepare(const char *config, char *path,
+static int32_t proxy_config_prepare(proxy_settings_t *settings,
+ const char *config, char *path,
int32_t size)
{
char hash[65];
goto done_mem;
}
- cfg.dst = proxy_config_destination_prepare();
+ cfg.dst = proxy_config_destination_prepare(settings);
if (cfg.dst < 0) {
err = cfg.dst;
goto done_src;
goto done_dst;
}
- err = proxy_snprintf(path, size, "ceph-%s.conf", hash);
+ err = proxy_snprintf(path, size, "%s/ceph-%s.conf", settings->work_dir,
+ hash);
if (err < 0) {
goto done_dst;
}
- err = proxy_config_destination_commit(cfg.dst, path);
+ err = proxy_config_destination_commit(settings, cfg.dst, path);
done_dst:
proxy_config_destination_close(cfg.dst);
static int32_t proxy_instance_config(proxy_instance_t *instance,
const char *config)
{
- char path[128], *ppath;
+ char path[strlen(instance->settings->work_dir) + 128], *ppath;
int32_t err;
if (instance->mounted) {
ppath = NULL;
if (config != NULL) {
- err = proxy_config_prepare(config, path, sizeof(path));
+ err = proxy_config_prepare(instance->settings, config, path,
+ sizeof(path));
if (err < 0) {
return err;
}