2011-11-14 12:53:05 +01:00
|
|
|
/* Created (MFS based):
|
|
|
|
* June 2011 (Evgeniy Ivanov)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "fs.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
#include "puffs.h"
|
|
|
|
#include "puffs_priv.h"
|
|
|
|
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* fs_create *
|
|
|
|
*===========================================================================*/
|
2014-08-24 11:51:35 +02:00
|
|
|
int fs_create(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid,
|
|
|
|
struct fsdriver_node *node)
|
2011-11-14 12:53:05 +01:00
|
|
|
{
|
|
|
|
int r;
|
|
|
|
struct puffs_node *pn_dir;
|
|
|
|
struct puffs_node *pn;
|
|
|
|
struct puffs_newinfo pni;
|
|
|
|
struct puffs_kcn pkcnp;
|
|
|
|
PUFFS_MAKECRED(pcr, &global_kcred);
|
2012-02-01 12:44:26 +01:00
|
|
|
struct puffs_cn pcn = {&pkcnp, (struct puffs_cred *) __UNCONST(pcr), {0,0,0}};
|
2011-11-14 12:53:05 +01:00
|
|
|
struct vattr va;
|
2013-04-07 10:42:26 +02:00
|
|
|
struct timespec cur_time;
|
2011-11-14 12:53:05 +01:00
|
|
|
|
|
|
|
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) */
|
2014-08-24 11:51:35 +02:00
|
|
|
pcn.pcn_namelen = strlen(name);
|
|
|
|
assert(pcn.pcn_namelen <= NAME_MAX);
|
|
|
|
strcpy(pcn.pcn_name, name);
|
2011-11-14 12:53:05 +01:00
|
|
|
|
|
|
|
/* Get last directory pnode (i.e., directory that will hold the new pnode) */
|
2014-08-24 11:51:35 +02:00
|
|
|
if ((pn_dir = puffs_pn_nodewalk(global_pu, 0, &dir_nr)) == NULL)
|
2011-11-14 12:53:05 +01:00
|
|
|
return(ENOENT);
|
|
|
|
|
|
|
|
memset(&pni, 0, sizeof(pni));
|
|
|
|
pni.pni_cookie = (void** )&pn;
|
|
|
|
|
2014-08-24 12:00:06 +02:00
|
|
|
(void)clock_time(&cur_time);
|
2011-11-14 12:53:05 +01:00
|
|
|
|
|
|
|
memset(&va, 0, sizeof(va));
|
|
|
|
va.va_type = VREG;
|
2014-08-24 11:51:35 +02:00
|
|
|
va.va_mode = mode;
|
|
|
|
va.va_uid = uid;
|
|
|
|
va.va_gid = gid;
|
2013-04-07 10:42:26 +02:00
|
|
|
va.va_atime = va.va_mtime = va.va_ctime = cur_time;
|
2011-11-14 12:53:05 +01:00
|
|
|
|
|
|
|
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++;
|
|
|
|
|
2013-04-07 10:42:26 +02:00
|
|
|
update_timens(pn_dir, MTIME | CTIME, &cur_time);
|
2011-11-14 12:53:05 +01:00
|
|
|
|
|
|
|
/* Reply message */
|
2014-08-24 11:51:35 +02:00
|
|
|
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;
|
2011-11-14 12:53:05 +01:00
|
|
|
|
|
|
|
return(OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* fs_mknod *
|
|
|
|
*===========================================================================*/
|
2014-08-24 11:51:35 +02:00
|
|
|
int fs_mknod(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid,
|
|
|
|
dev_t dev)
|
2011-11-14 12:53:05 +01:00
|
|
|
{
|
|
|
|
int r;
|
|
|
|
struct puffs_node *pn_dir;
|
|
|
|
struct puffs_node *pn;
|
|
|
|
struct puffs_newinfo pni;
|
|
|
|
struct puffs_kcn pkcnp;
|
|
|
|
PUFFS_MAKECRED(pcr, &global_kcred);
|
2012-02-01 12:44:26 +01:00
|
|
|
struct puffs_cn pcn = {&pkcnp, (struct puffs_cred *) __UNCONST(pcr), {0,0,0}};
|
2011-11-14 12:53:05 +01:00
|
|
|
struct vattr va;
|
2013-04-07 10:42:26 +02:00
|
|
|
struct timespec cur_time;
|
2011-11-14 12:53:05 +01:00
|
|
|
|
|
|
|
if (global_pu->pu_ops.puffs_node_mknod == NULL) {
|
|
|
|
lpuffs_debug("No puffs_node_mknod");
|
|
|
|
return(ENFILE);
|
|
|
|
}
|
|
|
|
|
2014-08-24 11:51:35 +02:00
|
|
|
/* Copy the last component */
|
|
|
|
pcn.pcn_namelen = strlen(name);
|
|
|
|
assert(pcn.pcn_namelen <= NAME_MAX);
|
|
|
|
strcpy(pcn.pcn_name, name);
|
2011-11-14 12:53:05 +01:00
|
|
|
|
|
|
|
/* Get last directory pnode */
|
2014-08-24 11:51:35 +02:00
|
|
|
if ((pn_dir = puffs_pn_nodewalk(global_pu, 0, &dir_nr)) == NULL)
|
2011-11-14 12:53:05 +01:00
|
|
|
return(ENOENT);
|
|
|
|
|
|
|
|
memset(&pni, 0, sizeof(pni));
|
|
|
|
pni.pni_cookie = (void** )&pn;
|
|
|
|
|
2014-08-24 12:00:06 +02:00
|
|
|
(void)clock_time(&cur_time);
|
2011-11-14 12:53:05 +01:00
|
|
|
|
|
|
|
memset(&va, 0, sizeof(va));
|
|
|
|
va.va_type = VDIR;
|
2014-08-24 11:51:35 +02:00
|
|
|
va.va_mode = mode;
|
|
|
|
va.va_uid = uid;
|
|
|
|
va.va_gid = gid;
|
|
|
|
va.va_rdev = dev;
|
2013-04-07 10:42:26 +02:00
|
|
|
va.va_atime = va.va_mtime = va.va_ctime = cur_time;
|
2011-11-14 12:53:05 +01:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2013-04-07 10:42:26 +02:00
|
|
|
update_timens(pn_dir, MTIME | CTIME, &cur_time);
|
2011-11-14 12:53:05 +01:00
|
|
|
|
|
|
|
return(OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* fs_mkdir *
|
|
|
|
*===========================================================================*/
|
2014-08-24 11:51:35 +02:00
|
|
|
int fs_mkdir(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid)
|
2011-11-14 12:53:05 +01:00
|
|
|
{
|
|
|
|
int r;
|
|
|
|
struct puffs_node *pn_dir;
|
|
|
|
struct puffs_node *pn;
|
|
|
|
struct puffs_newinfo pni;
|
|
|
|
struct puffs_kcn pkcnp;
|
|
|
|
PUFFS_MAKECRED(pcr, &global_kcred);
|
2012-02-01 12:44:26 +01:00
|
|
|
struct puffs_cn pcn = {&pkcnp, (struct puffs_cred *) __UNCONST(pcr), {0,0,0}};
|
2011-11-14 12:53:05 +01:00
|
|
|
struct vattr va;
|
2013-04-07 10:42:26 +02:00
|
|
|
struct timespec cur_time;
|
2011-11-14 12:53:05 +01:00
|
|
|
|
|
|
|
if (global_pu->pu_ops.puffs_node_mkdir == NULL) {
|
|
|
|
lpuffs_debug("No puffs_node_mkdir");
|
|
|
|
return(ENFILE);
|
|
|
|
}
|
|
|
|
|
2014-08-24 11:51:35 +02:00
|
|
|
/* Copy the last component */
|
|
|
|
pcn.pcn_namelen = strlen(name);
|
|
|
|
assert(pcn.pcn_namelen <= NAME_MAX);
|
|
|
|
strcpy(pcn.pcn_name, name);
|
2011-11-14 12:53:05 +01:00
|
|
|
|
|
|
|
/* Get last directory pnode */
|
2014-08-24 11:51:35 +02:00
|
|
|
if ((pn_dir = puffs_pn_nodewalk(global_pu, 0, &dir_nr)) == NULL)
|
2011-11-14 12:53:05 +01:00
|
|
|
return(ENOENT);
|
|
|
|
|
2014-08-24 12:00:06 +02:00
|
|
|
(void)clock_time(&cur_time);
|
2011-11-14 12:53:05 +01:00
|
|
|
|
|
|
|
memset(&pni, 0, sizeof(pni));
|
|
|
|
pni.pni_cookie = (void** )&pn;
|
|
|
|
|
|
|
|
memset(&va, 0, sizeof(va));
|
|
|
|
va.va_type = VDIR;
|
2014-08-24 11:51:35 +02:00
|
|
|
va.va_mode = mode;
|
|
|
|
va.va_uid = uid;
|
|
|
|
va.va_gid = gid;
|
2013-04-07 10:42:26 +02:00
|
|
|
va.va_atime = va.va_mtime = va.va_ctime = cur_time;
|
2011-11-14 12:53:05 +01:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2013-04-07 10:42:26 +02:00
|
|
|
update_timens(pn_dir, MTIME | CTIME, &cur_time);
|
2011-11-14 12:53:05 +01:00
|
|
|
|
|
|
|
return(OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* fs_slink *
|
|
|
|
*===========================================================================*/
|
2014-08-24 11:51:35 +02:00
|
|
|
int fs_slink(ino_t dir_nr, char *name, uid_t uid, gid_t gid,
|
|
|
|
struct fsdriver_data *data, size_t bytes)
|
2011-11-14 12:53:05 +01:00
|
|
|
{
|
|
|
|
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);
|
2012-02-01 12:44:26 +01:00
|
|
|
struct puffs_cn pcn = {&pkcnp, (struct puffs_cred *) __UNCONST(pcr), {0,0,0}};
|
2011-11-14 12:53:05 +01:00
|
|
|
struct vattr va;
|
2014-08-24 12:00:06 +02:00
|
|
|
struct timespec cur_time;
|
2011-11-14 12:53:05 +01:00
|
|
|
|
|
|
|
/* Copy the link name's last component */
|
2014-08-24 11:51:35 +02:00
|
|
|
pcn.pcn_namelen = strlen(name);
|
|
|
|
if (pcn.pcn_namelen <= NAME_MAX);
|
|
|
|
strcpy(pcn.pcn_name, name);
|
2011-11-14 12:53:05 +01:00
|
|
|
|
2014-08-24 11:51:35 +02:00
|
|
|
if (bytes >= PATH_MAX)
|
2011-11-14 12:53:05 +01:00
|
|
|
return(ENAMETOOLONG);
|
|
|
|
|
|
|
|
/* Copy the target path (note that it's not null terminated) */
|
2014-08-24 11:51:35 +02:00
|
|
|
if ((r = fsdriver_copyin(data, 0, target, bytes)) != OK)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
target[bytes] = '\0';
|
2011-11-14 12:53:05 +01:00
|
|
|
|
2014-08-24 11:51:35 +02:00
|
|
|
if (strlen(target) != bytes) {
|
2011-11-14 12:53:05 +01:00
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
|
2014-08-24 11:51:35 +02:00
|
|
|
if ((pn_dir = puffs_pn_nodewalk(global_pu, 0, &dir_nr)) == NULL)
|
2011-11-14 12:53:05 +01:00
|
|
|
return(EINVAL);
|
|
|
|
|
|
|
|
memset(&pni, 0, sizeof(pni));
|
|
|
|
pni.pni_cookie = (void** )&pn;
|
|
|
|
|
2014-08-24 12:00:06 +02:00
|
|
|
(void)clock_time(&cur_time);
|
|
|
|
|
2011-11-14 12:53:05 +01:00
|
|
|
memset(&va, 0, sizeof(va));
|
|
|
|
va.va_type = VLNK;
|
2014-04-29 20:59:48 +02:00
|
|
|
va.va_mode = (I_SYMBOLIC_LINK | RWX_MODES);
|
2014-08-24 11:51:35 +02:00
|
|
|
va.va_uid = uid;
|
|
|
|
va.va_gid = gid;
|
2014-08-24 12:00:06 +02:00
|
|
|
va.va_atime = va.va_mtime = va.va_ctime = cur_time;
|
2011-11-14 12:53:05 +01:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|