}
/*
+ * Free a refcounted inode
+ */
+void put_inode(struct inode *inode)
+{
+ if (inode) {
+ if (! --inode->refcnt) {
+ put_inode(inode->parent);
+ free(inode);
+ }
+ }
+}
+
+/*
* Get an empty file structure
*/
static struct file *alloc_file(void)
p++;
*p++ = '\0';
- if (part[0] != '.' || part[1] != '\0') {
+ if (part[0] == '.' && part[1] == '.' && part[2] == '\0') {
+ if (inode->parent) {
+ put_inode(parent);
+ parent = get_inode(inode->parent);
+ put_inode(inode);
+ inode = NULL;
+ if (!echar) {
+ /* Terminal double dots */
+ inode = parent;
+ parent = inode->parent ?
+ get_inode(inode->parent) : NULL;
+ }
+ }
+ } else if (part[0] != '.' || part[1] != '\0') {
inode = this_fs->fs_ops->iget(part, parent);
if (!inode)
goto err;
goto got_link;
}
- put_inode(parent);
+ inode->parent = parent;
parent = NULL;
if (!echar)
file->inode = inode;
file->offset = 0;
- dprintf("File %s -> %p (inode %p) len %u\n", name, file,
- inode, inode->size);
-
return file_to_handle(file);
err:
- if (inode)
- put_inode(inode);
- if (parent)
- put_inode(parent);
+ put_inode(inode);
+ put_inode(parent);
if (pathbuf)
free(pathbuf);
_close_file(file);
*/
struct inode {
struct fs_info *fs; /* The filesystem this inode is associated with */
+ struct inode *parent; /* Parent directory, if any */
int refcnt;
int mode; /* FILE , DIR or SYMLINK */
uint32_t size;
inode->refcnt++;
return inode;
}
-static inline void put_inode(struct inode *inode)
-{
- if (! --inode->refcnt)
- free(inode);
-}
+
+void put_inode(struct inode *inode);
static inline void malloc_error(char *obj)
{