ssize_t read(int fd, FAR void *buf, size_t nbytes) { ssize_t ret; /* read() is a cancellation point */ (void)enter_cancellation_point(); /* Did we get a valid file descriptor? */ #if CONFIG_NFILE_DESCRIPTORS > 0 if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS) #endif { #if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 /* No.. If networking is enabled, read() is the same as recv() with * the flags parameter set to zero. Note that recv() sets * the errno variable. */ ret = recv(fd, buf, nbytes, 0); #else /* No networking... it is a bad descriptor in any event */ set_errno(EBADF); ret = ERROR; #endif } #if CONFIG_NFILE_DESCRIPTORS > 0 else { FAR struct file *filep; /* The descriptor is in a valid range to file descriptor... do the * read. First, get the file structure. Note that on failure, * fs_getfilep() will set the errno variable. */ filep = fs_getfilep(fd); if (filep == NULL) { /* The errno value has already been set */ ret = ERROR; } else { /* Then let file_read do all of the work. Note that file_read() * sets the errno variable. */ ret = file_read(filep, buf, nbytes); } } #endif leave_cancellation_point(); return ret; }
int fs_dupfd(int fd, int minfd) { FAR struct file *filep; int ret; /* Get the file structure corresponding to the file descriptor. */ ret = fs_getfilep(fd, &filep); if (ret < 0) { goto errout; } DEBUGASSERT(filep != NULL); /* Let file_dup() do the real work */ ret = file_dup(filep, minfd); if (ret < 0) { goto errout; } return OK; errout: set_errno(-ret); return ERROR; }
int fstat(int fd, FAR struct stat *buf) { FAR struct file *filep; int ret; /* Did we get a valid file descriptor? */ if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS) { #if CONFIG_NSOCKET_DESCRIPTORS > 0 /* Let the networking logic handle the fstat() */ ret = net_fstat(fd, buf); if (ret < 0) { goto errout; } return OK; #else /* No networking... it is just a bad descriptor */ ret = -EBADF; goto errout; #endif } /* The descriptor is in a valid range for a file descriptor... do the * fstat. First, get the file structure. Note that on failure, * fs_getfilep() will set the errno variable. */ ret = fs_getfilep(fd, &filep); if (ret < 0) { goto errout; } /* Perform the fstat operation */ ret = file_fstat(filep, buf); /* Check if the fstat operation was successful */ if (ret >= 0) { /* Successfully fstat'ed the file */ return OK; } errout: set_errno(-ret); return ERROR; }
int fcntl(int fd, int cmd, ...) { FAR struct file *filep; va_list ap; int ret; /* fcntl() is a cancellation point */ (void)enter_cancellation_point(); /* Setup to access the variable argument list */ va_start(ap, cmd); /* Did we get a valid file descriptor? */ #if CONFIG_NFILE_DESCRIPTORS > 0 if ((unsigned int)fd < CONFIG_NFILE_DESCRIPTORS) { /* Get the file structure corresponding to the file descriptor. */ filep = fs_getfilep(fd); if (!filep) { /* The errno value has already been set */ va_end(ap); leave_cancellation_point(); return ERROR; } /* Let file_vfcntl() do the real work */ ret = file_vfcntl(filep, cmd, ap); } else #endif { /* No... check for operations on a socket descriptor */ #if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 if ((unsigned int)fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) { /* Yes.. defer socket descriptor operations to net_vfcntl() */ ret = net_vfcntl(fd, cmd, ap); } else #endif { /* No.. this descriptor number is out of range */ set_errno(EBADF); ret = ERROR; } } va_end(ap); leave_cancellation_point(); return ret; }
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; }
off_t lseek(int fd, off_t offset, int whence) { FAR struct file *filep; /* Get the file structure corresponding to the file descriptor. */ filep = fs_getfilep(fd); if (!filep) { /* The errno value has already been set */ return (off_t)ERROR; } /* Then let file_seek do the real work */ return file_seek(filep, offset, whence); }
ssize_t pread(int fd, FAR void *buf, size_t nbytes, off_t offset) { FAR struct file *filep; /* Get the file structure corresponding to the file descriptor. */ filep = fs_getfilep(fd); if (!filep) { /* The errno value has already been set */ return (ssize_t)ERROR; } /* Let file_pread do the real work */ return file_pread(filep, buf, nbytes, offset); }
ssize_t sendfile(int outfd, int infd, off_t *offset, size_t count) { #if defined(CONFIG_NET_TCP) && CONFIG_NSOCKET_DESCRIPTORS > 0 /* Check the destination file descriptor: Is it a (probable) file * descriptor? Check the source file: Is it a normal file? */ if ((unsigned int)outfd >= CONFIG_NFILE_DESCRIPTORS && (unsigned int)infd < CONFIG_NFILE_DESCRIPTORS) { FAR struct file *filep; /* This appears to be a file-to-socket transfer. Get the file * structure. */ filep = fs_getfilep(fd); if (!filep) { /* The errno value has already been set */ return ERROR; } /* Then let net_sendfile do the work. */ return net_sendfile(outfd, filep, offset, count); } else #endif { /* No... then this is probably a file-to-file transfer. The generic * lib_sendfile() can handle that case. */ return lib_sendfile(outfd, infd, offset, count); } }
int fcntl(int fd, int cmd, ...) { FAR struct file *filep; va_list ap; int ret; /* fcntl() is a cancellation point */ (void)enter_cancellation_point(); /* Setup to access the variable argument list */ va_start(ap, cmd); /* Did we get a valid file descriptor? */ #if CONFIG_NFILE_DESCRIPTORS > 0 if ((unsigned int)fd < CONFIG_NFILE_DESCRIPTORS) { /* Get the file structure corresponding to the file descriptor. */ ret = fs_getfilep(fd, &filep); if (ret >= 0) { DEBUGASSERT(filep != NULL); /* Let file_vfcntl() do the real work. The errno is not set on * failures. */ ret = file_vfcntl(filep, cmd, ap); } } else #endif { /* No... check for operations on a socket descriptor */ #if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 if ((unsigned int)fd < (CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS)) { /* Yes.. defer socket descriptor operations to net_vfcntl(). The * errno is not set on failures. */ ret = net_vfcntl(fd, cmd, ap); } else #endif { /* No.. this descriptor number is out of range */ ret = -EBADF; } } va_end(ap); if (ret < 0) { set_errno(-ret); ret = ERROR; } leave_cancellation_point(); return ret; }
ssize_t writev(int fd, FAR const struct iovec *iov, int iovcnt) { int seg; #if CONFIG_NFILE_DESCRIPTORS > 0 FAR struct file *filep; #endif /* check the input parameters */ if (iov == NULL || iovcnt == 0) { return 0; } if (iovcnt > UIO_MAXIOV) { set_errno(EINVAL); return ERROR; } for (seg = 0; seg < iovcnt; seg++) { void *buf = iov[seg].iov_base; ssize_t len = (ssize_t)iov[seg].iov_len; if (len < 0 || buf == NULL) { set_errno(EINVAL); return ERROR; } } /* Did we get a valid file descriptor? */ #if CONFIG_NFILE_DESCRIPTORS > 0 if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS) #endif { /* Write to a socket descriptor is equivalent to send with flags == 0 */ #if defined(CONFIG_NET_TCP) && CONFIG_NSOCKET_DESCRIPTORS > 0 return sock_sendv(fd, iov, iovcnt); #else set_errno(EBADF); return ERROR; #endif } #if CONFIG_NFILE_DESCRIPTORS > 0 /* The descriptor is in the right range to be a file descriptor... write * to the file. */ filep = fs_getfilep(fd); if (!filep) { /* The errno value has already been set */ return ERROR; } /* Perform the write operation using the file descriptor as an index */ return file_writev(filep, iov, iovcnt); #endif }
FAR struct aio_container_s *aio_contain(FAR struct aiocb *aiocbp) { FAR struct aio_container_s *aioc; union { #ifdef AIO_HAVE_FILEP FAR struct file *filep; #endif #ifdef AIO_HAVE_FILEP FAR struct socket *psock; #endif FAR void *ptr; } u; #ifdef CONFIG_PRIORITY_INHERITANCE struct sched_param param; #endif #if defined(AIO_HAVE_FILEP) && defined(AIO_HAVE_PSOCK) if (aiocbp->aio_fildes >= CONFIG_NFILE_DESCRIPTORS) #endif #ifdef AIO_HAVE_FILEP { /* Get the file structure corresponding to the file descriptor. */ u.filep = fs_getfilep(aiocbp->aio_fildes); if (!u.filep) { /* The errno value has already been set */ return NULL; } } #endif #if defined(AIO_HAVE_FILEP) && defined(AIO_HAVE_PSOCK) else #endif #ifdef AIO_HAVE_PSOCK { /* Get the socket structure corresponding to the socket descriptor */ u.psock = sockfd_socket(aiocbp->aio_fildes); if (!u.psock) { /* Does not set the errno. EBADF is the most likely explanation. */ set_errno(EBADF); return NULL; } } #endif /* Allocate the AIO control block container, waiting for one to become * available if necessary. This should never fail. */ aioc = aioc_alloc(); DEBUGASSERT(aioc); /* Initialize the container */ memset(aioc, 0, sizeof(struct aio_container_s)); aioc->aioc_aiocbp = aiocbp; aioc->u.aioc_filep = u.ptr; aioc->aioc_pid = getpid(); #ifdef CONFIG_PRIORITY_INHERITANCE DEBUGVERIFY(sched_getparam (aioc->aioc_pid, ¶m)); aioc->aioc_prio = param.sched_priority; #endif /* Add the container to the pending transfer list. */ aio_lock(); dq_addlast(&aioc->aioc_link, &g_aio_pending); aio_unlock(); return aioc; }
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; }