aboutsummaryrefslogtreecommitdiffstats
path: root/pseudo_client.c
diff options
context:
space:
mode:
Diffstat (limited to 'pseudo_client.c')
-rw-r--r--pseudo_client.c130
1 files changed, 78 insertions, 52 deletions
diff --git a/pseudo_client.c b/pseudo_client.c
index d957116..5ada209 100644
--- a/pseudo_client.c
+++ b/pseudo_client.c
@@ -37,14 +37,16 @@
#include "pseudo_ipc.h"
#include "pseudo_client.h"
+static char *base_path(int dirfd, const char *path, int leave_last);
+
static int connect_fd = -1;
static int server_pid = 0;
int pseudo_dir_fd = -1;
+char *pseudo_cwd = 0;
+size_t pseudo_cwd_len;
static char **fd_paths = 0;
static int nfds = 0;
-static char cwdbuf[PATH_MAX * 2], *cwd;
-static int cwdlen = 0;
static int messages = 0;
static struct timeval message_time = { 0 };
static int pseudo_inited = 0;
@@ -75,13 +77,52 @@ pseudo_client_touchgid(void) {
setenv("PSEUDO_GIDS", gidbuf, 1);
}
+char *
+pseudo_root_path(const char *func, int line, int dirfd, const char *path, int leave_last) {
+ char *rc;
+ pseudo_antimagic();
+ rc = base_path(dirfd, path, leave_last);
+ pseudo_magic();
+ if (!rc) {
+ pseudo_diag("couldn't allocate absolute path for '%s'.\n",
+ path);
+ }
+ pseudo_debug(3, "root_path [%s, %d]: '%s' from '%s'\n",
+ func, line,
+ rc ? rc : "<nil>",
+ path ? path : "<nil>");
+ return rc;
+}
+
+int
+pseudo_client_getcwd(void) {
+ char *cwd;
+ cwd = malloc(pseudo_path_max());
+ if (!cwd) {
+ pseudo_diag("Can't allocate CWD buffer!\n");
+ return -1;
+ }
+ pseudo_debug(2, "getcwd: trying to find cwd.\n");
+ if (getcwd(cwd, pseudo_path_max())) {
+ /* cwd now holds a canonical path to current directory */
+ pseudo_cwd_len = strlen(cwd);
+ pseudo_debug(3, "getcwd okay: [%s] %d bytes\n", cwd, (int) pseudo_cwd_len);
+ free(pseudo_cwd);
+ pseudo_cwd = cwd;
+ return 0;
+ } else {
+ pseudo_diag("Can't get CWD: %s\n", strerror(errno));
+ return -1;
+ }
+}
+
static char *
fd_path(int fd) {
if (fd >= 0 && fd < nfds) {
return fd_paths[fd];
}
if (fd == AT_FDCWD) {
- return cwd;
+ return pseudo_cwd;
}
return 0;
}
@@ -130,8 +171,7 @@ pseudo_client_reset() {
close(connect_fd);
connect_fd = -1;
}
- cwd = getcwd(cwdbuf, PATH_MAX);
- cwdlen = strlen(cwd);
+ pseudo_client_getcwd();
if (!pseudo_inited) {
char *env;
@@ -551,39 +591,42 @@ pseudo_client_shutdown(void) {
static char *
base_path(int dirfd, const char *path, int leave_last) {
char *basepath = 0;
- size_t pathlen = -1;
- size_t baselen;
+ size_t baselen = 0;
char *newpath;
- if (dirfd != -1 && dirfd != AT_FDCWD) {
- if (dirfd >= 0) {
- basepath = fd_path(dirfd);
- baselen = strlen(basepath);
+ if (path[0] != '/') {
+ if (dirfd != -1 && dirfd != AT_FDCWD) {
+ if (dirfd >= 0) {
+ basepath = fd_path(dirfd);
+ baselen = strlen(basepath);
+ } else {
+ pseudo_diag("got *at() syscall for unknown directory, fd %d\n", dirfd);
+ }
} else {
- pseudo_diag("got *at() syscall for unknown directory, fd %d\n", dirfd);
+ basepath = pseudo_cwd;
+ baselen = pseudo_cwd_len;
+ }
+ if (!basepath) {
+ pseudo_diag("unknown base path for fd %d, path %s\n", dirfd, path);
+ return 0;
}
- } else {
- basepath = cwd;
- baselen = cwdlen;
- }
- if (!basepath) {
- pseudo_diag("unknown base path for fd %d, path %s\n", dirfd, path);
- return 0;
}
- pathlen = baselen + strlen(path) + 2;
newpath = pseudo_fix_path(basepath, path, baselen, NULL, leave_last);
+ pseudo_debug(4, "base_path: %s</>%s\n",
+ basepath ? basepath : "<nil>",
+ path ? path : "<nil>");
return newpath;
}
pseudo_msg_t *
-pseudo_client_op(op_id_t op, int flags, int fd, int dirfd, const char *path, const struct stat64 *buf, ...) {
+pseudo_client_op(op_id_t op, int fd, int dirfd, const char *path, const struct stat64 *buf, ...) {
pseudo_msg_t *result = 0;
pseudo_msg_t msg = { .type = PSEUDO_MSG_OP };
- char *newpath = 0;
size_t pathlen = -1;
int do_request = 0;
char *oldpath = 0;
+ char *newpath = 0;
/* disable wrappers */
pseudo_antimagic();
@@ -606,43 +649,27 @@ pseudo_client_op(op_id_t op, int flags, int fd, int dirfd, const char *path, con
pseudo_magic();
return 0;
}
- if (oldpath[0] != '/') {
- oldpath = base_path(dirfd, oldpath, 1);
- } else {
- oldpath = pseudo_fix_path(NULL, oldpath, 0, NULL, 1);
- }
}
if (path) {
- /* fixup relative path */
- if (*path != '/') {
- newpath = base_path(dirfd, path, flags);
- } else {
- newpath = pseudo_fix_path(NULL, path, 0, NULL, flags);
- }
- if (newpath) {
- pathlen = strlen(newpath) + 1;
- } else {
- pseudo_diag("couldn't allocate space for a path (%s). Sorry.\n", path);
- free(oldpath);
- pseudo_magic();
- return 0;
- }
+ /* path fixup has to happen in the specific functions,
+ * because they may have to make calls which have to be
+ * fixed up for chroot stuff already.
+ */
+ pathlen = strlen(path) + 1;
if (oldpath) {
size_t full_len = strlen(oldpath) + 1 + pathlen;
char *both_paths = malloc(full_len);
if (!both_paths) {
pseudo_diag("can't allocate space for paths for a rename operation. Sorry.\n");
- free(newpath);
- free(oldpath);
pseudo_magic();
return 0;
}
snprintf(both_paths, full_len, "%s%c%s",
- newpath, 0, oldpath);
+ path, 0, oldpath);
pseudo_debug(2, "rename: %s -> %s [%d]\n",
both_paths + pathlen, both_paths, (int) full_len);
- free(newpath);
+ path = both_paths;
newpath = both_paths;
pathlen = full_len;
}
@@ -660,10 +687,9 @@ pseudo_client_op(op_id_t op, int flags, int fd, int dirfd, const char *path, con
(dirfd != -1 && dirfd != AT_FDCWD && op != OP_DUP) ? "at" : "");
if (oldpath) {
pseudo_debug(2, " %s ->", (char *) oldpath);
- free(oldpath);
}
- if (newpath || path) {
- pseudo_debug(2, " %s", newpath ? newpath : path);
+ if (path) {
+ pseudo_debug(2, " %s", path);
}
if (fd != -1) {
pseudo_debug(2, " [fd %d]", fd);
@@ -688,12 +714,11 @@ pseudo_client_op(op_id_t op, int flags, int fd, int dirfd, const char *path, con
pseudo_debug(4, "processing request [ino %llu]\n", (unsigned long long) msg.ino);
switch (msg.op) {
case OP_CHDIR:
- cwd = getcwd(cwdbuf, PATH_MAX);
- cwdlen = strlen(cwd);
+ pseudo_client_getcwd();
do_request = 0;
break;
case OP_OPEN:
- pseudo_client_path(fd, newpath ? newpath : path);
+ pseudo_client_path(fd, path);
do_request = 1;
break;
case OP_CLOSE:
@@ -752,7 +777,7 @@ pseudo_client_op(op_id_t op, int flags, int fd, int dirfd, const char *path, con
struct timeval tv1, tv2;
pseudo_debug(4, "sending request [ino %llu]\n", (unsigned long long) msg.ino);
gettimeofday(&tv1, NULL);
- result = pseudo_client_request(&msg, pathlen, newpath ? newpath : path);
+ result = pseudo_client_request(&msg, pathlen, path);
gettimeofday(&tv2, NULL);
++messages;
message_time.tv_sec += (tv2.tv_sec - tv1.tv_sec);
@@ -787,6 +812,7 @@ pseudo_client_op(op_id_t op, int flags, int fd, int dirfd, const char *path, con
}
pseudo_debug(2, "\n");
+ /* if not NULL, newpath is the buffer holding both paths */
free(newpath);
if (do_request && (messages % 1000 == 0)) {