aboutsummaryrefslogtreecommitdiffstats
path: root/pseudo_client.c
diff options
context:
space:
mode:
Diffstat (limited to 'pseudo_client.c')
-rw-r--r--pseudo_client.c42
1 files changed, 38 insertions, 4 deletions
diff --git a/pseudo_client.c b/pseudo_client.c
index 2134c8e..40985e6 100644
--- a/pseudo_client.c
+++ b/pseudo_client.c
@@ -1056,6 +1056,7 @@ pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path
size_t pathlen = -1;
int do_request = 0;
char *oldpath = 0;
+ size_t oldpathlen = 0;
char *alloced_path = 0;
/* disable wrappers */
@@ -1073,6 +1074,11 @@ pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path
pseudo_magic();
return 0;
}
+ /* we have to calculate this here, because SET_XATTR
+ * and friends will be using oldpath to hold a hunk of
+ * data of arbitrary length
+ */
+ oldpathlen = strlen(oldpath);
if (!path) {
pseudo_diag("rename (%s) without new path.\n",
path ? path : "<nil>");
@@ -1081,6 +1087,28 @@ pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path
}
}
+ /* we treat the "create" and "replace" flags as logically
+ * distinct operations, because they can fail when set can't.
+ */
+ if (op == OP_SET_XATTR || op == OP_CREATE_XATTR || op == OP_REPLACE_XATTR) {
+ va_list ap;
+ va_start(ap, buf);
+ oldpath = va_arg(ap, char *);
+ oldpathlen = va_arg(ap, size_t);
+ pseudo_debug(PDBGF_XATTR, "setxattr, oldpath (%d bytes): '%s'\n",
+ (int) oldpathlen, oldpath);
+ va_end(ap);
+ }
+ if (op == OP_GET_XATTR){
+ va_list ap;
+ va_start(ap, buf);
+ oldpath = va_arg(ap, char *);
+ oldpathlen = strlen(oldpath);
+ pseudo_debug(PDBGF_XATTR, "getxattr, oldpath (%d bytes): '%s'\n",
+ (int) oldpathlen, oldpath);
+ va_end(ap);
+ }
+
if (path) {
/* path fixup has to happen in the specific functions,
* because they may have to make calls which have to be
@@ -1093,16 +1121,18 @@ pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path
pathlen = strlen(path) + 1;
int strip_slash = (pathlen > 2 && (path[pathlen - 2]) == '/');
if (oldpath) {
- size_t full_len = strlen(oldpath) + 1 + pathlen;
+ 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;
}
- snprintf(both_paths, full_len, "%.*s%c%s",
- (int) (pathlen - 1 - strip_slash),
- path, 0, oldpath);
+ 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;
@@ -1239,6 +1269,10 @@ pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path
case OP_DID_UNLINK:
case OP_CANCEL_UNLINK:
case OP_MAY_UNLINK:
+ case OP_GET_XATTR:
+ case OP_LIST_XATTR:
+ case OP_SET_XATTR:
+ case OP_REMOVE_XATTR:
do_request = 1;
break;
default: