int fatfs_mknod(vnode_t * dir, const char * name, int mode, void * specinfo, vnode_t ** result) { struct fatfs_inode * indir = get_inode_of_vnode(dir); struct fatfs_inode * res = NULL; char * in_fpath; int err; #ifdef configFATFS_DEBUG KERROR(KERROR_DEBUG, "fatfs_mknod(dir %p, name \"%s\", mode %u, specinfo %p, result %p)\n", dir, name, mode, specinfo, result); #endif if (!S_ISDIR(dir->vn_mode)) return -ENOTDIR; if ((mode & S_IFMT) != S_IFREG) return -ENOTSUP; /* FAT only suports regular files. */ if (specinfo) return -EINVAL; /* specinfo not supported. */ in_fpath = format_fpath(indir, name); if (!in_fpath) return -ENOMEM; err = create_inode(&res, get_ffsb_of_sb(dir->sb), in_fpath, hash32_str(in_fpath, 0), O_CREAT); if (err) { kfree(in_fpath); return fresult2errno(err); } if (result) *result = &res->in_vnode; fatfs_chmod(&res->in_vnode, mode); #ifdef configFATFS_DEBUG KERROR(KERROR_DEBUG, "mkdod() ok\n"); #endif return 0; }
static vnode_t * create_root(struct fatfs_sb * fatfs_sb) { char * rootpath; long vn_hash; struct fatfs_inode * in; int err; rootpath = kzalloc(2); if (!rootpath) return NULL; vn_hash = hash32_str(rootpath, 0); err = create_inode(&in, fatfs_sb, rootpath, vn_hash, O_DIRECTORY | O_RDWR); if (err) { KERROR(KERROR_ERR, "Failed to init a root vnode for fatfs (%d)\n", err); return NULL; } in->in_fpath = rootpath; vrefset(&in->in_vnode, 1); return &in->in_vnode; }
/** * Lookup for a vnode (file/dir) in FatFs. * First lookup form vfs_hash and if not found then read it from ff which will * probably read it via devfs interface. After the vnode has been created it * will be added to the vfs hashmap. In ff terminology all files and directories * that are in hashmap are also open on a file/dir handle, thus we'll have to * make sure we don't have too many vnodes in cache that have no references, to * avoid hitting any ff hard limits. */ static int fatfs_lookup(vnode_t * dir, const char * name, vnode_t ** result) { struct fatfs_inode * indir = get_inode_of_vnode(dir); struct fatfs_sb * sb = get_ffsb_of_sb(dir->sb); char * in_fpath; long vn_hash; struct vnode * vn = NULL; int err, retval = 0; KASSERT(dir != NULL, "dir must be set"); /* Format full path */ in_fpath = format_fpath(indir, name); if (!in_fpath) return -ENOMEM; /* * Emulate . and .. */ if (name[0] == '.' && name[1] != '.') { #ifdef configFATFS_DEBUG KERROR(KERROR_DEBUG, "Lookup emulating \".\"\n"); #endif (void)vref(dir); *result = dir; kfree(in_fpath); return 0; } else if (name[0] == '.' && name[1] == '.' && name[2] != '.') { #ifdef configFATFS_DEBUG KERROR(KERROR_DEBUG, "Lookup emulating \"..\"\n"); #endif if (VN_IS_FSROOT(dir)) { *result = dir->sb->mountpoint; kfree(in_fpath); return -EDOM; } else { size_t i = strlenn(in_fpath, NAME_MAX) - 4; while (in_fpath[i] != '/') { i--; } in_fpath[i] = '\0'; } } /* * Lookup from vfs_hash */ vn_hash = hash32_str(in_fpath, 0); err = vfs_hash_get( dir->sb, /* FS superblock */ vn_hash, /* Hash */ &vn, /* Retval */ fatfs_vncmp, /* Comparator */ in_fpath /* Compared fpath */ ); if (err) { retval = -EIO; goto fail; } if (vn) { /* found it in vfs_hash */ #ifdef configFATFS_DEBUG KERROR(KERROR_DEBUG, "vn found in vfs_hash (%p)\n", vn); #endif *result = vn; retval = 0; } else { /* not cached */ struct fatfs_inode * in; #ifdef configFATFS_DEBUG KERROR(KERROR_DEBUG, "vn not in vfs_hash\n"); #endif /* * Create a inode and fetch data from the device. * This also vrefs. */ err = create_inode(&in, sb, in_fpath, vn_hash, O_RDWR); if (err) { retval = err; goto fail; } in_fpath = NULL; /* shall not be freed. */ *result = &in->in_vnode; retval = 0; } fail: kfree(in_fpath); return retval; }
static size_t hash_fun(const void * s,size_t t) { return hash32_str(((struct tl*)s)->s1,HASH32_STR_INIT)%t; }