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 syslog_initialize(void) { FAR struct inode *inode; FAR const char *relpath = NULL; int ret; /* At this point, the only expected states are SYSLOG_UNINITIALIZED or * SYSLOG_REOPEN.. Not SYSLOG_INITIALIZING, SYSLOG_FAILURE, SYSLOG_OPENED. */ DEBUGASSERT(g_sysdev.sl_state == SYSLOG_UNINITIALIZED || g_sysdev.sl_state == SYSLOG_REOPEN); g_sysdev.sl_state = SYSLOG_INITIALIZING; /* Try to open the device. * * Note that we cannot just call open. The syslog device must work on all * threads. Open returns a file descriptor that is valid only for the * task that opened the device (and its pthread children). Instead, we * essentially re-implement the guts of open() here so that we can get to * the thread-independent structures of the inode. */ /* Get an inode for this file/device */ inode = inode_find(CONFIG_SYSLOG_DEVPATH, &relpath); if (!inode) { /* The inode was not found. In this case, we will attempt to re-open * the device repeatedly. The assumption is that the device path is * valid but that the driver has not yet been registered. */ g_sysdev.sl_state = SYSLOG_REOPEN; return -ENOENT; } /* Verify that the inode is valid and either a character driver or a * mountpoint. */ #ifndef CONFIG_DISABLE_MOUNTPOINT if ((!INODE_IS_DRIVER(inode) && !INODE_IS_MOUNTPT(inode))) #else if (!INODE_IS_DRIVER(inode)) #endif { ret = -ENXIO; goto errout_with_inode; } /* Make sure that the "entity" at this inode supports write access */ if (!inode->u.i_ops || !inode->u.i_ops->write) { ret = -EACCES; goto errout_with_inode; } /* Initialize the file structure */ g_sysdev.sl_file.f_oflags = SYSLOG_OFLAGS; g_sysdev.sl_file.f_pos = 0; g_sysdev.sl_file.f_inode = inode; /* Perform the low-level open operation. */ ret = OK; if (inode->u.i_ops->open) { /* Is the inode a mountpoint? */ #ifndef CONFIG_DISABLE_MOUNTPOINT if (INODE_IS_MOUNTPT(inode)) { /* Yes. Open the device write-only, try to create it if it * doesn't exist, if the file that already exists, then append the * new log data to end of the file. */ ret = inode->u.i_mops->open(&g_sysdev.sl_file, relpath, SYSLOG_OFLAGS, 0666); } /* No... then it must be a character driver in the NuttX pseudo- * file system. */ else #endif { ret = inode->u.i_ops->open(&g_sysdev.sl_file); } } /* Was the file/device successfully opened? */ if (ret < 0) { ret = -ret; goto errout_with_inode; } /* The SYSLOG device is open and ready for writing. */ sem_init(&g_sysdev.sl_sem, 0, 1); g_sysdev.sl_holder = NO_HOLDER; g_sysdev.sl_state = SYSLOG_OPENED; return OK; errout_with_inode: inode_release(inode); g_sysdev.sl_state = SYSLOG_FAILURE; return ret; }
int unlink(FAR const char *pathname) { FAR struct inode *inode; const char *relpath = NULL; int errcode; int ret; /* Get an inode for this file */ inode = inode_find(pathname, &relpath); if (!inode) { /* There is no inode that includes in this path */ errcode = ENOENT; goto errout; } #ifndef CONFIG_DISABLE_MOUNTPOINT /* Check if the inode is a valid mountpoint. */ if (INODE_IS_MOUNTPT(inode) && inode->u.i_mops) { /* Perform the unlink operation using the relative path at the * mountpoint. */ if (inode->u.i_mops->unlink) { ret = inode->u.i_mops->unlink(inode, relpath); if (ret < 0) { errcode = -ret; goto errout_with_inode; } } else { errcode = ENOSYS; goto errout_with_inode; } } else #endif #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS /* If this is a "dangling" pseudo-file node (i.e., it has operations) then rm * should remove the node. */ if (!INODE_IS_SPECIAL(inode) && inode->u.i_ops) { /* If this is a pseudo-file node (i.e., it has no operations) * then rmdir should remove the node. */ if (inode->u.i_ops) { inode_semtake(); /* Refuse to unlink the inode if it has children. I.e., if it is * functioning as a directory and the directory is not empty. */ if (inode->i_child != NULL) { errcode = ENOTEMPTY; inode_semgive(); goto errout_with_inode; } /* Notify the driver that it has been unlinked. If there are no * open references to the driver instance, then the driver should * release all resources because it is no longer accessible. */ if (INODE_IS_DRIVER(inode) && inode->u.i_ops->unlink) { /* Notify the character driver that it has been unlinked */ ret = inode->u.i_ops->unlink(inode); if (ret < 0) { errcode = -ret; goto errout_with_inode; } } #ifndef CONFIG_DISABLE_MOUNTPOINT else if (INODE_IS_BLOCK(inode) && inode->u.i_bops->unlink) { /* Notify the block driver that it has been unlinked */ ret = inode->u.i_bops->unlink(inode); if (ret < 0) { errcode = -ret; goto errout_with_inode; } } #endif /* Remove the old inode. Because we hold a reference count on the * inode, it will not be deleted now. It will be deleted when all * of the references to to the inode have been released (perhaps * when inode_release() is called below). inode_remove() will * return -EBUSY to indicate that the inode was not deleted now. */ ret = inode_remove(pathname); inode_semgive(); if (ret < 0 && ret != -EBUSY) { errcode = -ret; goto errout_with_inode; } } else { errcode = EISDIR; goto errout_with_inode; } } else #endif { errcode = ENXIO; goto errout_with_inode; } /* Successfully unlinked */ inode_release(inode); return OK; errout_with_inode: inode_release(inode); errout: set_errno(errcode); 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; }