static inline int fs_checkfd(FAR struct tcb_s *tcb, int fd, int oflags) { FAR struct file *filep; FAR struct inode *inode; int ret; DEBUGASSERT(tcb && tcb->group); /* Get the file structure corresponding to the file descriptor. */ ret = fs_getfilep(fd, &filep); if (ret < 0) { return ret; } /* Get the inode associated with the file descriptor. This should * normally be the case if fd >= 0. But not in the case where the * called attempts to explicitly stdin with fdopen(0) but stdin has * been closed. */ inode = filep->f_inode; if (!inode) { /* No inode -- descriptor does not correspond to an open file */ return -ENOENT; } /* Make sure that the inode supports the requested access. In * the case of fdopen, we are not actually creating the file -- in * particular w and w+ do not truncate the file and any files have * already been created. */ if (inode_checkflags(inode, oflags) != OK) { /* Cannot support the requested access */ return -EACCES; } /* Looks good to me */ return OK; }
static inline int fs_checkfd(FAR _TCB *tcb, int fd, int oflags) { FAR struct filelist *flist; FAR struct inode *inode; /* Get the file list from the TCB */ flist = tcb->filelist; /* Get the inode associated with the file descriptor. This should * normally be the case if fd >= 0. But not in the case where the * called attempts to explictly stdin with fdopen(0) but stdin has * been closed. */ inode = flist->fl_files[fd].f_inode; if (!inode) { /* No inode -- descriptor does not correspond to an open file */ return -ENOENT; } /* Make sure that the inode supports the requested access. In * the case of fdopen, we are not actually creating the file -- in * particular w and w+ do not truncate the file and any files have * already been created. */ if (inode_checkflags(inode, oflags) != OK) { /* Cannot support the requested access */ return -EACCES; } /* Looks good to me */ return OK; }
FAR struct file_struct *fs_fdopen(int fd, int oflags, FAR _TCB *tcb) { FAR struct filelist *flist; FAR struct streamlist *slist; FAR struct inode *inode; FAR FILE *stream; int err = OK; int ret; int i; /* Check input parameters */ if (fd < 0) { err = EBADF; goto errout; } /* A NULL TCB pointer means to use this threads TCB. This is a little * hack the let's this function be called from user-space (via a syscall) * without having access to the TCB. */ if (!tcb) { tcb = sched_self(); } /* Get the file and stream list from the TCB */ flist = tcb->filelist; slist = tcb->streams; /* Get the inode associated with the file descriptor. This should * normally be the case if fd >= 0. But not in the case where the * called attempts to explictly stdin with fdopen(0) but stdin has * been closed. */ inode = flist->fl_files[fd].f_inode; if (!inode) { err = ENOENT; goto errout; } /* Make sure that the inode supports the requested access. In * the case of fdopen, we are not actually creating the file -- in * particular w and w+ do not truncate the file and any files have * already been created. */ if (inode_checkflags(inode, oflags) != OK) { err = EACCES; goto errout; } /* Find an unallocated FILE structure */ ret = sem_wait(&slist->sl_sem); if (ret != OK) { goto errout_with_errno; } for (i = 0 ; i < CONFIG_NFILE_STREAMS; i++) { stream = &slist->sl_streams[i]; if (stream->fs_filedes < 0) { /* Zero the structure */ #if CONFIG_STDIO_BUFFER_SIZE > 0 memset(stream, 0, sizeof(FILE)); #elif CONFIG_NUNGET_CHARS > 0 stream->fs_nungotten = 0; #endif #if CONFIG_STDIO_BUFFER_SIZE > 0 /* Initialize the semaphore the manages access to the buffer */ (void)sem_init(&stream->fs_sem, 0, 1); /* Allocate the IO buffer */ stream->fs_bufstart = kmalloc(CONFIG_STDIO_BUFFER_SIZE); if (!stream) { err = ENOMEM; goto errout_with_sem; } /* Set up pointers */ stream->fs_bufend = &stream->fs_bufstart[CONFIG_STDIO_BUFFER_SIZE]; stream->fs_bufpos = stream->fs_bufstart; stream->fs_bufpos = stream->fs_bufstart; stream->fs_bufread = stream->fs_bufstart; #endif /* Save the file description and open flags. Setting the * file descriptor locks this stream. */ stream->fs_filedes = fd; stream->fs_oflags = oflags; sem_post(&slist->sl_sem); return stream; } } #if CONFIG_STDIO_BUFFER_SIZE > 0 errout_with_sem: #endif sem_post(&slist->sl_sem); errout: set_errno(err); errout_with_errno: return NULL; }
int open(const char *path, int oflags, ...) { FAR struct filelist *list; FAR struct inode *inode; FAR const char *relpath = NULL; #if defined(CONFIG_FILE_MODE) || !defined(CONFIG_DISABLE_MOUNTPOINT) mode_t mode = 0666; #endif int ret; int fd; /* Get the thread-specific file list */ list = sched_getfiles(); if (!list) { ret = EMFILE; goto errout; } #ifdef CONFIG_FILE_MODE # ifdef CONFIG_CPP_HAVE_WARNING # warning "File creation not implemented" # endif /* If the file is opened for creation, then get the mode bits */ if (oflags & (O_WRONLY|O_CREAT) != 0) { va_list ap; va_start(ap, oflags); mode = va_arg(ap, mode_t); va_end(ap); } #endif /* Get an inode for this file */ inode = inode_find(path, &relpath); if (!inode) { /* "O_CREAT is not set and the named file does not exist. Or, a * directory component in pathname does not exist or is a dangling * symbolic link." */ ret = ENOENT; goto errout; } /* Verify that the inode is valid and either a "normal" or a mountpoint. We * specifically exclude block drivers. */ #ifndef CONFIG_DISABLE_MOUNTPOINT if ((!INODE_IS_DRIVER(inode) && !INODE_IS_MOUNTPT(inode)) || !inode->u.i_ops) #else if (!INODE_IS_DRIVER(inode) || !inode->u.i_ops) #endif { ret = ENXIO; goto errout_with_inode; } /* Make sure that the inode supports the requested access */ ret = inode_checkflags(inode, oflags); if (ret < 0) { ret = -ret; goto errout_with_inode; } /* Associate the inode with a file structure */ fd = files_allocate(inode, oflags, 0, 0); if (fd < 0) { ret = EMFILE; goto errout_with_inode; } /* Perform the driver open operation. NOTE that the open method may be * called many times. The driver/mountpoint logic should handled this * because it may also be closed that many times. */ ret = OK; if (inode->u.i_ops->open) { #ifndef CONFIG_DISABLE_MOUNTPOINT if (INODE_IS_MOUNTPT(inode)) { ret = inode->u.i_mops->open((FAR struct file*)&list->fl_files[fd], relpath, oflags, mode); } else #endif { ret = inode->u.i_ops->open((FAR struct file*)&list->fl_files[fd]); } } if (ret < 0) { ret = -ret; goto errout_with_fd; } return fd; errout_with_fd: files_release(fd); errout_with_inode: inode_release(inode); errout: set_errno(ret); return ERROR; }
int open(const char *path, int oflags, ...) { FAR struct file *filep; FAR struct inode *inode; FAR const char *relpath = NULL; #if defined(CONFIG_FILE_MODE) || !defined(CONFIG_DISABLE_MOUNTPOINT) mode_t mode = 0666; #endif int ret; int fd; #ifdef CONFIG_FILE_MODE # ifdef CONFIG_CPP_HAVE_WARNING # warning "File creation not implemented" # endif /* If the file is opened for creation, then get the mode bits */ if ((oflags & (O_WRONLY | O_CREAT)) != 0) { va_list ap; va_start(ap, oflags); mode = va_arg(ap, mode_t); va_end(ap); } #endif /* Get an inode for this file */ inode = inode_find(path, &relpath); if (!inode) { /* "O_CREAT is not set and the named file does not exist. Or, a * directory component in pathname does not exist or is a dangling * symbolic link." */ ret = ENOENT; goto errout; } #if !defined(CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && \ !defined(CONFIG_DISABLE_MOUNTPOINT) /* If the inode is block driver, then we may return a character driver * proxy for the block driver. block_proxy() will instantiate a BCH * character driver wrapper around the block driver, open(), then * unlink() the character driver. On success, block_proxy() will * return the file descriptor of the opened character driver. * * NOTE: This will recurse to open the character driver proxy. */ if (INODE_IS_BLOCK(inode)) { /* Release the inode reference */ inode_release(inode); /* Get the file descriptor of the opened character driver proxy */ fd = block_proxy(path, oflags); if (fd < 0) { ret = fd; goto errout; } /* Return the file descriptor */ return fd; } else #endif /* Verify that the inode is either a "normal" character driver or a * mountpoint. We specifically "special" inodes (semaphores, message * queues, shared memory). */ #ifndef CONFIG_DISABLE_MOUNTPOINT if ((!INODE_IS_DRIVER(inode) && !INODE_IS_MOUNTPT(inode)) || !inode->u.i_ops) #else if (!INODE_IS_DRIVER(inode) || !inode->u.i_ops) #endif { ret = ENXIO; goto errout_with_inode; } /* Make sure that the inode supports the requested access */ ret = inode_checkflags(inode, oflags); if (ret < 0) { ret = -ret; goto errout_with_inode; } /* Associate the inode with a file structure */ fd = files_allocate(inode, oflags, 0, 0); if (fd < 0) { ret = EMFILE; goto errout_with_inode; } /* Get the file structure corresponding to the file descriptor. */ filep = fs_getfilep(fd); if (!filep) { /* The errno value has already been set */ return ERROR; } /* Perform the driver open operation. NOTE that the open method may be * called many times. The driver/mountpoint logic should handled this * because it may also be closed that many times. */ ret = OK; if (inode->u.i_ops->open) { #ifndef CONFIG_DISABLE_MOUNTPOINT if (INODE_IS_MOUNTPT(inode)) { ret = inode->u.i_mops->open(filep, relpath, oflags, mode); } else #endif { ret = inode->u.i_ops->open(filep); } } if (ret < 0) { ret = -ret; goto errout_with_fd; } return fd; errout_with_fd: files_release(fd); errout_with_inode: inode_release(inode); errout: set_errno(ret); return ERROR; }