| /**************************************************************************** |
| * fs/vfs/fs_fstat.c |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. The |
| * ASF licenses this file to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance with the |
| * License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations |
| * under the License. |
| * |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Included Files |
| ****************************************************************************/ |
| |
| #include <nuttx/config.h> |
| |
| #include <sys/stat.h> |
| #include <unistd.h> |
| #include <sched.h> |
| #include <assert.h> |
| #include <errno.h> |
| |
| #include <nuttx/fs/fs.h> |
| #include <nuttx/mtd/mtd.h> |
| #include "inode/inode.h" |
| |
| /**************************************************************************** |
| * Private Functions |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Name: proxy_fstat |
| * |
| * Description: |
| * Check for special cases where the character driver is really just a |
| * proxy for the real, underlying MTD or block driver. |
| * |
| * NOTE: This must be done here rather than in the the common |
| * inode_stat() function because the filep reference must be available |
| * in order to call the character driver ioctl method. |
| * |
| * Input Parameters: |
| * filep - File structure instance |
| * inode - The inode associated with the file descriptor |
| * buf - The caller provide location in which to return information |
| * about the open file. |
| * |
| * Returned Value: |
| * Upon successful completion, 0 is returned. Otherwise, a negated errno |
| * value is returned. |
| * |
| ****************************************************************************/ |
| |
| static int proxy_fstat(FAR struct file *filep, FAR struct inode *inode, |
| FAR struct stat *buf) |
| { |
| #ifdef CONFIG_MTD |
| struct mtd_geometry_s mtdgeo; |
| #endif |
| #ifndef CONFIG_DISABLE_MOUNTPOINT |
| struct geometry blkgeo; |
| #endif |
| int ret = -ENOENT; |
| |
| /* Check if this is a valid character driver */ |
| |
| if (INODE_IS_DRIVER(inode) && |
| inode->u.i_ops != NULL && |
| inode->u.i_ops->ioctl != NULL) |
| { |
| #ifdef CONFIG_MTD |
| /* Check if this is a proxy for an MTD driver. In this case, both the |
| * MTDIOC_GEOMETRY ioctl and the BIOC_GEOMTRY will be supported by |
| * character driver. |
| */ |
| |
| if (inode->u.i_ops->ioctl(filep, MTDIOC_GEOMETRY, |
| (unsigned long)((uintptr_t)&mtdgeo)) >= 0) |
| { |
| memset(buf, 0, sizeof(struct stat)); |
| buf->st_mode = S_IFMTD; |
| buf->st_mode |= S_IROTH | S_IRGRP | S_IRUSR; |
| buf->st_mode |= S_IWOTH | S_IWGRP | S_IWUSR; |
| buf->st_size = mtdgeo.neraseblocks * mtdgeo.erasesize; |
| ret = OK; |
| } |
| #ifndef CONFIG_DISABLE_MOUNTPOINT |
| else |
| #endif |
| #endif |
| |
| #ifndef CONFIG_DISABLE_MOUNTPOINT |
| /* Check if this is a proxy for a block driver. In this case, only |
| * the BIOC_GEOMETRY ioctl will be supported. |
| */ |
| |
| if (inode->u.i_ops->ioctl(filep, BIOC_GEOMETRY, |
| (unsigned long)((uintptr_t)&blkgeo)) >= 0) |
| { |
| memset(buf, 0, sizeof(struct stat)); |
| buf->st_mode = S_IFBLK; |
| if (inode->u.i_ops->read) |
| { |
| buf->st_mode |= S_IROTH | S_IRGRP | S_IRUSR; |
| } |
| |
| if (inode->u.i_ops->write) |
| { |
| buf->st_mode |= S_IWOTH | S_IWGRP | S_IWUSR; |
| } |
| |
| if (blkgeo.geo_available) |
| { |
| buf->st_size = blkgeo.geo_nsectors * blkgeo.geo_sectorsize; |
| } |
| |
| ret = OK; |
| } |
| #endif |
| } |
| |
| return ret; |
| } |
| |
| /**************************************************************************** |
| * Public Functions |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Name: file_fstat |
| * |
| * Description: |
| * file_fstat() is an internal OS interface. It is functionally similar |
| * to the standard fstat() interface except: |
| * |
| * - It does not modify the errno variable, |
| * - It is not a cancellation point, |
| * - It does not handle socket descriptors, and |
| * - It accepts a file structure instance instead of file descriptor. |
| * |
| * Input Parameters: |
| * filep - File structure instance |
| * buf - The caller provide location in which to return information |
| * about the open file. |
| * |
| * Returned Value: |
| * Upon successful completion, 0 shall be returned. Otherwise, -1 shall be |
| * returned and errno set to indicate the error. |
| * |
| ****************************************************************************/ |
| |
| int file_fstat(FAR struct file *filep, FAR struct stat *buf) |
| { |
| FAR struct inode *inode; |
| int ret; |
| |
| DEBUGASSERT(filep != NULL); |
| |
| /* Get the inode from the file structure */ |
| |
| inode = filep->f_inode; |
| |
| /* Was this file opened ? */ |
| |
| if (!inode) |
| { |
| return -EBADF; |
| } |
| |
| /* The way we handle the stat depends on the type of inode that we |
| * are dealing with. |
| */ |
| |
| #ifndef CONFIG_DISABLE_MOUNTPOINT |
| if (INODE_IS_MOUNTPT(inode)) |
| { |
| /* The inode is a file system mountpoint. Verify that the mountpoint |
| * supports the fstat() method |
| */ |
| |
| ret = -ENOSYS; |
| if (inode->u.i_mops && inode->u.i_mops->fstat) |
| { |
| /* Perform the fstat() operation */ |
| |
| ret = inode->u.i_mops->fstat(filep, buf); |
| } |
| } |
| else |
| #endif |
| #ifdef CONFIG_NET |
| if (INODE_IS_SOCKET(inode)) |
| { |
| /* Let the networking logic handle the fstat() */ |
| |
| ret = psock_fstat(file_socket(filep), buf); |
| } |
| else |
| #endif |
| { |
| /* Check if the inode is a proxy for a block or MTD driver */ |
| |
| ret = proxy_fstat(filep, inode, buf); |
| if (ret < 0) |
| { |
| /* The inode is part of the root pseudo file system. */ |
| |
| ret = inode_stat(inode, buf, 0); |
| } |
| } |
| |
| return ret; |
| } |
| |
| int nx_fstat(int fd, FAR struct stat *buf) |
| { |
| FAR struct file *filep; |
| int ret; |
| |
| /* First, get the file structure. Note that on failure, |
| * fs_getfilep() will return the errno. |
| */ |
| |
| ret = fs_getfilep(fd, &filep); |
| if (ret >= 0) |
| { |
| /* Perform the fstat operation */ |
| |
| return file_fstat(filep, buf); |
| } |
| |
| return ret; |
| } |
| |
| /**************************************************************************** |
| * Name: fstat |
| * |
| * Description: |
| * The fstat() function will obtain information about an open file |
| * associated with the file descriptor 'fd', and will write it to the area |
| * pointed to by 'buf'. |
| * |
| * The 'buf' argument is a pointer to a stat structure, as defined in |
| * <sys/stat.h>, into which information is placed concerning the file. |
| * |
| * Input Parameters: |
| * fd - The file descriptor associated with the open file of interest |
| * buf - The caller provide location in which to return information about |
| * the open file. |
| * |
| * Returned Value: |
| * Upon successful completion, 0 shall be returned. Otherwise, -1 shall be |
| * returned and errno set to indicate the error. |
| * |
| ****************************************************************************/ |
| |
| int fstat(int fd, FAR struct stat *buf) |
| { |
| int ret; |
| |
| ret = nx_fstat(fd, buf); |
| if (ret < 0) |
| { |
| set_errno(-ret); |
| ret = ERROR; |
| } |
| |
| return ret; |
| } |