Beispiel #1
0
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;
}
Beispiel #2
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;
}
Beispiel #3
0
/**
 * 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;
}
Beispiel #4
0
static size_t hash_fun(const void * s,size_t t)
{
    return hash32_str(((struct  tl*)s)->s1,HASH32_STR_INIT)%t;
}