NFSv4: Add support for mknod()

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
libnfs-4.0.0-vitalif
Ronnie Sahlberg 2017-08-15 20:05:47 +10:00
parent de9da5689d
commit bd95371005
5 changed files with 144 additions and 2 deletions

View File

@ -484,6 +484,8 @@ int nfs4_link_async(struct nfs_context *nfs, const char *oldpath,
const char *newpath, nfs_cb cb, void *private_data);
int nfs4_mkdir2_async(struct nfs_context *nfs, const char *path, int mode,
nfs_cb cb, void *private_data);
int nfs4_mknod_async(struct nfs_context *nfs, const char *path, int mode,
int dev, nfs_cb cb, void *private_data);
int nfs4_mount_async(struct nfs_context *nfs, const char *server,
const char *export, nfs_cb cb, void *private_data);
int nfs4_open_async(struct nfs_context *nfs, const char *path, int flags,

View File

@ -1247,9 +1247,11 @@ nfs_mknod_async(struct nfs_context *nfs, const char *path, int mode, int dev,
switch (nfs->version) {
case NFS_V3:
return nfs3_mknod_async(nfs, path, mode, dev, cb, private_data);
case NFS_V4:
return nfs4_mknod_async(nfs, path, mode, dev, cb, private_data);
default:
nfs_set_error(nfs, "%s does not support NFSv4",
__FUNCTION__);
nfs_set_error(nfs, "%s does not support NFSv%d",
__FUNCTION__, nfs->version);
return -1;
}
}

View File

@ -3001,6 +3001,7 @@ nfs3_mknod_continue_internal(struct nfs_context *nfs,
args.what.mknoddata3_u.blk_device.dev_attributes.mode.set_mode3_u.mode = cb_data->mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH);
args.what.mknoddata3_u.blk_device.spec.specdata1 = cb_data->major;
args.what.mknoddata3_u.blk_device.spec.specdata2 = cb_data->minor;
break;
case S_IFSOCK:
args.what.type = NF3SOCK;
args.what.mknoddata3_u.sock_attributes.mode.set_it = 1;

View File

@ -2752,3 +2752,128 @@ nfs4_rename_async(struct nfs_context *nfs, const char *oldpath,
return 0;
}
static void
nfs4_mknod_cb(struct rpc_context *rpc, int status, void *command_data,
void *private_data)
{
struct nfs4_cb_data *data = private_data;
struct nfs_context *nfs = data->nfs;
COMPOUND4res *res = command_data;
assert(rpc->magic == RPC_CONTEXT_MAGIC);
if (check_nfs4_error(nfs, status, data, res, "MKNOD")) {
free_nfs4_cb_data(data);
return;
}
data->cb(0, nfs, NULL, data->private_data);
free_nfs4_cb_data(data);
}
static int
nfs4_populate_mknod(struct nfs4_cb_data *data, nfs_argop4 *op)
{
CREATE4args *cargs;
uint32_t mode, *ptr;
int dev;
/* Strip off the file type before we marshall it */
ptr = (void *)data->filler.blob1.val;
mode = *ptr;
*ptr = htonl(mode & ~S_IFMT);
dev = data->filler.blob2.len;
op[0].argop = OP_CREATE;
cargs = &op[0].nfs_argop4_u.opcreate;
memset(cargs, 0, sizeof(*cargs));
cargs->objname.utf8string_val = data->filler.data;
cargs->objname.utf8string_len = strlen(cargs->objname.utf8string_val);
cargs->createattrs.attrmask.bitmap4_len = data->filler.blob0.len;
cargs->createattrs.attrmask.bitmap4_val = data->filler.blob0.val;
cargs->createattrs.attr_vals.attrlist4_len = data->filler.blob1.len;
cargs->createattrs.attr_vals.attrlist4_val = data->filler.blob1.val;
switch (mode & S_IFMT) {
case S_IFCHR:
cargs->objtype.type = NF4CHR;
cargs->objtype.createtype4_u.devdata.specdata1 = major(dev);
cargs->objtype.createtype4_u.devdata.specdata2 = minor(dev);
break;
case S_IFBLK:
cargs->objtype.type = NF4BLK;
cargs->objtype.createtype4_u.devdata.specdata1 = major(dev);
cargs->objtype.createtype4_u.devdata.specdata2 = minor(dev);
break;
}
return 1;
}
/* Takes object name as filler.data
* blob0 as attribute mask
* blob1 as attribute value
* blob2.len as dev
*/
int
nfs4_mknod_async(struct nfs_context *nfs, const char *path, int mode, int dev,
nfs_cb cb, void *private_data)
{
struct nfs4_cb_data *data;
uint32_t *u32ptr;
switch (mode & S_IFMT) {
case S_IFCHR:
case S_IFBLK:
break;
default:
nfs_set_error(nfs, "Invalid file type for "
"MKNOD call");
return -1;
}
data = init_cb_data_split_path(nfs, path);
if (data == NULL) {
return -1;
}
data->cb = cb;
data->private_data = private_data;
data->filler.func = nfs4_populate_mknod;
data->filler.max_op = 1;
/* attribute mask */
u32ptr = malloc(2 * sizeof(uint32_t));
if (u32ptr == NULL) {
nfs_set_error(nfs, "Out of memory allocating bitmap");
return 0;
}
u32ptr[0] = 0;
u32ptr[1] = 1 << (FATTR4_MODE - 32);
data->filler.blob0.len = 2;
data->filler.blob0.val = u32ptr;
data->filler.blob0.free = free;
/* attribute values */
u32ptr = malloc(1 * sizeof(uint32_t));
if (u32ptr == NULL) {
nfs_set_error(nfs, "Out of memory allocating attributes");
free_nfs4_cb_data(data);
return -1;
}
u32ptr[0] = mode;
data->filler.blob1.len = 4;
data->filler.blob1.val = u32ptr;
data->filler.blob1.free = free;
data->filler.blob2.len = dev;
if (nfs4_lookup_path_async(nfs, data, nfs4_mknod_cb) < 0) {
free_nfs4_cb_data(data);
return -1;
}
return 0;
}

View File

@ -44,6 +44,18 @@ echo -n "Create a chrdev outside the share (abs) (6)... "
./prog_mknod "${TESTURL}/?uid=0&version=${VERS}" "." ../subdir2/mknod6 020775 0x1234 2>/dev/null && failure
success
echo -n "Create a blkdev in the root (abs) (7)... "
./prog_mknod "${TESTURL}/?uid=0&version=${VERS}" "." /mknod7 060755 0x1234 || failure
success
echo -n "Stat the node ... "
./prog_stat "${TESTURL}/?version=${VERS}" "." mknod7 > "${TESTDIR}/output" || failure
success
echo -n "Testing nfs_mode and verify it is a BLKDEV ... "
grep "nfs_mode:60755" "${TESTDIR}/output" >/dev/null || failure
success
stop_share
exit 0