diff options
-rw-r--r-- | pseudo.c | 21 | ||||
-rw-r--r-- | pseudo_client.c | 82 | ||||
-rw-r--r-- | pseudo_db.c | 6 |
3 files changed, 66 insertions, 43 deletions
@@ -524,6 +524,7 @@ pseudo_op(pseudo_msg_t *msg, const char *program, const char *tag, char **respon */ if (msg->pathlen) { + size_t initial_len; switch (msg->op) { case OP_RENAME: case OP_CREATE_XATTR: @@ -532,10 +533,18 @@ pseudo_op(pseudo_msg_t *msg, const char *program, const char *tag, char **respon case OP_REPLACE_XATTR: case OP_SET_XATTR: /* In a rename there are two paths, null separated in msg->path */ - oldpath = msg->path + strlen(msg->path) + 1; - oldpathlen = msg->pathlen - (oldpath - msg->path); - pseudo_debug(PDBGF_OP | PDBGF_FILE | PDBGF_XATTR, "%s: path '%s', oldpath '%s' [%d]\n", - pseudo_op_name(msg->op), msg->path, oldpath, (int) oldpathlen); + initial_len = strlen(msg->path); + oldpath = msg->path + initial_len + 1; + /* for rename, the path name would be null-terminated, + * but for *xattr, we don't want the null. */ + oldpathlen = msg->pathlen - (oldpath - msg->path) - 1; + pseudo_debug(PDBGF_OP | PDBGF_FILE | PDBGF_XATTR, "%s: path '%s', oldpath '%s' [%d/%d]\n", + pseudo_op_name(msg->op), msg->path, oldpath, (int) oldpathlen, (int) msg->pathlen); + /* if we got an oldpath, but a 0-length initial + * path, we don't want to act as though we had + * a non-empty initial path. + */ + msg->pathlen = initial_len; break; default: break; @@ -956,8 +965,8 @@ pseudo_op(pseudo_msg_t *msg, const char *program, const char *tag, char **respon } else { *response_path = oldpath; *response_len = oldpathlen; - pseudo_debug(PDBGF_XATTR, "get results: '%s' (%d bytes)\n", - *response_path, (int) *response_len); + pseudo_debug(PDBGF_XATTR, "get results: '%.*s' (%d bytes)\n", + (int) *response_len, *response_path, (int) *response_len); } break; case OP_LIST_XATTR: diff --git a/pseudo_client.c b/pseudo_client.c index 40985e6..8c39e6b 100644 --- a/pseudo_client.c +++ b/pseudo_client.c @@ -1058,6 +1058,7 @@ pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path char *oldpath = 0; size_t oldpathlen = 0; char *alloced_path = 0; + int strip_slash; /* disable wrappers */ pseudo_antimagic(); @@ -1109,7 +1110,20 @@ pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path va_end(ap); } + /* if path isn't available, try to find one? */ + if (!path && fd >= 0 && fd <= nfds) { + path = fd_path(fd); + if (!path) { + pathlen = 0; + } else { + pathlen = strlen(path) + 1; + } + } + if (path) { + if (pathlen == (size_t) -1) { + pathlen = strlen(path) + 1; + } /* 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. @@ -1118,43 +1132,43 @@ pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path * (no attempt is made to handle a rename of "/" occurring * in a chroot...) */ - pathlen = strlen(path) + 1; - int strip_slash = (pathlen > 2 && (path[pathlen - 2]) == '/'); - if (oldpath) { - size_t full_len = oldpathlen + 1 + pathlen; - size_t partial_len = pathlen - 1 - strip_slash; - char *both_paths = malloc(full_len); - if (!both_paths) { - pseudo_diag("Can't allocate space for paths for a rename operation. Sorry.\n"); - pseudo_magic(); - return 0; - } - memcpy(both_paths, path, partial_len); - both_paths[partial_len] = '\0'; - memcpy(both_paths + partial_len + 1, oldpath, oldpathlen); - both_paths[full_len - 1] = '\0'; - pseudo_debug(PDBGF_PATH | PDBGF_FILE, "rename: %s -> %s [%d]\n", - both_paths + pathlen, both_paths, (int) full_len); - alloced_path = both_paths; - path = alloced_path; - pathlen = full_len; - } else { - if (strip_slash) { - alloced_path = strdup(path); - alloced_path[pathlen - 2] = '\0'; - path = alloced_path; - } + strip_slash = (pathlen > 2 && (path[pathlen - 2]) == '/'); + } else { + path = ""; + pathlen = 0; + strip_slash = 0; + } + + /* f*xattr operations can result in needing to send a path + * value even though we don't have one available. We use an + * empty path for that. + */ + if (oldpath) { + size_t full_len = oldpathlen + 1 + pathlen; + size_t partial_len = pathlen - 1 - strip_slash; + char *both_paths = malloc(full_len); + if (!both_paths) { + pseudo_diag("Can't allocate space for paths for a rename operation. Sorry.\n"); + pseudo_magic(); + return 0; } - } else if (fd >= 0 && fd <= nfds) { - path = fd_path(fd); - if (!path) - msg.pathlen = 0; - else - msg.pathlen = strlen(path) + 1; + memcpy(both_paths, path, partial_len); + both_paths[partial_len] = '\0'; + memcpy(both_paths + partial_len + 1, oldpath, oldpathlen); + both_paths[full_len - 1] = '\0'; + pseudo_debug(PDBGF_PATH | PDBGF_FILE, "rename: %s -> %s [%d]\n", + both_paths + pathlen, both_paths, (int) full_len); + alloced_path = both_paths; + path = alloced_path; + pathlen = full_len; } else { - path = 0; - msg.pathlen = 0; + if (strip_slash) { + alloced_path = strdup(path); + alloced_path[pathlen - 2] = '\0'; + path = alloced_path; + } } + pseudo_debug(PDBGF_OP, "%s%s", pseudo_op_name(op), (dirfd != -1 && dirfd != AT_FDCWD && op != OP_DUP) ? "at" : ""); if (oldpath) { diff --git a/pseudo_db.c b/pseudo_db.c index 2faeb10..0a20b96 100644 --- a/pseudo_db.c +++ b/pseudo_db.c @@ -2377,8 +2377,8 @@ pdb_set_xattr(long long file_id, char *value, size_t len, int flags) { vlen = strlen(value); len = len - (vlen + 1); value = value + len; - pseudo_debug(PDBGF_XATTR, "trying to set a value for %lld: name is '%s', value is '%s'. Existing row %lld.\n", - file_id, vname, value, existing_row); + pseudo_debug(PDBGF_XATTR, "trying to set a value for %lld: name is '%s' [%d/%d bytes], value is '%s'. Existing row %lld.\n", + file_id, vname, (int) vlen, (int) (len + vlen + 1), value, existing_row); if (existing_row != -1) { /* update */ if (!update) { @@ -2388,7 +2388,7 @@ pdb_set_xattr(long long file_id, char *value, size_t len, int flags) { return 1; } } - rc = sqlite3_bind_text(update, 1, value, -1, SQLITE_STATIC); + rc = sqlite3_bind_text(update, 1, value, len, SQLITE_STATIC); if (rc) { dberr(file_db, "couldn't bind xattr value to UPDATE."); return 1; |