Esempio n. 1
0
static int fatfs_fcntl(mount_point_t *point, file_t *file, int cmd, int arg)
{
    privinfo_t *priv = file->ctx;

    if (priv == NULL) {
        seterrno(EINVAL);
        return -1;
    }

    switch (cmd) {
    case F_GETFL:
        return file->flags;

    case F_SETFL:
        if ((!(file->flags & FWRITE)) && (arg & FWRITE)) {
            seterrno(EINVAL);
            return -1;
        }
        file->flags = arg;
        return 0;

    default:
        seterrno(EINVAL);
        return -1;
    }
}
Esempio n. 2
0
/*********************************************************************************************************
** Function name:           __vfs_close
** Descriptions:            关闭文件
** input parameters:        pid                 任务 ID
**                          fd                  文件描述符
** output parameters:       NONE
** Returned value:          0 OR -1
*********************************************************************************************************/
int __vfs_close(pid_t pid, int fd)
{
    int ret;

    vfs_file_begin(pid);
    if (point->fs->close == NULL) {
        vfs_file_end(pid);
        seterrno(ENOSYS);
        return -1;
    }
    seterrno(0);
    if (atomic_dec_and_test(&file->ref)) {
        ret = point->fs->close(point, file);
        if (ret == 0) {
            mutex_lock(&info_lock[pid], 0);
            info->files[fd] = NULL;
            mutex_unlock(&info_lock[pid]);
            vfs_file_free(file);
            atomic_dec(&point->ref);
            return ret;
        } else {
            atomic_inc(&file->ref);
        }
    } else {
        ret = 0;
    }
    vfs_file_end(pid);
    return ret;
}
Esempio n. 3
0
static int fatfs_mount(mount_point_t *point, device_t *dev, const char *dev_name, const char *param)
{
    FATFS *fs;
    FRESULT res;

    if (dev == NULL) {
        seterrno(EINVAL);
        return -1;
    }

    fs = (FATFS *)kmalloc(sizeof(FATFS), GFP_KERNEL);
    if (fs != NULL) {
        memset(fs, 0, sizeof(FATFS));
        res = f_mount(0, fs);
        if (res != FR_OK) {
            fatfs_result_to_errno(res);
            kfree(fs);
            return -1;
        } else {
            point->ctx = fs;
            fs->drv    = dev;
            return 0;
        }
    } else {
        seterrno(ENOMEM);
        return -1;
    }
}
Esempio n. 4
0
/*********************************************************************************************************
** Function name:           vfs_write
** Descriptions:            写文件
** input parameters:        fd                  文件描述符
**                          buf                 数据缓冲区
**                          len                 新长度
** output parameters:       NONE
** Returned value:          成功写入的字节数 OR -1
*********************************************************************************************************/
ssize_t vfs_write(int fd, const void *buf, size_t len)
{
    ssize_t slen;
    pid_t pid = getpid();

    if (buf == NULL || len < 0) {
        seterrno(EINVAL);
        return -1;
    }

    if (len == 0) {
        seterrno(0);
        return 0;
    }

    {
        vfs_file_begin(pid);
        if (!(file->flags & FWRITE)) {
            vfs_file_end(pid);
            seterrno(EIO);
            return -1;
        }
        if (point->fs->write == NULL) {
            vfs_file_end(pid);
            seterrno(ENOSYS);
            return -1;
        }
        seterrno(0);
        slen = point->fs->write(point, file, buf, len);
        vfs_file_end(pid);
        return slen;
    }
}
Esempio n. 5
0
/** \brief Initialise a \e libcaca canvas.
 *
 *  Initialise internal \e libcaca structures and the backend that will
 *  be used for subsequent graphical operations. It must be the first
 *  \e libcaca function to be called in a function. caca_free_canvas()
 *  should be called at the end of the program to free all allocated resources.
 *
 *  Both the cursor and the canvas' handle are initialised at the top-left
 *  corner.
 *
 *  If an error occurs, NULL is returned and \b errno is set accordingly:
 *  - \c EINVAL Specified width or height is invalid.
 *  - \c ENOMEM Not enough memory for the requested canvas size.
 *
 *  \param width The desired canvas width
 *  \param height The desired canvas height
 *  \return A libcaca canvas handle upon success, NULL if an error occurred.
 */
caca_canvas_t * caca_create_canvas(int width, int height)
{
    caca_canvas_t *cv;

    if(width < 0 || height < 0)
    {
        seterrno(EINVAL);
        return NULL;
    }

    cv = malloc(sizeof(caca_canvas_t));

    if(!cv)
        goto nomem;

    cv->refcount = 0;
    cv->autoinc = 0;
    cv->resize_callback = NULL;
    cv->resize_data = NULL;

    cv->frame = 0;
    cv->framecount = 1;
    cv->frames = malloc(sizeof(struct caca_frame));
    if(!cv->frames)
    {
        free(cv);
        goto nomem;
    }

    cv->frames[0].width = cv->frames[0].height = 0;
    cv->frames[0].chars = NULL;
    cv->frames[0].attrs = NULL;
    cv->frames[0].x = cv->frames[0].y = 0;
    cv->frames[0].handlex = cv->frames[0].handley = 0;
    cv->frames[0].curattr = 0;
    cv->frames[0].name = strdup("frame#00000000");

    _caca_load_frame_info(cv);
    caca_set_color_ansi(cv, CACA_DEFAULT, CACA_TRANSPARENT);

    cv->ndirty = 0;
    cv->dirty_disabled = 0;
    cv->ff = NULL;

    if(caca_resize(cv, width, height) < 0)
    {
        int saved_errno = geterrno();
        free(cv->frames[0].name);
        free(cv->frames);
        free(cv);
        seterrno(saved_errno);
        return NULL;
    }

    return cv;

nomem:
    seterrno(ENOMEM);
    return NULL;
}
Esempio n. 6
0
/*
 * 写 xxx
 */
static ssize_t xxx_write(void *ctx, file_t *file, const void *buf, size_t len)
{
    privinfo_t *priv = ctx;
    int ret;

    if (priv == NULL) {
        seterrno(EINVAL);
        return -1;
    }

    __again:
    if (atomic_read(&priv->select.flags) & VFS_FILE_ERROR) {
        seterrno(EIO);
        return -1;
    }

    if (0) {                                                            /*  如果没有空间可写            */
        ret = vfs_block_helper(&priv->select, xxx_scan, ctx, file, VFS_FILE_WRITEABLE);
        if (ret <= 0) {
            return ret;
        } else {
            goto __again;
        }
    }

    {
        /*
         * 完成写操作
         */
        return 0;
    }
}
Esempio n. 7
0
/*********************************************************************************************************
** Function name:           socket_priv_fd
** Descriptions:            获得 socket 的私有文件描述符
** input parameters:        fd                  IO 系统文件描述符
** output parameters:       ctx                 上下文
** Returned value:          socket 的私有文件描述符
*********************************************************************************************************/
int socket_priv_fd(int fd, void **ctx)
{
    file_t *file;
    device_t *dev;
    privinfo_t *priv;
    int sock_fd;

    file = vfs_get_file(fd);
    if (file != NULL) {
        if (file->type & VFS_FILE_TYPE_SOCK) {
            dev = file->ctx;
            if (dev != NULL) {
                priv = dev->ctx;
                if (priv != NULL) {
                    sock_fd = priv->sock_fd;
                    *ctx = file;
                    seterrno(0);
                    return sock_fd;
                }
            }
        }
        seterrno(EFTYPE);
    }
    return -1;
}
Esempio n. 8
0
/*
 * 扫描 socket
 */
static int socket_scan(void *ctx, file_t *file, int flags)
{
    privinfo_t *priv = ctx;
    int ret;
    int readable;
    int writeable;
    int error;

    if (priv == NULL) {
        seterrno(EINVAL);
        return -1;
    }

    extern int socket_stat(int sock_fd, int *readable, int *writeable, int *error);
    ret = socket_stat(priv->sock_fd, &readable, &writeable, &error);
    if (ret < 0) {
        seterrno(EINVAL);
        return -1;
    }

    ret = 0;
    if (readable && flags & VFS_FILE_READABLE) {
        ret |= VFS_FILE_READABLE;
    }
    if (writeable && flags & VFS_FILE_WRITEABLE) {
        ret |= VFS_FILE_WRITEABLE;
    }
    if (error && flags & VFS_FILE_ERROR) {
        ret |= VFS_FILE_ERROR;
    }
    return ret;
}
Esempio n. 9
0
/*********************************************************************************************************
** Function name:           vfs_ftruncate
** Descriptions:            修改文件长度
** input parameters:        fd                  文件描述符
**                          len                 新长度
** output parameters:       NONE
** Returned value:          0 OR -1
*********************************************************************************************************/
int vfs_ftruncate(int fd, off_t len)
{
    int ret;
    pid_t pid = getpid();

    if (len < 0) {
        seterrno(EINVAL);
        return -1;
    }

    vfs_file_begin(pid);
    if (!(file->flags & FWRITE)) {
        vfs_file_end(pid);
        seterrno(EIO);
        return -1;
    }
    if (point->fs->ftruncate == NULL) {
        vfs_file_end(pid);
        seterrno(ENOSYS);
        return -1;
    }
    seterrno(0);
    ret = point->fs->ftruncate(point, file, len);
    vfs_file_end(pid);
    return ret;
}
Esempio n. 10
0
/*********************************************************************************************************
** Function name:           socket_attach
** Descriptions:            联结 socket
** input parameters:        sock_fd             socket 的私有文件描述符
** output parameters:       NONE
** Returned value:          IO 系统文件描述符
*********************************************************************************************************/
int socket_attach(int sock_fd)
{
    char path[PATH_MAX];
    int fd;
    privinfo_t *priv;
    reg_t reg;
    file_t *file;
    int err;

    priv = kmalloc(sizeof(privinfo_t), GFP_KERNEL);
    if (priv != NULL) {
        priv->sock_fd = sock_fd;

        device_init(priv);

        sprintf(path, "/dev/socket%d", sock_fd);

        reg = interrupt_disable();

        if (device_create(path, "socket", priv) < 0) {
            interrupt_resume(reg);
            kfree(priv);
            return -1;
        }

        fd = vfs_open(path, O_RDWR, 0666);
        if (fd < 0) {
            geterrno(err);
            vfs_unlink(path);
            seterrno(err);
            interrupt_resume(reg);
            kfree(priv);
            return -1;
        }

        file = vfs_get_file(fd);
        if (file == NULL) {
            geterrno(err);
            vfs_close(fd);
            vfs_unlink(path);
            seterrno(err);
            interrupt_resume(reg);
            kfree(priv);
            return -1;
        }

        file->type = VFS_FILE_TYPE_SOCK;
        vfs_put_file(file);

        lwip_socket_set_ctx(sock_fd, priv);

        interrupt_resume(reg);
        seterrno(0);
        return fd;
    } else {
        seterrno(ENOMEM);
        return -1;
    }
}
Esempio n. 11
0
/*********************************************************************************************************
** Function name:           vfs_unmount
** Descriptions:            取消挂载文件系统
** input parameters:        path                目录 PATH
**                          param               参数
** output parameters:       NONE
** Returned value:          0 OR -1
*********************************************************************************************************/
int vfs_unmount(const char *path, const char *param)
{
    mount_point_t  *point;
    char           *pathbuf;
    char           *filepath;
    int             ret;

    pathbuf = kmalloc(PATH_BUF_LEN, GFP_KERNEL);
    if (pathbuf == NULL) {
        seterrno(ENOMEM);
        return -1;
    }

    mutex_lock(&mount_point_lock, 0);

    point = vfs_mount_point_lookup2(pathbuf, &filepath, path);          /*  查找挂载点                  */
    if (point == NULL) {
        mutex_unlock(&mount_point_lock);
        kfree(pathbuf);
        return -1;
    }

    if (point->fs->unmount == NULL) {
        mutex_unlock(&mount_point_lock);
        kfree(pathbuf);
        seterrno(ENOSYS);
        return -1;
    }

    if (atomic_read(&point->ref) != 0) {
        mutex_unlock(&mount_point_lock);
        kfree(pathbuf);
        seterrno(EBUSY);
        return -1;
    }

    vfs_sync(path);

    seterrno(0);
    ret = point->fs->unmount(point, param);                             /*  取消挂载文件系统            */
    if (ret == 0) {
        if (point->dev != NULL) {
            atomic_dec(&point->dev->ref);
        }
        atomic_dec(&point->fs->ref);
        mount_point_remove(point);
    }

    mutex_unlock(&mount_point_lock);

    kfree(pathbuf);

    return ret;
}
Esempio n. 12
0
static long fatfs_telldir(mount_point_t *point, file_t *file)
{
    privinfo_t *priv = file->ctx;

    if (priv == NULL) {
        seterrno(EINVAL);
        return -1;
    }

    seterrno(ENOSYS);
    return -1;
}
Esempio n. 13
0
static int fatfs_seekdir(mount_point_t *point, file_t *file, long loc)
{
    privinfo_t *priv = file->ctx;

    if (priv == NULL) {
        seterrno(EINVAL);
        return -1;
    }

    seterrno(ENOSYS);
    return -1;
}
Esempio n. 14
0
static int fatfs_ioctl(mount_point_t *point, file_t *file, int cmd, void *arg)
{
    privinfo_t *priv = file->ctx;

    if (priv == NULL) {
        seterrno(EINVAL);
        return -1;
    }

    seterrno(ENOSYS);
    return -1;
}
Esempio n. 15
0
/*
 * 写 socket
 */
static ssize_t socket_write(void *ctx, file_t *file, const void *buf, size_t len)
{
    privinfo_t *priv = ctx;

    if (priv == NULL) {
        seterrno(EINVAL);
        return -1;
    }
    if (atomic_read(&priv->select.flags) & VFS_FILE_ERROR) {
        seterrno(EIO);
        return -1;
    }

    return lwip_send(priv->sock_fd, buf, len, 0);
}
Esempio n. 16
0
/*
 * 控制 socket
 */
static int socket_ioctl(void *ctx, file_t *file, int cmd, void *arg)
{
    privinfo_t *priv = ctx;

    if (priv == NULL) {
        seterrno(EINVAL);
        return -1;
    }
    if (atomic_read(&priv->select.flags) & VFS_FILE_ERROR) {
        seterrno(EIO);
        return -1;
    }

    return lwip_ioctl(priv->sock_fd, cmd, ua_to_ka(arg));
}
Esempio n. 17
0
/*
 * 控制 xxx
 */
static int xxx_ioctl(void *ctx, file_t *file, int cmd, void *arg)
{
    privinfo_t *priv = ctx;

    if (priv == NULL) {
        seterrno(EINVAL);
        return -1;
    }
    if (atomic_read(&priv->select.flags) & VFS_FILE_ERROR) {
        seterrno(EIO);
        return -1;
    }

    return 0;
}
Esempio n. 18
0
int
fchmod(int fd, mode_t mode)
{
	Dir d, *dir;

	dir = _dirfstat(fd);
	if(dir == nil)
		return seterrno();
	_nulldir(&d);
	d.mode = (dir->mode & ~0777) | (mode & 0777);
	free(dir);
	if(_dirfwstat(fd, &d) < 0)
		return seterrno();
	return 0;
}
Esempio n. 19
0
int
chmod(const char *path, mode_t mode)
{
	Dir d, *dir;

	dir = _dirstat(path);
	if(dir == nil)
		return seterrno();
	_nulldir(&d);
	d.mode = (dir->mode & ~0777) | (mode & 0777);
	free(dir);
	if(_dirwstat(path, &d) < 0)
		return seterrno();
	return 0;
}
Esempio n. 20
0
/*********************************************************************************************************
** Function name:           vfs_lseek
** Descriptions:            调整文件读写位置
** input parameters:        fd                  文件描述符
**                          offset              偏移
**                          whence              调整的位置
** output parameters:       NONE
** Returned value:          新的读写位置 OR -1
*********************************************************************************************************/
off_t vfs_lseek(int fd, off_t offset, int whence)
{
    pid_t pid = getpid();

    vfs_file_begin(pid);
    if (point->fs->lseek == NULL) {
        vfs_file_end(pid);
        seterrno(ENOSYS);
        return -1;
    }
    seterrno(0);
    offset = point->fs->lseek(point, file, offset, whence);
    vfs_file_end(pid);
    return offset;
}
Esempio n. 21
0
/*********************************************************************************************************
** Function name:           vfs_mount_point_lookup
** Descriptions:            查找挂载点, PATH 不能是挂载点
** input parameters:        pathbuf             路径临时缓冲区
**                          path                路径
** output parameters:       ppath               指向去掉挂载点后的路径
** Returned value:          挂载点 OR NULL
*********************************************************************************************************/
mount_point_t *vfs_mount_point_lookup(char pathbuf[PATH_BUF_LEN], char **ppath, const char *path)
{
    mount_point_t *point;
    char          *tmp;

    if (path == NULL || strlen(path) > PATH_MAX - 1) {                  /*  PATH 合法性检查             */
        seterrno(EINVAL);
        return NULL;
    }

    if (path[0] == '/') {                                               /*  如果是绝对路径              */
        if (path[1] == '\0') {                                          /*  不能是根目录                */
            seterrno(EINVAL);
            return NULL;
        }
        strlcpy(pathbuf, path, PATH_MAX);
    } else {                                                            /*  如果是相对路径              */
        /*
         * cwd 要以 / 号开头和结尾
         */
        int tid = gettid();
        snprintf(pathbuf, PATH_BUF_LEN, "%s%s", cwd[tid], path);        /*  在前面加入当前工作目录      */
    }

    if (vfs_path_normalization(pathbuf, FALSE) < 0) {                   /*  正常化 PATH                 */
        return NULL;
    }

    tmp = strchr(pathbuf + 1, '/');                                     /*  查找挂载点名后的 / 号       */
    if (tmp == NULL) {                                                  /*  没有到                      */
        seterrno(EINVAL);
        return NULL;
    }
    if (tmp[1] == '\0') {                                               /*  不能是挂载点                */
        seterrno(EINVAL);
        return NULL;
    }

    *tmp  = '\0';                                                       /*  暂时去掉 / 号               */
    point = mount_point_lookup(pathbuf);                                /*  查找挂载点                  */
    *tmp  = '/';                                                        /*  恢复 / 号                   */

    *ppath = tmp;
    if (point == NULL) {
        seterrno(ENOENT);
    }
    return point;
}
Esempio n. 22
0
/*
 * 关闭 socket
 */
static int socket_close(void *ctx, file_t *file)
{
    privinfo_t *priv = ctx;
    reg_t reg;

    if (priv == NULL) {
        seterrno(EINVAL);
        return -1;
    }

    reg = interrupt_disable();

    atomic_dec(dev_ref(file));

    device_remove(file->ctx);

    file->ctx = NULL;

    lwip_close(priv->sock_fd);

    kfree(priv);

    interrupt_resume(reg);

    return 0;
}
Esempio n. 23
0
/** \brief Remove an area from the dirty rectangle list.
 *
 *  Mark a cell area in the canvas as not dirty. For more information about
 *  the dirty rectangles, see caca_get_dirty_rect().
 *
 *  Values such that \b xmin > \b xmax or \b ymin > \b ymax indicate that
 *  the dirty rectangle is empty. They will be silently ignored.
 *
 *  If an error occurs, -1 is returned and \b errno is set accordingly:
 *  - \c EINVAL Specified rectangle coordinates are out of bounds.
 *
 *  \param cv A libcaca canvas.
 *  \param x The leftmost edge of the clean rectangle.
 *  \param y The topmost edge of the clean rectangle.
 *  \param width The width of the clean rectangle.
 *  \param height The height of the clean rectangle.
 *  \return 0 in case of success, -1 if an error occurred.
 */
int caca_remove_dirty_rect(caca_canvas_t *cv, int x, int y,
                           int width, int height)
{
    /* Clip arguments to canvas size */
    if(x < 0) { width += x; x = 0; }

    if(x + width > cv->width)
        width = cv->width - x;

    if(y < 0) { height += y; y = 0; }

    if(y + height > cv->height)
        height = cv->height - y;

    /* Ignore empty and out-of-canvas rectangles */
    if(width <= 0 || height <= 0)
    {
        seterrno(EINVAL);
        return -1;
    }

    /* FIXME: implement this function. It's OK to have it do nothing,
     * since we take a conservative approach in dirty rectangle handling,
     * but we ought to help the rendering eventually. */

    return 0;
}
Esempio n. 24
0
/*********************************************************************************************************
** Function name:           vfs_unselect_file
** Descriptions:            将当前任务从文件的等待列表中移除
** input parameters:        fd                  文件描述符
**                          flags               标志
** output parameters:       NONE
** Returned value:          0 OR -1
*********************************************************************************************************/
int vfs_unselect_file(int fd, int flags)
{
    int ret;
    pid_t pid = getpid();

    vfs_file_begin(pid);
    if (point->fs->unselect == NULL) {
        vfs_file_end(pid);
        seterrno(ENOSYS);
        return -1;
    }
    seterrno(0);
    ret = point->fs->unselect(point, file, flags);
    vfs_file_end(pid);
    return ret;
}
Esempio n. 25
0
/*********************************************************************************************************
** Function name:           vfs_dup2
** Descriptions:            复制文件描述符到指定的文件描述符
** input parameters:        fd                  文件描述符
**                          to                  指定的文件描述符
** output parameters:       NONE
** Returned value:          0 OR -1
*********************************************************************************************************/
int vfs_dup2(int fd, int to)
{
    int ret;
    pid_t pid = getpid();

    vfs_file_begin(pid);

    ret = vfs_close(to);
    if (ret < 0) {
        vfs_file_end(pid);
        return ret;
    }

    mutex_lock(&info_lock[pid], 0);

    info->files[to] = file;

    mutex_unlock(&info_lock[pid]);

    atomic_inc(&file->ref);

    atomic_inc(&point->ref);

    vfs_file_end(pid);

    seterrno(0);

    return 0;
}
Esempio n. 26
0
/*********************************************************************************************************
** Function name:           vfs_ioctl
** Descriptions:            控制文件
** input parameters:        fd                  文件描述符
**                          cmd                 命令
**                          arg                 参数
** output parameters:       NONE
** Returned value:          0 OR -1
*********************************************************************************************************/
int vfs_ioctl(int fd, int cmd, void *arg)
{
    int ret;
    pid_t pid = getpid();

    vfs_file_begin(pid);
    if (point->fs->ioctl == NULL) {
        vfs_file_end(pid);
        seterrno(ENOSYS);
        return -1;
    }
    seterrno(0);
    ret = point->fs->ioctl(point, file, cmd, arg);
    vfs_file_end(pid);
    return ret;
}
Esempio n. 27
0
static struct dirent *fatfs_readdir(mount_point_t *point, file_t *file)
{
    privinfo_t *priv = file->ctx;
    FRESULT res;

    if (priv != NULL) {
        FILINFO info;

        priv->entry.d_name[0] = '\0';

#if _USE_LFN
        info.lfname = priv->entry.d_name;
        info.lfsize = sizeof(priv->entry.d_name);
#endif

        res = f_readdir(&priv->dir, &info);
        if (res == FR_OK && info.fname[0] != '\0') {
#if _USE_LFN
            if (info.lfname[0] == '\0') {
                strlcpy(priv->entry.d_name, info.fname, sizeof(priv->entry.d_name));
            }
#else
            strlcpy(priv->entry.d_name, info.fname, sizeof(priv->entry.d_name));
#endif
            priv->entry.d_ino = 0;
            return &priv->entry;
        } else {
            fatfs_result_to_errno(res);
            return NULL;
        }
    } else {
        seterrno(EINVAL);
        return NULL;
    }
}
Esempio n. 28
0
/*********************************************************************************************************
** Function name:           vfs_fstat
** Descriptions:            判断文件是不是终端
** input parameters:        fd                  文件描述符
** output parameters:       NONE
** Returned value:          0 OR -1
*********************************************************************************************************/
int vfs_isatty(int fd)
{
    int ret;
    pid_t pid = getpid();

    vfs_file_begin(pid);
    if (point->fs->isatty == NULL) {
        vfs_file_end(pid);
        seterrno(0);
        return 0;
    }
    seterrno(0);
    ret = point->fs->isatty(point, file);
    vfs_file_end(pid);
    return ret;
}
Esempio n. 29
0
static int fatfs_access(mount_point_t *point, const char *path, int amode)
{
    struct stat buf;
    int ret;

    ret = fatfs_stat(point, path, &buf);
    if (ret == 0) {
        int access_ok = 1;

        if ((amode & R_OK) && !(buf.st_mode & S_IRUSR)) {
            access_ok = 0;
        }
        if ((amode & W_OK) && !(buf.st_mode & S_IWUSR)) {
            access_ok = 0;
        }
        if ((amode & X_OK) && !(buf.st_mode & S_IXUSR)) {
            access_ok = 0;
        }

        if (!access_ok) {
            seterrno(EACCES);
            return -1;
        } else {
            return 0;
        }
    } else {
        return ret;
    }
}
Esempio n. 30
0
/*********************************************************************************************************
** Function name:           mtdblock_create
** Descriptions:            创建 MTD 块设备
** input parameters:        path                MTD 块设备路径
**                          mtd_no              MTD 设备号
**                          start               开始块号
**                          end                 结束块号
**                          reserved            保留块数
**                          readonly            是否只读
** output parameters:       NONE
** Returned value:          0 OR -1
*********************************************************************************************************/
int mtdblock_create(const char *path,
                    long mtd_no,
                    long start,
                    long end,
                    long reserved,
                    bool_t readonly)
{
    privinfo_t *priv;

    if (path == NULL) {
        seterrno(EINVAL);
        return -1;
    }

    priv = kmalloc(sizeof(privinfo_t), GFP_KERNEL);
    if (priv != NULL) {
        device_init(priv);

        priv->reserved = reserved;
        priv->start    = start;
        priv->end      = end;
        priv->readonly = readonly;

        mutex_lock(&mtd_lock, 0);
        priv->mtd = get_mtd_device(NULL, mtd_no);
        mutex_unlock(&mtd_lock);

        if (priv->mtd == NULL) {
            kfree(priv);
            seterrno(EINVAL);
            return -1;
        }

        if (device_create(path, "mtdblock", priv) < 0) {
            mutex_lock(&mtd_lock, 0);
            put_mtd_device(priv->mtd);
            mutex_unlock(&mtd_lock);
            kfree(priv);
            return -1;
        }
        seterrno(0);
        return 0;
    } else {
        seterrno(ENOMEM);
        return -1;
    }
}