Ejemplo n.º 1
0
Archivo: nffs.c Proyecto: tecbea/larva
/**
 * Retrieves the current length of the specified open file.
 *
 * @param file              The file to query.
 * @param out_len           On success, the number of bytes in the file gets
 *                              written here.
 *
 * @return                  0 on success; nonzero on failure.
 */
int
nffs_file_len(struct nffs_file *file, uint32_t *out_len)
{
    int rc;

    nffs_lock();
    rc = nffs_inode_data_len(file->nf_inode_entry, out_len);
    nffs_unlock();

    return rc;
}
Ejemplo n.º 2
0
/**
 * Retrieves the current length of the specified open file.
 *
 * @param file              The file to query.
 * @param out_len           On success, the number of bytes in the file gets
 *                              written here.
 *
 * @return                  0 on success; nonzero on failure.
 */
static int
nffs_file_len(const struct fs_file *fs_file, uint32_t *out_len)
{
    int rc;
    const struct nffs_file *file = (const struct nffs_file *)fs_file;

    nffs_lock();
    rc = nffs_inode_data_len(file->nf_inode_entry, out_len);
    nffs_unlock();

    return rc;
}
Ejemplo n.º 3
0
/**
 * Positions a file's read and write pointer at the specified offset.  The
 * offset is expressed as the number of bytes from the start of the file (i.e.,
 * seeking to 0 places the pointer at the first byte in the file).
 *
 * @param file              The file to reposition.
 * @param offset            The offset from the start of the file to seek to.
 *
 * @return                  0 on success; nonzero on failure.
 */
int
nffs_file_seek(struct nffs_file *file, uint32_t offset)
{ 
    uint32_t len;
    int rc;

    rc = nffs_inode_data_len(file->nf_inode_entry, &len);
    if (rc != 0) {
        return rc;
    }

    if (offset > len) {
        return FS_ERANGE;
    }

    file->nf_offset = offset;
    return 0;
}
Ejemplo n.º 4
0
/**
 * Performs a file open operation.
 *
 * @param out_file          On success, a pointer to the newly-created file
 *                              handle gets written here.
 * @param path              The path of the file to open.
 * @param access_flags      Flags controlling file access; see nffs_open() for
 *                              details.
 *
 * @return                  0 on success; nonzero on failure.
 */
int
nffs_file_open(struct nffs_file **out_file, const char *path,
               uint8_t access_flags)
{
    struct nffs_path_parser parser;
    struct nffs_inode_entry *parent;
    struct nffs_inode_entry *inode;
    struct nffs_file *file;
    int rc;

    file = NULL;

    /* Reject invalid access flag combinations. */
    if (!(access_flags & (FS_ACCESS_READ | FS_ACCESS_WRITE))) {
        rc = FS_EINVAL;
        goto err;
    }
    if (access_flags & (FS_ACCESS_APPEND | FS_ACCESS_TRUNCATE) &&
        !(access_flags & FS_ACCESS_WRITE)) {

        rc = FS_EINVAL;
        goto err;
    }
    if (access_flags & FS_ACCESS_APPEND &&
        access_flags & FS_ACCESS_TRUNCATE) {

        rc = FS_EINVAL;
        goto err;
    }

    file = nffs_file_alloc();
    if (file == NULL) {
        rc = FS_ENOMEM;
        goto err;
    }

    nffs_path_parser_new(&parser, path);
    rc = nffs_path_find(&parser, &inode, &parent);
    if (rc == FS_ENOENT && parser.npp_token_type == NFFS_PATH_TOKEN_LEAF) {
        /* The path is valid, but the file does not exist.  This is an error
         * for read-only opens.
         */
        if (!(access_flags & FS_ACCESS_WRITE)) {
            goto err;
        }

        /* Make sure the parent directory exists. */
        if (parent == NULL) {
            goto err;
        }

        /* Create a new file at the specified path. */
        rc = nffs_file_new(parent, parser.npp_token, parser.npp_token_len, 0,
                           &file->nf_inode_entry);
        if (rc != 0) {
            goto err;
        }
    } else if (rc == 0) {
        /* The file already exists. */

        /* Reject an attempt to open a directory. */
        if (nffs_hash_id_is_dir(inode->nie_hash_entry.nhe_id)) {
            rc = FS_EINVAL;
            goto err;
        }

        if (access_flags & FS_ACCESS_TRUNCATE) {
            /* The user is truncating the file.  Unlink the old file and create
             * a new one in its place.
             */
            nffs_path_unlink(path);
            rc = nffs_file_new(parent, parser.npp_token, parser.npp_token_len,
                               0, &file->nf_inode_entry);
            if (rc != 0) {
                goto err;
            }
        } else {
            /* The user is not truncating the file.  Point the file handle to
             * the existing inode.
             */
            file->nf_inode_entry = inode;
        }
    } else {
        /* Invalid path. */
        goto err;
    }

    if (access_flags & FS_ACCESS_APPEND) {
        rc = nffs_inode_data_len(file->nf_inode_entry, &file->nf_offset);
        if (rc != 0) {
            goto err;
        }
    } else {
        file->nf_offset = 0;
    }
    file->nf_inode_entry->nie_refcnt++;
    file->nf_access_flags = access_flags;

    *out_file = file;

    return 0;

err:
    nffs_file_free(file);
    return rc;
}