minix/minix/lib/libpuffs/open.c
David van Moolenbroek ba736c7968 libpuffs: clean up, unbreak
- move MINIX3-specific files into minix/lib/libpuffs;
- resynchronize the remaining files with NetBSD code;
- remove a few unnecessary changes;
- put remaining MINIX3-specific changes in __minix blocks;
- sort out the source files being linked at all.

The result is that libpuffs now successfully links against FUSE
file system programs again.  It can successfully mount, perform
some of the most basic operations, and unmount the file system.

Change-Id: Ieac220f7ad8c4d1fa293abda81967e8045be0bb4
2015-09-23 12:05:03 +00:00

319 lines
7.8 KiB
C

/* Created (MFS based):
* June 2011 (Evgeniy Ivanov)
*/
#include "fs.h"
/*===========================================================================*
* fs_create *
*===========================================================================*/
int fs_create(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid,
struct fsdriver_node *node)
{
int r;
struct puffs_node *pn_dir;
struct puffs_node *pn;
struct puffs_newinfo pni;
struct puffs_kcn pkcnp;
PUFFS_MAKECRED(pcr, &global_kcred);
struct puffs_cn pcn = {&pkcnp, (struct puffs_cred *) __UNCONST(pcr), {0,0,0}};
struct vattr va;
struct timespec cur_time;
if (global_pu->pu_ops.puffs_node_create == NULL) {
lpuffs_debug("No puffs_node_create");
return(ENFILE);
}
/* Copy the last component (i.e., file name) */
pcn.pcn_namelen = strlen(name);
assert(pcn.pcn_namelen <= NAME_MAX);
strcpy(pcn.pcn_name, name);
/* Get last directory pnode (i.e., directory that will hold the new pnode) */
if ((pn_dir = puffs_pn_nodewalk(global_pu, find_inode_cb, &dir_nr)) == NULL)
return(ENOENT);
memset(&pni, 0, sizeof(pni));
pni.pni_cookie = (void** )&pn;
(void)clock_time(&cur_time);
memset(&va, 0, sizeof(va));
va.va_type = VREG;
va.va_mode = mode;
va.va_uid = uid;
va.va_gid = gid;
va.va_atime = va.va_mtime = va.va_ctime = cur_time;
if (buildpath) {
r = puffs_path_pcnbuild(global_pu, &pcn, pn_dir);
if (r) {
lpuffs_debug("pathbuild error\n");
return(ENOENT);
}
}
r = global_pu->pu_ops.puffs_node_create(global_pu, pn_dir, &pni, &pcn, &va);
if (buildpath) {
if (r) {
global_pu->pu_pathfree(global_pu, &pcn.pcn_po_full);
} else {
struct puffs_node *_pn;
_pn = PU_CMAP(global_pu, pn);
_pn->pn_po = pcn.pcn_po_full;
}
}
if (r != OK) {
if (r > 0) r = -r;
return(r);
}
/* Open pnode */
pn->pn_count++;
update_timens(pn_dir, MTIME | CTIME, &cur_time);
/* Reply message */
node->fn_ino_nr = pn->pn_va.va_fileid;
node->fn_mode = pn->pn_va.va_mode;
node->fn_size = pn->pn_va.va_size;
node->fn_uid = pn->pn_va.va_uid;
node->fn_gid = pn->pn_va.va_gid;
node->fn_dev = NO_DEV;
return(OK);
}
/*===========================================================================*
* fs_mknod *
*===========================================================================*/
int fs_mknod(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid,
dev_t dev)
{
int r;
struct puffs_node *pn_dir;
struct puffs_node *pn;
struct puffs_newinfo pni;
struct puffs_kcn pkcnp;
PUFFS_MAKECRED(pcr, &global_kcred);
struct puffs_cn pcn = {&pkcnp, (struct puffs_cred *) __UNCONST(pcr), {0,0,0}};
struct vattr va;
struct timespec cur_time;
if (global_pu->pu_ops.puffs_node_mknod == NULL) {
lpuffs_debug("No puffs_node_mknod");
return(ENFILE);
}
/* Copy the last component */
pcn.pcn_namelen = strlen(name);
assert(pcn.pcn_namelen <= NAME_MAX);
strcpy(pcn.pcn_name, name);
/* Get last directory pnode */
if ((pn_dir = puffs_pn_nodewalk(global_pu, find_inode_cb, &dir_nr)) == NULL)
return(ENOENT);
memset(&pni, 0, sizeof(pni));
pni.pni_cookie = (void** )&pn;
(void)clock_time(&cur_time);
memset(&va, 0, sizeof(va));
va.va_type = VDIR;
va.va_mode = mode;
va.va_uid = uid;
va.va_gid = gid;
va.va_rdev = dev;
va.va_atime = va.va_mtime = va.va_ctime = cur_time;
if (buildpath) {
if (puffs_path_pcnbuild(global_pu, &pcn, pn_dir) != 0) {
lpuffs_debug("pathbuild error\n");
return(ENOENT);
}
}
r = global_pu->pu_ops.puffs_node_mknod(global_pu, pn_dir, &pni, &pcn, &va);
if (buildpath) {
if (r) {
global_pu->pu_pathfree(global_pu, &pcn.pcn_po_full);
} else {
struct puffs_node *_pn;
_pn = PU_CMAP(global_pu, pn);
_pn->pn_po = pcn.pcn_po_full;
}
}
if (r != OK) {
if (r > 0) r = -r;
return(r);
}
update_timens(pn_dir, MTIME | CTIME, &cur_time);
return(OK);
}
/*===========================================================================*
* fs_mkdir *
*===========================================================================*/
int fs_mkdir(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid)
{
int r;
struct puffs_node *pn_dir;
struct puffs_node *pn;
struct puffs_newinfo pni;
struct puffs_kcn pkcnp;
PUFFS_MAKECRED(pcr, &global_kcred);
struct puffs_cn pcn = {&pkcnp, (struct puffs_cred *) __UNCONST(pcr), {0,0,0}};
struct vattr va;
struct timespec cur_time;
if (global_pu->pu_ops.puffs_node_mkdir == NULL) {
lpuffs_debug("No puffs_node_mkdir");
return(ENFILE);
}
/* Copy the last component */
pcn.pcn_namelen = strlen(name);
assert(pcn.pcn_namelen <= NAME_MAX);
strcpy(pcn.pcn_name, name);
/* Get last directory pnode */
if ((pn_dir = puffs_pn_nodewalk(global_pu, find_inode_cb, &dir_nr)) == NULL)
return(ENOENT);
(void)clock_time(&cur_time);
memset(&pni, 0, sizeof(pni));
pni.pni_cookie = (void** )&pn;
memset(&va, 0, sizeof(va));
va.va_type = VDIR;
va.va_mode = mode;
va.va_uid = uid;
va.va_gid = gid;
va.va_atime = va.va_mtime = va.va_ctime = cur_time;
if (buildpath) {
r = puffs_path_pcnbuild(global_pu, &pcn, pn_dir);
if (r) {
lpuffs_debug("pathbuild error\n");
return(ENOENT);
}
}
r = global_pu->pu_ops.puffs_node_mkdir(global_pu, pn_dir, &pni, &pcn, &va);
if (buildpath) {
if (r) {
global_pu->pu_pathfree(global_pu, &pcn.pcn_po_full);
} else {
struct puffs_node *_pn;
_pn = PU_CMAP(global_pu, pn);
_pn->pn_po = pcn.pcn_po_full;
}
}
if (r != OK) {
if (r > 0) r = -r;
return(r);
}
update_timens(pn_dir, MTIME | CTIME, &cur_time);
return(OK);
}
/*===========================================================================*
* fs_slink *
*===========================================================================*/
int fs_slink(ino_t dir_nr, char *name, uid_t uid, gid_t gid,
struct fsdriver_data *data, size_t bytes)
{
int r;
struct pnode *pn; /* pnode containing symbolic link */
struct pnode *pn_dir; /* directory containing link */
char target[PATH_MAX + 1]; /* target path */
struct puffs_newinfo pni;
struct puffs_kcn pkcnp;
PUFFS_MAKECRED(pcr, &global_kcred);
struct puffs_cn pcn = {&pkcnp, (struct puffs_cred *) __UNCONST(pcr), {0,0,0}};
struct vattr va;
struct timespec cur_time;
/* Copy the link name's last component */
pcn.pcn_namelen = strlen(name);
if (pcn.pcn_namelen > NAME_MAX)
return(ENAMETOOLONG);
strcpy(pcn.pcn_name, name);
if (bytes >= PATH_MAX)
return(ENAMETOOLONG);
/* Copy the target path (note that it's not null terminated) */
if ((r = fsdriver_copyin(data, 0, target, bytes)) != OK)
return r;
target[bytes] = '\0';
if (strlen(target) != bytes) {
/* This can happen if the user provides a buffer
* with a \0 in it. This can cause a lot of trouble
* when the symlink is used later. We could just use
* the strlen() value, but we want to let the user
* know he did something wrong. ENAMETOOLONG doesn't
* exactly describe the error, but there is no
* ENAMETOOWRONG.
*/
return(ENAMETOOLONG);
}
if ((pn_dir = puffs_pn_nodewalk(global_pu, find_inode_cb, &dir_nr)) == NULL)
return(EINVAL);
memset(&pni, 0, sizeof(pni));
pni.pni_cookie = (void** )&pn;
(void)clock_time(&cur_time);
memset(&va, 0, sizeof(va));
va.va_type = VLNK;
va.va_mode = (I_SYMBOLIC_LINK | RWX_MODES);
va.va_uid = uid;
va.va_gid = gid;
va.va_atime = va.va_mtime = va.va_ctime = cur_time;
if (buildpath) {
r = puffs_path_pcnbuild(global_pu, &pcn, pn_dir);
if (r) {
lpuffs_debug("pathbuild error\n");
return(ENOENT);
}
}
r = global_pu->pu_ops.puffs_node_symlink(global_pu, pn_dir, &pni, &pcn, &va, target);
if (buildpath) {
if (r) {
global_pu->pu_pathfree(global_pu, &pcn.pcn_po_full);
} else {
struct puffs_node *_pn;
_pn = PU_CMAP(global_pu, pn);
_pn->pn_po = pcn.pcn_po_full;
}
}
if (r > 0) r = -r;
return(r);
}