minix/minix/lib/libpuffs/path.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

159 lines
3.9 KiB
C

/*
* This file contains the procedures that look up path names in the directory
* system and determine the pnode number that goes with a given path name.
*
* Created (based on MFS):
* June 2011 (Evgeniy Ivanov)
*/
#include "fs.h"
#include <sys/cdefs.h>
#include <sys/stat.h>
#include <sys/types.h>
/*===========================================================================*
* fs_lookup *
*===========================================================================*/
int fs_lookup(ino_t dir_nr, char *name, struct fsdriver_node *node,
int *is_mountpt)
{
struct puffs_node *pn, *pn_dir;
/* Find the pnode of the directory node. */
if ((pn_dir = puffs_pn_nodewalk(global_pu, find_inode_cb, &dir_nr)) == NULL) {
lpuffs_debug("nodewalk failed\n");
return(EINVAL);
}
if (!S_ISDIR(pn_dir->pn_va.va_mode))
return ENOTDIR;
if ((pn = advance(pn_dir, name)) == NULL)
return err_code;
pn->pn_count++; /* open pnode */
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 = pn->pn_va.va_rdev;
*is_mountpt = pn->pn_mountpoint;
return OK;
}
/*===========================================================================*
* advance *
*===========================================================================*/
struct puffs_node *advance(
struct puffs_node *pn_dir, /* pnode for directory to be searched */
char string[NAME_MAX + 1] /* component name to look for */
)
{
/* Given a directory and a component of a path, look up the component in
* the directory, find the pnode, open it, and return a pointer to its pnode
* slot.
* TODO: instead of string, should get pcn.
*/
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}};
enum vtype node_vtype;
voff_t size;
dev_t rdev;
int error;
assert(pn_dir != NULL);
err_code = OK;
/* If 'string' is empty, return an error. */
if (string[0] == '\0') {
err_code = ENOENT;
return(NULL);
}
/* If dir has been removed return ENOENT. */
if (pn_dir->pn_va.va_nlink == NO_LINK) {
err_code = ENOENT;
return(NULL);
}
if (strcmp(string, ".") == 0) {
/* Otherwise we will fall into trouble: path for pnode to be looked up
* will be parent path (same pnode as the one to be looked up) +
* requested path. E.g. after several lookups we might get advance
* for "." with parent path "/././././././././.".
* FIXME: how is ".." handled then?
*
* Another problem is that after lookup pnode will be added
* to the pu_pnodelst, which already contains pnode instance for this
* pnode. It will cause lot of troubles.
* FIXME: check if this is actually correct, because if it is, we are
* in lots of trouble; there are many ways to reach already-open pnodes
*/
return pn_dir;
}
pni.pni_cookie = (void** )&pn;
pni.pni_vtype = &node_vtype;
pni.pni_size = &size;
pni.pni_rdev = &rdev;
pcn.pcn_namelen = strlen(string);
assert(pcn.pcn_namelen <= MAXPATHLEN);
strcpy(pcn.pcn_name, string);
if (buildpath) {
if (puffs_path_pcnbuild(global_pu, &pcn, pn_dir) != 0) {
lpuffs_debug("pathbuild error\n");
err_code = ENOENT;
return(NULL);
}
}
/* lookup *must* be present */
error = global_pu->pu_ops.puffs_node_lookup(global_pu, pn_dir, &pni, &pcn);
if (buildpath) {
if (error) {
global_pu->pu_pathfree(global_pu, &pcn.pcn_po_full);
err_code = ENOENT;
return(NULL);
} else {
struct puffs_node *_pn;
/*
* did we get a new node or a
* recycled node?
*/
_pn = PU_CMAP(global_pu, pn);
if (_pn->pn_po.po_path == NULL)
_pn->pn_po = pcn.pcn_po_full;
else
global_pu->pu_pathfree(global_pu, &pcn.pcn_po_full);
}
}
if (error) {
err_code = error < 0 ? error : -error;
return(NULL);
}
err_code = OK;
assert(pn != NULL);
return(pn);
}