add OpenHarmony 1.0 baseline

This commit is contained in:
wenjun
2020-09-08 10:21:40 +08:00
parent 1fbeabe0a6
commit 4cd89633bd
105 changed files with 90541 additions and 0 deletions
+13
View File
@@ -0,0 +1,13 @@
### 该问题是怎么引起的?
### 重现步骤
### 报错信息
+15
View File
@@ -0,0 +1,15 @@
### 相关的Issue
### 原因(目的、解决的问题等)
### 描述(做了什么,变更了什么)
### 测试用例(新增、改动、可能影响的功能)
Executable
+2
View File
@@ -0,0 +1,2 @@
*.swp
cscope.*
Executable
+296
View File
@@ -0,0 +1,296 @@
COPYING
=======
Describes the terms under which Nuttx is distributed. A copy of the BSD-
style licensing is included in this file. In my words -- I believe that you
should free to use NuttX in any environment, private, private, commercial,
open, closed, etc. provided only that you respect the modest copyright
notices as described in license (below), respect Trademarks, and include a
copy of the BSD license. Please feel free to contact me if you have any
icensing concerns.
Tool Licenses
-------------
Tools under the nuttx/tools directory are not intended for binary
distribution. You may find other licensing on individual tools in that
directory. If you intend to redistribute these tools in binary form, please
respect the individual license of each tool as identified in the file header
of the tool source files.
Copyright Date Notation
-----------------------
Copyright information is provided in the header of each file. This
copyright information includes the name of the copyright holder and the
year(s) in which copyrighted additions to the file were made to the file.
A comma (',') is used to separate years in the list of years. A hyphen ('-')
is used as a more compact notation when additions were made over several
consecutive years. So for example, "2007, 2011" would mean that copyrighted
additions were made during the years of 2007 and 2011 whereas "2007-2011"
would indicate copyrighted additions in the years 2007, 2008, 2009, 2010,
and 2011.
Copyright Line Continuation
---------------------------
Copy information which exceeds the usable line lengh may be broken and
continued on the following line, such as:
Copyright (C) 2007-2010, 2012, 2014-2015, 2017 Gregory Nutt. All
rights reserved.
NuttX
=====
License for NuttX in general (authorship and copyright dates on individual
files will vary):
/****************************************************************************
* directory path/filename
*
* Copyright (C) 2007-2019 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
FAT Long File Names
===================
NOTE: If CONFIG_FAT_LFN is defined in your NuttX configuration file, then
there may be some legal, patent issues. The following was extracted from
the entry "File Allocation Table from Wikipedia, the free encyclopedia:
"On December 3, 2003 Microsoft announced it would be offering licenses
for use of its FAT specification and 'associated intellectual property',
at the cost of a US$0.25 royalty per unit sold, with a $250,000 maximum
royalty per license agreement.
o "U.S. Patent 5,745,902 (http://www.google.com/patents?vid=5745902) -
Method and system for accessing a file using file names having
different file name formats. ...
o "U.S. Patent 5,579,517 (http://www.google.com/patents?vid=5579517) -
Common name space for long and short filenames. ...
o "U.S. Patent 5,758,352 (http://www.google.com/patents?vid=5758352) -
Common name space for long and short filenames. ...
o "U.S. Patent 6,286,013 (http://www.google.com/patents?vid=6286013) -
Method and system for providing a common name space for long and
short file names in an operating system. ...
"Many technical commentators have concluded that these patents only cover
FAT implementations that include support for long filenames, and that
removable solid state media and consumer devices only using short names
would be unaffected. ..."
This Wikipedia entry has been updated with recent legal decisions in favor
of Microsoft. Refer to:
https://en.wikipedia.org/wiki/File_Allocation_Table#Patents
So you have been forewarned: Use the long filename at your own risk!
uIP
===
Many lower-level networking components of NuttX derive from uIP which
has a similar BSD style license:
Copyright (c) 2001-2003, Adam Dunkels.
All rights reserved.
Rhombus Math Library
====================
The math library used in NuttX derives from the Rhombus OS by Nick Johnson
(with many, many addtions). The Rhombus OS is/was distributed under the ISC
license. The ISC licsense is a permissive license that allows people do
anything with your code with proper attribution and without warranty. The
ISC license is functionally equivalent to the BSD 2-Clause and MIT licenses,
removing some language that is no longer necessary.
IGMP
===
IGMP support, if enabled, adds additional logic by Steve Reynolds:
Copyright (c) 2002 CITEL Technologies Ltd.
All rights reserved.
The HID Parser in drivers/usbhost
=================================
Adapted from the LUFA Library (MIT license):
Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
dean [at] fourwalledcubicle [dot] com, www.lufa-lib.org
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
Certain functions in the NuttX C-library derive from other BSD-compatible
sources:
fs/nfs
======
NFS:
Copyright (c) 1989, 1991, 1993, 1995 The Regents of the University of
California. All rights reserved.
and RPC also has:
Copyright (c) 2004 The Regents of the University of Michigan.
Copyright (c) 2004 Weston Andros Adamson <muzzle@umich.edu>.
Copyright (c) 2004 Marius Aamodt Eriksen <marius@umich.edu>.
The University of Michigan uses a modified BSD license equivalent to
the NuttX license. The University of California code uses the original
BSD license and requires that I state the following:
"This product includes software developed by the University of
California, Berkeley and its contributors."
fs/spiffs
=========
The MIT License (MIT)
Copyright (c) 2013-2017 Peter Andersson (pelleplutt1976<at>gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
strtod()
========
Copyright (C) 2002 Michael Ringgaard. All rights reserved.
Copyright (C) 2006-2007 H. Peter Anvin.
dtoa()
======
If you enable floating point conversions with CONFIG_LIBC_FLOATINGPOINT,
then some files with an unmodified BSD license will be included. That
license is similar to the above (modified) BSD license, but has an
additional requirement that I state the following:
"This product includes software developed by the University of
California, Berkeley and its contributors."
libc/string/lib_vikmemcpy.c
===========================
If you enable CONFIG_MEMCPY_VIK, then you will build with the optimized
version of memcpy from Daniel Vik. Licensing information for that version
of memcpy() follows:
Copyright (C) 1999-2010 Daniel Vik
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you
must not claim that you wrote the original software. If you
use this software in a product, an acknowledgment in the
use this software in a product, an acknowledgment in the
product documentation would be appreciated but is not
required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
libs/libc/math
==============
If you enable CONFIG_LIB, you will build the math library at libc/math.
This library was taken from the math library developed for the Rhombus
OS by Nick Johnson (https://github.com/nickbjohnson4224/rhombus). This
port was contributed by Darcy Gong. The Rhombus math library has this
compatible MIT license:
Copyright (C) 2009-2011 Nick Johnson <nickbjohnson4224 at gmail.com>
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
drivers/video/ov2640
====================
WARNING: Some of the information in the data tables in this file came
from other projects with conflicting licenses: Linux and ArduCAM. Those
both have GPL licenses. I am not sure if it is proper or not to lift the
content of those tables and still retain this BSD license. I am guessing
so, but I am not a copyright attorney so you should use this driver in
products at your own risk.
Executable
+27615
View File
File diff suppressed because it is too large Load Diff
+125
View File
@@ -0,0 +1,125 @@
The Inviolable Principles of Nuttx
==================================
These are properties of NuttX that we can be certain of for all time:
Definition
----------
*in·vi·o·la·ble*
/inˈvīələbəl/
adjective
adjective: inviolable
never to be broken, infringed, or dishonored.
"an inviolable rule of chastity"
synonyms: inalienable, absolute, untouchable, unalterable,
unchallengeable, unbreakable, impregnable; sacrosanct,
sacred, holy, hallowed; rare intemerate
"the inviolable right to life"
Source: Oxford Dictionary of the English Language
Strict POSIX compliance
-----------------------
o Strict conformance to the portable standard OS interface as defined at
OpenGroup.org.
o A deeply embedded system requires some special support. Special
support must be minimized.
o The portable interface must never be compromised only for the sake of
expediency.
o Expediency or even improved performance are not justifications for
violation of the strict POSIX interface
Modular Architecture
--------------------
o The internal modular architecture of the OS must maintained.
o This means formalizing and documenting all internal interfaces (in the
porting guide), minimal use of global variables at the interface, and
only well defined functional interfaces.
Clear, Consistent, Standardized Coding Style
--------------------------------------------
o Strict conformance to the NuttX coding style. No "revolutionary"
changes to the coding standard (but perhaps some "evolutionary"
changes).
o Personal or organizational preference is not a justification for a
coding style change.
o Nothing can come into NuttX that does not follow the coding standard.
o Expediency is not a justification for violating the coding standard.
The NuttX coding standard can be found here:
http://www.nuttx.org/doku.php?id=documentation:codingstandard
Open and Unencumbered License
-----------------------------
o Currently BSD 3-clause or compatible: BSD 3-clause with constraints,
BSD 3 and 4 clause, MIT, public domain
o Other unencumbered licenses such as Apache may be considered
NuttX will never be licensed under a restrictive, "Copyleft" license.
All Users Matter
----------------
o All support must apply equally to all supported platforms. At present
this includes Linux, Windows MSYS, Windows Cygwin, Windows Ubuntu,
Windows native, macOS, Solaris, and FreeBSD. No tool/environment
solutions will be considered that limit the usage of NuttX on any of
the supported platforms.
o Inclusive rather than exclusive
o Hobbyists are valued users of the OS including retro computing hobbyists
* and DIY “Maker” hobbyists.
o Supported toolchains: GCC, Clang, SDCC, ZiLOG ZDS-II (c89), IAR.
Others?
o No changes to build system should limit use of NuttX by any user.
o Simplifying things for one user does not justify excluding another user.
o We should seek to expand the the NuttX user base, not to limit it for
reasons of preference or priority.
o We must resist the pull to make NuttX into a Linux-only, GCC-only, and
ARM-only solution.
NuttX Branding
--------------
o The official name of authentic Nuttx will always be "NuttX"
o This name is trademarked and may not be used by other OSs or forks of
NuttX
The Enemies
===========
No Short Cuts
-------------
o Doing things the easy way instead of the correct way.
o Reducing effort at the expense of Quality, Portability, or
Consistency
o Focus on the values of the organization, not the values of the Open
Source project. Need to support both.
o It takes work to support the Inviolables. There are no shortcuts.
Sometimes Code Duplication is OK
--------------------------------
o Sometimes is better to duplicate some logic than to introduce coupling
Keep the Big Picture
--------------------
o Too much focus on solving the problem in hand, loss of the Big Picture
o Insufficient understanding of the architectural principles.
Conform to Standards
--------------------
o Changing things only to suite a personal or organizational preference
o Inflexibility, Inability to adapt
o Not Invented Here (NIH) syndrome
Executable
+2355
View File
File diff suppressed because it is too large Load Diff
Executable
+26620
View File
File diff suppressed because it is too large Load Diff
+110
View File
@@ -0,0 +1,110 @@
/****************************************************************************
* drivers/bch/bch.h
*
* Copyright (C) 2008-2009, 2014-2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __DRIVERS_BCH_BCH_H
#define __DRIVERS_BCH_BCH_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <semaphore.h>
#include "fs/fs.h"
#include "disk.h"
#include "user_copy.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define bchlib_semgive(d) (void)sem_post(&(d)->sem) /* To match bchlib_semtake */
#define MAX_OPENCNT (255) /* Limit of uint8_t */
#define DIOC_GETPRIV (0x1000)
/****************************************************************************
* Public Types
****************************************************************************/
struct bchlib_s
{
struct inode *inode; /* I-node of the block driver */
uint32_t sectsize; /* The size of one sector on the device */
unsigned long long nsectors; /* Number of sectors supported by the device */
unsigned long long sector; /* The current sector in the buffer */
sem_t sem; /* For atomic accesses to this structure */
uint8_t refs; /* Number of references */
bool dirty; /* true: Data has been written to the buffer */
bool readonly; /* true: Only read operations are supported */
bool unlinked; /* true: The driver has been unlinked */
uint8_t *buffer; /* One sector buffer */
los_disk *disk;
unsigned long long sectstart;
};
/****************************************************************************
* Public Data
****************************************************************************/
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C" {
#else
#define EXTERN extern
#endif
EXTERN const struct file_operations_vfs bch_fops;
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
EXTERN void bchlib_semtake(struct bchlib_s *bch);
EXTERN int bchlib_flushsector(struct bchlib_s *bch);
EXTERN int bchlib_readsector(struct bchlib_s *bch, unsigned long long sector);
EXTERN int bchlib_setup(const char *blkdev, bool readonly, void **handle);
EXTERN int bchlib_teardown(void *handle);
EXTERN ssize_t bchlib_read(void *handle, char *buffer, loff_t offset, size_t len);
EXTERN ssize_t bchlib_write(void *handle, const char *buffer, loff_t offset, size_t len);
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif /* __DRIVERS_BCH_BCH_H */
+454
View File
@@ -0,0 +1,454 @@
/****************************************************************************
* drivers/bch/bchdev_driver.c
*
* Copyright (C) 2008-2009, 2014-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sched.h>
#include <errno.h>
#include <poll.h>
#include <assert.h>
#include <debug.h>
#include "bch.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static int bch_open(struct file *filep);
static int bch_close(struct file *filep);
static off_t bch_seek(struct file *filep, off_t offset, int whence);
static ssize_t bch_read(struct file *filep, char *buffer,
size_t buflen);
static ssize_t bch_write(struct file *filep, const char *buffer,
size_t buflen);
static int bch_ioctl(struct file *filep, int cmd,
unsigned long arg);
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
static int bch_unlink(struct inode *inode);
#endif
/****************************************************************************
* Public Data
****************************************************************************/
const struct file_operations_vfs bch_fops =
{
bch_open, /* open */
bch_close, /* close */
bch_read, /* read */
bch_write, /* write */
bch_seek, /* seek */
bch_ioctl, /* ioctl */
NULL, /* mmap */
#ifndef CONFIG_DISABLE_POLL
NULL, /* poll */
#endif
bch_unlink, /* unlink */
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: bch_open
*
* Description: Open the block device
*
****************************************************************************/
static int bch_open(FAR struct file *filep)
{
FAR struct inode *inode = filep->f_inode;
FAR struct bchlib_s *bch;
int ret = OK;
DEBUGASSERT(inode && inode->i_private);
bch = (FAR struct bchlib_s *)inode->i_private;
/* Increment the reference count */
bchlib_semtake(bch);
if (bch->refs == MAX_OPENCNT)
{
ret = -EMFILE;
}
else
{
bch->refs++;
}
bchlib_semgive(bch);
return ret;
}
/****************************************************************************
* Name: bch_close
*
* Description: close the block device
*
****************************************************************************/
static int bch_close(FAR struct file *filep)
{
FAR struct inode *inode = filep->f_inode;
FAR struct bchlib_s *bch;
int ret = OK;
DEBUGASSERT(inode && inode->i_private);
bch = (FAR struct bchlib_s *)inode->i_private;
/* Flush any dirty pages remaining in the cache */
bchlib_semtake(bch);
(void)bchlib_flushsector(bch);
/* Decrement the reference count (I don't use bchlib_decref() because I
* want the entire close operation to be atomic wrt other driver
* operations.
*/
if (bch->refs == 0)
{
ret = -EIO;
}
else
{
bch->refs--;
/* If the reference count decremented to zero AND if the character
* driver has been unlinked, then teardown the BCH device now.
*/
if (bch->refs == 0 && bch->unlinked)
{
/* Tear the driver down now. */
ret = bchlib_teardown((FAR void *)bch);
/* bchlib_teardown() would only fail if there are outstanding
* references on the device. Since we know that is not true, it
* should not fail at all.
*/
DEBUGASSERT(ret >= 0);
if (ret >= 0)
{
/* Return without releasing the stale semaphore */
return OK;
}
}
}
bchlib_semgive(bch);
return ret;
}
/****************************************************************************
* Name: bch_seek
****************************************************************************/
static off_t bch_seek(FAR struct file *filep, off_t offset, int whence)
{
FAR struct inode *inode = filep->f_inode;
FAR struct bchlib_s *bch;
loff_t newpos;
int ret;
DEBUGASSERT(inode && inode->i_private);
bch = (FAR struct bchlib_s *)inode->i_private;
bchlib_semtake(bch);
/* Determine the new, requested file position */
switch (whence)
{
case SEEK_CUR:
newpos = filep->f_pos + offset;
break;
case SEEK_SET:
newpos = offset;
break;
case SEEK_END:
newpos = (loff_t)bch->sectsize * bch->nsectors + offset;
break;
default:
/* Return EINVAL if the whence argument is invalid */
bchlib_semgive(bch);
return -EINVAL;
}
/* Opengroup.org:
*
* "The lseek() function shall allow the file offset to be set beyond the end
* of the existing data in the file. If data is later written at this point,
* subsequent reads of data in the gap shall return bytes with the value 0
* until data is actually written into the gap."
*
* We can conform to the first part, but not the second. But return EINVAL if
*
* "...the resulting file offset would be negative for a regular file, block
* special file, or directory."
*/
if (newpos >= 0)
{
filep->f_pos = newpos;
ret = newpos;
}
else
{
ret = -EINVAL;
}
bchlib_semgive(bch);
return ret;
}
/****************************************************************************
* Name: bch_read
****************************************************************************/
static ssize_t bch_read(FAR struct file *filep, FAR char *buffer, size_t len)
{
FAR struct inode *inode = filep->f_inode;
FAR struct bchlib_s *bch;
int ret;
DEBUGASSERT(inode && inode->i_private);
bch = (FAR struct bchlib_s *)inode->i_private;
bchlib_semtake(bch);
ret = bchlib_read(bch, buffer, filep->f_pos, len);
if (ret > 0)
{
filep->f_pos += len;
}
bchlib_semgive(bch);
return ret;
}
/****************************************************************************
* Name: bch_write
****************************************************************************/
static ssize_t bch_write(FAR struct file *filep, FAR const char *buffer, size_t len)
{
FAR struct inode *inode = filep->f_inode;
FAR struct bchlib_s *bch;
int ret = -EACCES;
DEBUGASSERT(inode && inode->i_private);
bch = (FAR struct bchlib_s *)inode->i_private;
if (!bch->readonly)
{
bchlib_semtake(bch);
ret = bchlib_write(bch, buffer, filep->f_pos, len);
if (ret > 0)
{
filep->f_pos += len;
}
bchlib_semgive(bch);
}
return ret;
}
/****************************************************************************
* Name: bch_ioctl
*
* Description:
* Handle IOCTL commands
*
****************************************************************************/
static int bch_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
FAR struct inode *inode = filep->f_inode;
FAR struct bchlib_s *bch;
int ret = -ENOTTY;
DEBUGASSERT(inode && inode->i_private);
bch = (FAR struct bchlib_s *)inode->i_private;
/* Process the call according to the command */
switch (cmd)
{
/* This isa request to get the private data structure */
case DIOC_GETPRIV:
{
FAR struct bchlib_s **bchr =
(FAR struct bchlib_s **)((uintptr_t)arg);
bchlib_semtake(bch);
if (!bchr || bch->refs == MAX_OPENCNT)
{
ret = -EINVAL;
}
else
{
bch->refs++;
ret = LOS_CopyFromKernel(bchr, sizeof(char *), &bch, sizeof(char *));
if (ret)
{
ret = -EFAULT;
}
else
{
ret = OK;
}
}
bchlib_semgive(bch);
}
break;
/* Otherwise, pass the IOCTL command on to the contained block driver. */
default:
{
struct inode *bchinode = bch->inode;
/* Does the block driver support the ioctl method? */
los_disk *disk = bch->disk;
if (disk == NULL)
{
ret = -1;
break;
}
if (pthread_mutex_lock(&disk->disk_mutex) != ENOERR)
{
PRINT_ERR("%s %d, mutex lock fail!\n", __FUNCTION__, __LINE__);
return -1;
}
if (disk->disk_status == STAT_INUSED)
{
if (bchinode->u.i_bops->ioctl != NULL)
{
ret = bchinode->u.i_bops->ioctl(bchinode, cmd, arg);
}
}
if (pthread_mutex_unlock(&disk->disk_mutex) != ENOERR)
{
PRINT_ERR("%s %d, mutex unlock fail!\n", __FUNCTION__, __LINE__);
return -1;
}
}
break;
}
return ret;
}
/****************************************************************************
* Name: bch_unlink
*
* Handle unlinking of the BCH device
*
****************************************************************************/
static int bch_unlink(FAR struct inode *inode)
{
FAR struct bchlib_s *bch;
int ret = OK;
DEBUGASSERT(inode && inode->i_private);
bch = (FAR struct bchlib_s *)inode->i_private;
/* Get exclusive access to the BCH device */
bchlib_semtake(bch);
/* Indicate that the driver has been unlinked */
bch->unlinked = true;
/* If there are no open references to the drvier then teardown the BCH
* device now.
*/
if (bch->refs == 0)
{
/* Tear the driver down now. */
ret = bchlib_teardown((FAR void *)bch);
/* bchlib_teardown() would only fail if there are outstanding
* references on the device. Since we know that is not true, it
* should not fail at all.
*/
DEBUGASSERT(ret >= 0);
if (ret >= 0)
{
/* Return without releasing the stale semaphore */
return OK;
}
}
bchlib_semgive(bch);
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
+84
View File
@@ -0,0 +1,84 @@
/****************************************************************************
* drivers/bch/bchdev_register.c
*
* Copyright (C) 2008-2009, 2012, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdbool.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include "bch.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: bchdev_register
*
* Description:
* Setup so that it exports the block driver referenced by 'blkdev' as a
* character device 'chardev'
*
****************************************************************************/
int bchdev_register(FAR const char *blkdev, FAR const char *chardev,
bool readonly)
{
FAR void *handle;
int ret;
/* Setup the BCH lib functions */
ret = bchlib_setup(blkdev, readonly, &handle);
if (ret < 0)
{
PRINTK("ERROR: bchlib_setup failed: %d\n", -ret);
return ret;
}
/* Then setup the character device */
ret = register_driver(chardev, &bch_fops, 0666, handle);
if (ret < 0)
{
PRINTK("ERROR: register_driver failed: %d\n", -ret);
(void)bchlib_teardown(handle);
handle = NULL;
}
return ret;
}
+137
View File
@@ -0,0 +1,137 @@
/****************************************************************************
* drivers/bch/bchdev_unregister.c
*
* Copyright (C) 2008-2009, 2012, 2016, 2018 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sched.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <sys/ioctl.h>
#include "bch.h"
#define _err PRINTK
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: bchdev_unregister
*
* Description:
* Unregister character driver access to a block device that was created
* by a previous call to bchdev_register().
*
****************************************************************************/
int bchdev_unregister(FAR const char *chardev)
{
FAR struct bchlib_s *bch;
int fd;
int ret;
/* Sanity check */
if (!chardev)
{
return -EINVAL;
}
/* Open the character driver associated with chardev */
fd = open(chardev, O_RDONLY);
if (fd < 0)
{
_err("ERROR: Failed to open %s: %d\n", chardev, errno);
return -errno;
}
/* Get a reference to the internal data structure. On success, we
* will hold a reference count on the state structure.
*/
ret = ioctl(fd, DIOC_GETPRIV, (unsigned long)((uintptr_t)&bch));
(void)close(fd);
if (ret < 0)
{
_err("ERROR: ioctl failed: %d\n", errno);
return -errno;
}
/* Lock out context switches. If there are no other references
* and no context switches, then we can assume that we can safely
* teardown the driver.
*/
LOS_TaskLock();
/* Check if the internal structure is non-busy (we hold one reference). */
if (bch->refs > 1)
{
ret = -EBUSY;
goto errout_with_lock;
}
/* Unregister the driver (this cannot suspend or we lose our non-preemptive
* state!). Once the driver is successfully unregistered, we can assume
* we have exclusive access to the state instance.
*/
ret = unregister_driver(chardev);
if (ret < 0)
{
goto errout_with_lock;
}
LOS_TaskUnlock();
/* Release the internal structure */
bch->refs = 0;
return bchlib_teardown(bch);
errout_with_lock:
bch->refs--;
LOS_TaskUnlock();
return ret;
}
+126
View File
@@ -0,0 +1,126 @@
/****************************************************************************
* drivers/bch/bchlib_cache.c
*
* Copyright (C) 2008-2009, 2014, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/types.h>
#include <stdbool.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include "bch.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: bchlib_flushsector
*
* Description:
* Flush the current contents of the sector buffer (if dirty)
*
* Assumptions:
* Caller must assume mutual exclusion
*
****************************************************************************/
int bchlib_flushsector(FAR struct bchlib_s *bch)
{
int ret = OK;
/* Check if the sector has been modified and is out of synch with the
* media.
*/
if (bch->dirty)
{
/* Write the sector to the media */
ret = los_disk_write(bch->disk->disk_id, (FAR const void *)bch->buffer, bch->sector, 1);
if (ret < 0)
{
PRINTK("bchlib_flushsector Write failed: %d\n", ret);
return ret;
}
/* The sector is now in sync with the media */
bch->dirty = false;
}
return ret;
}
/****************************************************************************
* Name: bchlib_readsector
*
* Description:
* Flush the current contents of the sector buffer (if dirty)
*
* Assumptions:
* Caller must assume mutual exclusion
*
****************************************************************************/
int bchlib_readsector(FAR struct bchlib_s *bch, unsigned long long sector)
{
int ret = OK;
if (bch->sector != sector)
{
ret = bchlib_flushsector(bch);
if (ret < 0)
{
return ret;
}
bch->sector = (unsigned long long)-1;
ret = los_disk_read(bch->disk->disk_id, (FAR void *)bch->buffer, sector, 1);
if (ret < 0)
{
PRINTK("Read failed: %d\n", ret);
return ret;
}
bch->sector = sector;
}
return ret;
}
+212
View File
@@ -0,0 +1,212 @@
/****************************************************************************
* drivers/bch/bchlib_read.c
*
* Copyright (C) 2008-2009, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/types.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include "bch.h"
#include <stdlib.h>
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: bchlib_read
*
* Description:
* Read from the block device set-up by bchlib_setup as if it were a character
* device.
*
****************************************************************************/
ssize_t bchlib_read(FAR void *handle, FAR char *buffer, loff_t offset, size_t len)
{
FAR struct bchlib_s *bch = (FAR struct bchlib_s *)handle;
size_t nsectors;
unsigned long long sector;
uint16_t sectoffset;
size_t nbytes;
size_t bytesread;
int ret;
/* Get rid of this special case right away */
if (len < 1)
{
return 0;
}
/* Convert the file position into a sector number an offset. */
sector = offset / bch->sectsize;
sectoffset = offset - sector * bch->sectsize;
if (sector >= bch->nsectors)
{
/* Return end-of-file */
return 0;
}
/* Read the initial partial sector */
bytesread = 0;
if (sectoffset > 0)
{
/* Read the sector into the sector buffer */
ret = bchlib_readsector(bch, sector + bch->sectstart);
if (ret < 0)
{
return bytesread;
}
/* Copy the tail end of the sector to the user buffer */
if (sectoffset + len > bch->sectsize)
{
nbytes = bch->sectsize - sectoffset;
}
else
{
nbytes = len;
}
ret = LOS_CopyFromKernel(buffer, len, &bch->buffer[sectoffset], nbytes);
if (ret != EOK)
{
PRINTK("ERROR: bchlib_read failed: %d\n", ret);
return bytesread;
}
/* Adjust pointers and counts */
++sector;
if (sector >= bch->nsectors)
{
return nbytes;
}
bytesread = nbytes;
buffer += nbytes;
len -= nbytes;
}
/* Then read all of the full sectors following the partial sector directly
* into the user buffer.
*/
if (len >= bch->sectsize)
{
nsectors = len / bch->sectsize;
if (sector + nsectors > bch->nsectors)
{
nsectors = bch->nsectors - sector;
}
ret = los_disk_read(bch->disk->disk_id, (FAR void *)buffer, sector + bch->sectstart, nsectors);
if (ret < 0)
{
PRINTK("ERROR: Read failed: %d\n", ret);
return bytesread;
}
/* Adjust pointers and counts */
sector += nsectors;
nbytes = nsectors * bch->sectsize;
bytesread += nbytes;
if (sector >= bch->nsectors)
{
return bytesread;
}
buffer += nbytes;
len -= nbytes;
}
/* Then read any partial final sector */
if (len > 0)
{
/* Read the sector into the sector buffer */
ret = bchlib_readsector(bch, sector + bch->sectstart);
if (ret < 0)
{
return bytesread;
}
/* Copy the head end of the sector to the user buffer */
ret = LOS_CopyFromKernel(buffer, len, bch->buffer, len);
if (ret != EOK)
{
PRINTK("ERROR: bchlib_read failed: %d\n", ret);
return bytesread;
}
/* Adjust counts */
bytesread += len;
}
return bytesread;
}
+63
View File
@@ -0,0 +1,63 @@
/****************************************************************************
* drivers/bch/bchlib_sem.c
*
* Copyright (C) 2008-2009, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <semaphore.h>
#include "bch.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: bch_semtake
****************************************************************************/
void bchlib_semtake(FAR struct bchlib_s *bch)
{
while (sem_wait(&bch->sem) != 0)
{
/* The only case that an error should occur here is if the wait was
* awakened by a signal.
*/
LOS_ASSERT(get_errno() == EINTR);
}
}
+155
View File
@@ -0,0 +1,155 @@
/****************************************************************************
* drivers/bch/bchlib_setup.c
*
* Copyright (C) 2008-2009, 2011, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/types.h>
#include <sys/mount.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <securec.h>
#include "bch.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: bchlib_setup
*
* Description:
* Setup so that the block driver referenced by 'blkdev' can be accessed
* similar to a character device.
*
****************************************************************************/
int bchlib_setup(const char *blkdev, bool readonly, FAR void **handle)
{
FAR struct bchlib_s *bch;
struct geometry geo;
los_part *part;
int ret;
DEBUGASSERT(blkdev);
/* Allocate the BCH state structure */
bch = (FAR struct bchlib_s *)zalloc(sizeof(struct bchlib_s));
if (!bch)
{
PRINTK("ERROR: Failed to allocate BCH structure\n");
return -ENOMEM;
}
/* Open the block driver */
ret = open_blockdriver(blkdev, readonly ? MS_RDONLY : 0, &bch->inode);
if (ret < 0)
{
PRINTK("ERROR: Failed to open driver %s: %d\n", blkdev, -ret);
goto errout_with_bch;
}
DEBUGASSERT(bch->inode && bch->inode->u.i_bops && bch->inode->u.i_bops->geometry);
ret = bch->inode->u.i_bops->geometry(bch->inode, &geo);
if (ret < 0)
{
PRINTK("ERROR: geometry failed: %d\n", -ret);
goto errout_with_bch;
}
if (!geo.geo_available)
{
PRINTK("ERROR: geometry failed: %d\n", -ret);
ret = -ENODEV;
goto errout_with_bch;
}
if (!readonly && (!bch->inode->u.i_bops->write || !geo.geo_writeenabled))
{
PRINTK("ERROR: write access not supported\n");
ret = -EACCES;
goto errout_with_bch;
}
/* Save the geometry info and complete initialization of the structure */
(void)sem_init(&bch->sem, 0, 1);
bch->nsectors = geo.geo_nsectors;
bch->sectsize = geo.geo_sectorsize;
bch->sector = (size_t)-1;
bch->readonly = readonly;
bch->dirty = false;
bch->unlinked = false;
part = los_part_find(bch->inode);
if (part != NULL)
{
bch->sectstart = part->sector_start;
bch->nsectors = part->sector_count;
bch->disk = get_disk(part->disk_id);
}
else
{
PRINTK("ERROR: los_part_find failed\n");
ret = -ENODEV;
goto errout_with_bch;
}
/* Allocate the sector I/O buffer */
bch->buffer = (FAR uint8_t *)malloc(bch->sectsize);
if (!bch->buffer)
{
PRINTK("ERROR: Failed to allocate sector buffer\n");
ret = -ENOMEM;
goto errout_with_bch;
}
*handle = bch;
return OK;
errout_with_bch:
(void)sem_destroy(&bch->sem);
free(bch);
return ret;
}
+90
View File
@@ -0,0 +1,90 @@
/****************************************************************************
* drivers/bch/bchlib_teardown.c
*
* Copyright (C) 2008-2009, 2011, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include "bch.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: bchlib_teardown
*
* Description:
* Setup so that the block driver referenced by 'blkdev' can be accessed
* similar to a character device.
*
****************************************************************************/
int bchlib_teardown(FAR void *handle)
{
FAR struct bchlib_s *bch = (FAR struct bchlib_s *)handle;
DEBUGASSERT(handle);
/* Check that there are not outstanding reference counts on the object */
if (bch->refs > 0)
{
return -EBUSY;
}
/* Flush any pending data to the block driver */
(void)bchlib_flushsector(bch);
/* Close the block driver */
(void)close_blockdriver(bch->inode);
/* Free the BCH state structure */
if (bch->buffer)
{
free(bch->buffer);
}
(void)sem_destroy(&bch->sem);
free(bch);
return OK;
}
+209
View File
@@ -0,0 +1,209 @@
/****************************************************************************
* drivers/bch/bchlib_write.c
*
* Copyright (C) 2008-2009, 2011, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include "bch.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: bchlib_write
*
* Description:
* Write to the block device set-up by bchlib_setup as if it were a character
* device.
*
****************************************************************************/
ssize_t bchlib_write(FAR void *handle, FAR const char *buffer, loff_t offset, size_t len)
{
FAR struct bchlib_s *bch = (FAR struct bchlib_s *)handle;
size_t nsectors;
unsigned long long sector;
uint16_t sectoffset;
size_t nbytes;
size_t byteswritten;
int ret;
/* Get rid of this special case right away */
if (len < 1)
{
return 0;
}
/* Convert the file position into a sector number and offset. */
sector = offset / bch->sectsize;
sectoffset = offset - sector * bch->sectsize;
if (sector >= bch->nsectors)
{
return 0;
}
/* Write the initial partial sector */
byteswritten = 0;
if (sectoffset > 0)
{
/* Read the full sector into the sector buffer */
ret = bchlib_readsector(bch, sector + bch->sectstart);
if (ret < 0)
{
return byteswritten;
}
/* Copy the tail end of the sector from the user buffer */
if (sectoffset + len > bch->sectsize)
{
nbytes = bch->sectsize - sectoffset;
}
else
{
nbytes = len;
}
ret = LOS_CopyToKernel(&bch->buffer[sectoffset], nbytes, buffer, nbytes);
if (ret != EOK)
{
PRINTK("ERROR: bchlib_write failed: %d\n", ret);
return byteswritten;
}
bch->dirty = true;
/* Adjust pointers and counts */
sector++;
if (sector >= bch->nsectors)
{
return nbytes;
}
byteswritten = nbytes;
buffer += nbytes;
len -= nbytes;
}
/* Then write all of the full sectors following the partial sector
* directly from the user buffer.
*/
if (len >= bch->sectsize)
{
nsectors = len / bch->sectsize;
if (sector + nsectors > bch->nsectors)
{
nsectors = bch->nsectors - sector;
}
/* Write the contiguous sectors */
ret = los_disk_write(bch->disk->disk_id, (FAR const void *)buffer,
sector + bch->sectstart, nsectors);
if (ret < 0)
{
PRINTK("ERROR: Write failed: %d\n", ret);
return byteswritten;
}
/* Adjust pointers and counts */
sector += nsectors;
nbytes = nsectors * bch->sectsize;
byteswritten += nbytes;
if (sector >= bch->nsectors)
{
return byteswritten;
}
buffer += nbytes;
len -= nbytes;
}
/* Then write any partial final sector */
if (len > 0)
{
/* Read the sector into the sector buffer */
ret = bchlib_readsector(bch, sector + bch->sectstart);
if (ret < 0)
{
return byteswritten;
}
/* Copy the head end of the sector from the user buffer */
ret = LOS_CopyToKernel(bch->buffer, len, buffer, len);
if (ret != EOK)
{
PRINTK("ERROR: bchlib_write failed: %d\n", ret);
return byteswritten;
}
bch->dirty = true;
/* Adjust counts */
byteswritten += len;
}
/* Finally, flush any cached writes to the device as well */
ret = bchlib_flushsector(bch);
if (ret < 0)
{
PRINTK("ERROR: Flush failed: %d\n", ret);
return byteswritten;
}
return byteswritten;
}
+41
View File
@@ -0,0 +1,41 @@
# Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
# Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this list of
# conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
# of conditions and the following disclaimer in the documentation and/or other materials
# provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors may be used
# to endorse or promote products derived from this software without specific prior written
# permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
static_library("drivers_pipe") {
sources = [
"fifo.c",
"pipe.c",
"pipe_common.c",
]
include_dirs = [
"./",
]
}
+37
View File
@@ -0,0 +1,37 @@
# Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
# Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this list of
# conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
# of conditions and the following disclaimer in the documentation and/or other materials
# provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors may be used
# to endorse or promote products derived from this software without specific prior written
# permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
include $(LITEOSTOPDIR)/config.mk
MODULE_NAME := $(notdir $(shell pwd))
ifeq ($(LOSCFG_KERNEL_PIPE), y)
LOCAL_SRCS += $(wildcard ./*.c)
endif
include $(MODULE)
+151
View File
@@ -0,0 +1,151 @@
/****************************************************************************
* drivers/pipes/fifo.c
*
* Copyright (C) 2008-2009, 2014-2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h>
#include <errno.h>
#include <fs/fs.h>
#include "pipe_common.h"
#if CONFIG_DEV_FIFO_SIZE > 0
/****************************************************************************
* Private Data
****************************************************************************/
static ssize_t fifo_map(FAR struct file* filep, FAR LosVmMapRegion *region)
{
PRINTK("%s %d, mmap is not support\n", __FUNCTION__, __LINE__);
return 0;
}
static const struct file_operations_vfs fifo_fops =
{
pipecommon_open, /* open */
pipecommon_close, /* close */
pipecommon_read, /* read */
pipecommon_write, /* write */
NULL, /* seek */
NULL, /* ioctl */
fifo_map, /* mmap */
NULL, /* poll */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
pipecommon_unlink, /* unlink */
#endif
};
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: mkfifo2
*
* Description:
* mkfifo() makes a FIFO device driver file with name 'pathname.' Unlike
* Linux, a NuttX FIFO is not a special file type but simply a device
* driver instance. 'mode' specifies the FIFO's permissions.
*
* Once the FIFO has been created by mkfifo(), any thread can open it for
* reading or writing, in the same way as an ordinary file. However, it
* must have been opened from both reading and writing before input or
* output can be performed. This FIFO implementation will block all
* attempts to open a FIFO read-only until at least one thread has opened
* the FIFO for writing.
*
* If all threads that write to the FIFO have closed, subsequent calls to
* read() on the FIFO will return 0 (end-of-file).
*
* NOTE: mkfifo2 is a special, non-standard, NuttX-only interface. Since
* the NuttX FIFOs are based in in-memory, circular buffers, the ability
* to control the size of those buffers is critical for system tuning.
*
* Input Parameters:
* pathname - The full path to the FIFO instance to attach to or to create
* (if not already created).
* mode - Ignored for now
* bufsize - The size of the in-memory, circular buffer in bytes.
*
* Returned Value:
* 0 is returned on success; otherwise, -1 is returned with errno set
* appropriately.
*
****************************************************************************/
int mkfifo(FAR const char *pathname, mode_t mode)
{
FAR struct pipe_dev_s *dev;
int ret;
size_t bufsize = 1024;
if (mode > 0777)
{
return -EINVAL;
}
if (pathname == NULL)
{
return -EINVAL;
}
if (strlen(pathname) > PATH_MAX)
{
return -EINVAL;
}
/* Allocate and initialize a new device structure instance */
dev = pipecommon_allocdev(bufsize, pathname);
if (!dev)
{
return -ENOMEM;
}
ret = register_driver(pathname, &fifo_fops, mode, (FAR void *)dev);
if (ret != 0)
{
pipecommon_freedev(dev);
}
return ret;
}
#endif /* CONFIG_DEV_FIFO_SIZE > 0 */
+343
View File
@@ -0,0 +1,343 @@
/****************************************************************************
* drivers/pipes/pipe.c
*
* Copyright (C) 2008-2009, 2015, 2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <semaphore.h>
#include <fcntl.h>
#include <errno.h>
#include <assert.h>
#include <fs/fs.h>
#include "pipe_common.h"
#include "stdio.h"
#if CONFIG_DEV_PIPE_SIZE > 0
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define MAX_PIPES 32
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static int pipe_close(FAR struct file *filep);
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
static int pipe_unlink(FAR struct inode *priv);
#endif
/****************************************************************************
* Private Data
****************************************************************************/
static ssize_t pipe_map(FAR struct file* filep, FAR LosVmMapRegion *region)
{
PRINTK("%s %d, mmap is not support\n", __FUNCTION__, __LINE__);
return 0;
}
static const struct file_operations_vfs pipe_fops =
{
pipecommon_open, /* open */
pipe_close, /* close */
pipecommon_read, /* read */
pipecommon_write, /* write */
NULL, /* seek */
NULL, /* ioctl */
pipe_map, /* mmap */
pipecommon_poll, /* poll */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
pipe_unlink, /* unlink */
#endif
};
static sem_t g_pipesem = {NULL};
static uint32_t g_pipeset = 0;
static uint32_t g_pipecreated = 0;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: pipe_allocate
****************************************************************************/
static inline int pipe_allocate(void)
{
int pipeno;
int ret = -ENFILE;
for (pipeno = 0; pipeno < MAX_PIPES; pipeno++)
{
if ((g_pipeset & (1 << pipeno)) == 0)
{
g_pipeset |= (1 << pipeno);
ret = pipeno;
break;
}
}
return ret;
}
/****************************************************************************
* Name: pipe_free
****************************************************************************/
static inline void pipe_free(int pipeno)
{
int ret;
ret = sem_wait(&g_pipesem);
if (ret == OK)
{
g_pipeset &= ~(1 << pipeno);
(void)sem_post(&g_pipesem);
}
}
/****************************************************************************
* Name: pipe_close
****************************************************************************/
static int pipe_close(FAR struct file *filep)
{
FAR struct inode *inode = filep->f_inode;
FAR struct pipe_dev_s *dev = inode->i_private;
int ret;
if (dev == NULL)
{
return -EINVAL;
}
/* Perform common close operations */
ret = pipecommon_close(filep);
if (ret == 0 && inode->i_crefs == 1)
{
/* Release the pipe when there are no further open references to it. */
pipe_free(dev->d_pipeno);
}
return ret;
}
/****************************************************************************
* Name: pipe_unlink
****************************************************************************/
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
static int pipe_unlink(FAR struct inode *priv)
{
FAR struct pipe_dev_s *dev = priv->i_private;
uint8_t pipeno = 0;
int ret;
if (dev != NULL)
{
pipeno = dev->d_pipeno;
}
/* Perform common close operations */
ret = pipecommon_unlink(priv);
if (ret == 0 && priv->i_crefs == 1)
{
(void)sem_wait(&g_pipesem);
g_pipecreated &= ~(1 << pipeno);
(void)sem_post(&g_pipesem);
/* Release the pipe when there are no further open references to it. */
pipe_free(pipeno);
}
return ret;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: pipe2
*
* Description:
* pipe() creates a pair of file descriptors, pointing to a pipe inode,
* and places them in the array pointed to by 'fd'. fd[0] is for reading,
* fd[1] is for writing.
*
* NOTE: mkfifo2 is a special, non-standard, NuttX-only interface. Since
* the NuttX FIFOs are based in in-memory, circular buffers, the ability
* to control the size of those buffers is critical for system tuning.
*
* Input Parameters:
* fd[2] - The user provided array in which to catch the pipe file
* descriptors
* bufsize - The size of the in-memory, circular buffer in bytes.
*
* Returned Value:
* 0 is returned on success; otherwise, -1 is returned with errno set
* appropriately.
*
****************************************************************************/
int pipe(int fd[2])
{
FAR struct pipe_dev_s *dev = NULL;
char devname[16];
int pipeno;
int errcode;
int ret;
size_t bufsize = 1024;
/* Get exclusive access to the pipe allocation data */
ret = sem_wait(&g_pipesem);
if (ret < 0)
{
errcode = -ret;
goto errout;
}
/* Allocate a minor number for the pipe device */
pipeno = pipe_allocate();
if (pipeno < 0)
{
(void)sem_post(&g_pipesem);
errcode = -pipeno;
goto errout;
}
/* Create a pathname to the pipe device */
snprintf_s(devname, sizeof(devname), sizeof(devname) - 1, "/dev/pipe%d", pipeno);
/* Check if the pipe device has already been created */
if ((g_pipecreated & (1 << pipeno)) == 0)
{
/* No.. Allocate and initialize a new device structure instance */
dev = pipecommon_allocdev(bufsize, devname);
if (!dev)
{
(void)sem_post(&g_pipesem);
errcode = ENOMEM;
goto errout_with_pipe;
}
dev->d_pipeno = pipeno;
/* Register the pipe device */
ret = register_driver(devname, &pipe_fops, 0660, (FAR void *)dev);
if (ret != 0)
{
(void)sem_post(&g_pipesem);
errcode = -ret;
goto errout_with_dev;
}
/* Remember that we created this device */
g_pipecreated |= (1 << pipeno);
}
(void)sem_post(&g_pipesem);
/* Get a write file descriptor */
fd[1] = open(devname, O_WRONLY);
if (fd[1] < 0)
{
errcode = -fd[1];
goto errout_with_driver;
}
/* Get a read file descriptor */
fd[0] = open(devname, O_RDONLY);
if (fd[0] < 0)
{
errcode = -fd[0];
goto errout_with_wrfd;
}
return OK;
errout_with_wrfd:
close(fd[1]);
errout_with_driver:
unregister_driver(devname);
errout_with_dev:
if (dev)
{
pipecommon_freedev(dev);
}
errout_with_pipe:
pipe_free(pipeno);
errout:
set_errno(errcode);
return VFS_ERROR;
}
int pipe_init()
{
int ret = sem_init(&g_pipesem, 0, 1);
if (ret != 0) {
dprintf(" pipe_init failed!\n");
}
return ret;
}
#endif /* CONFIG_DEV_PIPE_SIZE > 0 */
+816
View File
@@ -0,0 +1,816 @@
/****************************************************************************
* drivers/pipes/pipe_common.c
*
* Copyright (C) 2008-2009, 2011, 2015-2016, 2018 Gregory Nutt. All
* rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <sched.h>
#include <semaphore.h>
#include <fcntl.h>
#include <errno.h>
#include <debug.h>
#include <poll.h>
#include "linux/wait.h"
#include "fs/fs.h"
#include "fs_poll_pri.h"
#include <assert.h>
#ifdef CONFIG_DEBUG_FEATURES
# include <nuttx/arch.h>
#endif
#include <semaphore.h>
#include <fs/fs.h>
#include "pipe_common.h"
#include "los_printf.h"
#include "user_copy.h"
#ifdef LOSCFG_KERNEL_PIPE
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* CONFIG_DEV_PIPEDUMP will dump the contents of each transfer into and out
* of the pipe.
*/
#ifdef CONFIG_DEV_PIPEDUMP
# define pipe_dumpbuffer(m,a,n) lib_dumpbuffer(m,a,n)
#else
# define pipe_dumpbuffer(m,a,n)
#endif
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static void pipecommon_semtake(sem_t *sem);
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: pipecommon_semtake
****************************************************************************/
static void pipecommon_semtake(FAR sem_t *sem)
{
int ret;
do
{
/* Take the semaphore (perhaps waiting) */
ret = sem_wait(sem);
}
while (ret == -EINTR);
}
/****************************************************************************
* Name: pipecommon_pollnotify
****************************************************************************/
static void pipecommon_pollnotify(FAR struct pipe_dev_s *dev,
pollevent_t eventset)
{
if (eventset & POLLERR)
{
eventset &= ~(POLLOUT | POLLIN);
}
notify_poll_with_key(&dev->wq, eventset);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: pipecommon_allocdev
****************************************************************************/
FAR struct pipe_dev_s *pipecommon_allocdev(size_t bufsize, const char *name)
{
FAR struct pipe_dev_s *dev;
int ret;
if (bufsize > CONFIG_DEV_PIPE_MAXSIZE)
{
return NULL;
}
/* Allocate a private structure to manage the pipe */
dev = (FAR struct pipe_dev_s *)malloc(sizeof(struct pipe_dev_s));
if (dev)
{
/* Initialize the private structure */
(void)memset_s(dev, sizeof(struct pipe_dev_s), 0, sizeof(struct pipe_dev_s));
ret = strcpy_s(dev->name, sizeof(dev->name), name);
if (ret < 0)
{
free(dev);
return NULL;
}
sem_init(&dev->d_bfsem, 0, 1);
sem_init(&dev->d_rdsem, 0, 0);
sem_init(&dev->d_wrsem, 0, 0);
LOS_ListInit(&dev->wq.poll_queue);
/* The read/write wait semaphores are used for signaling and, hence,
* should not have priority inheritance enabled.
*/
dev->d_bufsize = bufsize;
}
return dev;
}
/****************************************************************************
* Name: pipecommon_freedev
****************************************************************************/
void pipecommon_freedev(FAR struct pipe_dev_s *dev)
{
sem_destroy(&dev->d_bfsem);
sem_destroy(&dev->d_rdsem);
sem_destroy(&dev->d_wrsem);
free(dev);
}
/****************************************************************************
* Name: pipecommon_open
****************************************************************************/
int pipecommon_open(FAR struct file *filep)
{
FAR struct inode *inode = filep->f_inode;
FAR struct pipe_dev_s *dev = inode->i_private;
int sval;
int ret;
if (dev == NULL)
{
return -EINVAL;
}
/* Make sure that we have exclusive access to the device structure. The
* sem_wait() call should fail only if we are awakened by a signal.
*/
ret = sem_wait(&dev->d_bfsem);
if (ret < 0)
{
PRINT_ERR("ERROR: sem_wait failed: %d\n", ret);
return ret;
}
/* If this the first reference on the device, then allocate the buffer.
* In the case of policy 1, the buffer already be present when the pipe
* is first opened.
*/
if (inode->i_crefs == 1 && dev->d_buffer == NULL)
{
dev->d_buffer = (FAR uint8_t *)malloc(dev->d_bufsize);
if (!dev->d_buffer)
{
(void)sem_post(&dev->d_bfsem);
return -ENOMEM;
}
}
/* If opened for writing, increment the count of writers on the pipe instance */
if ((filep->f_oflags & O_WRONLY) != 0)
{
dev->d_nwriters++;
/* If this this is the first writer, then the read semaphore indicates the
* number of readers waiting for the first writer. Wake them all up.
*/
if (dev->d_nwriters == 1)
{
while (sem_getvalue(&dev->d_rdsem, &sval) == 0 && sval == 0)
{
sem_post(&dev->d_rdsem);
}
}
}
/* If opened for reading, increment the count of reader on on the pipe instance */
if ((filep->f_oflags & O_WRONLY) == 0)
{
dev->d_nreaders++;
}
/* If opened for read-only, then wait for either (1) at least one writer
* on the pipe (policy == 0), or (2) until there is buffered data to be
* read (policy == 1).
*/
(void)sem_post(&dev->d_bfsem);
if ((filep->f_oflags & O_WRONLY) == 0 && /* Read-only */
dev->d_nwriters < 1 && /* No writers on the pipe */
dev->d_wrndx == dev->d_rdndx) /* Buffer is empty */
{
/* NOTE: d_rdsem is normally used when the read logic waits for more
* data to be written. But until the first writer has opened the
* pipe, the meaning is different: it is used prevent O_RDONLY open
* calls from returning until there is at least one writer on the pipe.
* This is required both by spec and also because it prevents
* subsequent read() calls from returning end-of-file because there is
* no writer on the pipe.
*/
ret = sem_wait(&dev->d_rdsem);
if (ret < 0)
{
/* The sem_wait() call should fail only if we are awakened by
* a signal.
*/
PRINT_ERR("ERROR: sem_wait failed: %d\n", ret);
/* Immediately close the pipe that we just opened */
(void)pipecommon_close(filep);
}
}
return ret;
}
/****************************************************************************
* Name: pipecommon_close
****************************************************************************/
int pipecommon_close(FAR struct file *filep)
{
FAR struct inode *inode = filep->f_inode;
FAR struct pipe_dev_s *dev = inode->i_private;
int sval;
if (dev == NULL || filep->f_inode->i_crefs <= 0)
{
return -EINVAL;
}
/* Make sure that we have exclusive access to the device structure.
* NOTE: close() is supposed to return EINTR if interrupted, however
* I've never seen anyone check that.
*/
pipecommon_semtake(&dev->d_bfsem);
/* Decrement the number of references on the pipe. Check if there are
* still outstanding references to the pipe.
*/
/* Check if the decremented inode reference count would go to zero */
if (inode->i_crefs > 1)
{
/* More references.. If opened for writing, decrement the count of
* writers on the pipe instance.
*/
if ((filep->f_oflags & O_WRONLY) != 0)
{
/* If there are no longer any writers on the pipe, then notify all of the
* waiting readers that they must return end-of-file.
*/
if (--dev->d_nwriters <= 0)
{
while (sem_getvalue(&dev->d_rdsem, &sval) == 0 && sval == 0)
{
sem_post(&dev->d_rdsem);
}
/* Inform poll readers that other end closed. */
pipecommon_pollnotify(dev, POLLHUP);
}
}
/* If opened for reading, decrement the count of readers on the pipe
* instance.
*/
if ((filep->f_oflags & O_WRONLY) == 0)
{
if (--dev->d_nreaders <= 0)
{
if (PIPE_IS_POLICY_0(dev->d_flags))
{
/* Inform poll writers that other end closed. */
pipecommon_pollnotify(dev, POLLERR);
}
}
}
}
/* What is the buffer management policy? Do we free the buffer when the
* last client closes the pipe policy 0, or when the buffer becomes empty.
* In the latter case, the buffer data will remain valid and can be
* obtained when the pipe is re-opened.
*/
else if (PIPE_IS_POLICY_0(dev->d_flags) || dev->d_wrndx == dev->d_rdndx)
{
/* Policy 0 or the buffer is empty ... deallocate the buffer now. */
free(dev->d_buffer);
dev->d_buffer = NULL;
/* And reset all counts and indices */
dev->d_wrndx = 0;
dev->d_rdndx = 0;
dev->d_nwriters = 0;
dev->d_nreaders = 0;
}
sem_post(&dev->d_bfsem);
return OK;
}
/****************************************************************************
* Name: pipecommon_read
****************************************************************************/
ssize_t pipecommon_read(FAR struct file *filep, FAR char *buffer, size_t len)
{
FAR struct inode *inode = filep->f_inode;
FAR struct pipe_dev_s *dev = inode->i_private;
ssize_t nread = 0;
int sval;
int ret;
if (dev == NULL)
{
return -EINVAL;
}
if (len == 0)
{
return 0;
}
if (len > MAX_READ_WRITE_LEN)
{
return -EINVAL;
}
/* Make sure that we have exclusive access to the device structure */
ret = sem_wait(&dev->d_bfsem);
if (ret < 0)
{
return ret;
}
/* If the pipe is empty, then wait for something to be written to it */
while (dev->d_wrndx == dev->d_rdndx)
{
/* If O_NONBLOCK was set, then return EGAIN */
if (filep->f_oflags & O_NONBLOCK)
{
sem_post(&dev->d_bfsem);
return -EAGAIN;
}
/* If there are no writers on the pipe, then return end of file */
if (dev->d_nwriters <= 0)
{
sem_post(&dev->d_bfsem);
return 0;
}
/* Otherwise, wait for something to be written to the pipe */
sem_post(&dev->d_bfsem);
ret = sem_wait(&dev->d_rdsem);
if (ret < 0 || (ret = sem_wait(&dev->d_bfsem)) < 0)
{
return ret;
}
}
/* Then return whatever is available in the pipe (which is at least one byte) */
nread = 0;
for (; ; )
{
while ((size_t)nread < len && dev->d_wrndx != dev->d_rdndx)
{
ret = LOS_ArchCopyToUser(buffer, dev->d_buffer + dev->d_rdndx, sizeof(char));
if (ret != 0)
{
sem_post(&dev->d_bfsem);
return -EFAULT;
}
buffer++;
if (++dev->d_rdndx >= dev->d_bufsize)
{
dev->d_rdndx = 0;
}
nread++;
}
/* If O_NONBLOCK was set, then break */
if (filep->f_oflags & O_NONBLOCK)
{
break;
}
/* Is the read complete? */
if ((size_t)nread >= len)
{
break;
}
/* wait for something to be written to the pipe */
sem_post(&dev->d_wrsem);
pipecommon_pollnotify(dev, POLLOUT);
sem_post(&dev->d_bfsem);
ret = sem_wait(&dev->d_rdsem);
if (ret < 0)
{
return ret;
}
ret = sem_wait(&dev->d_bfsem);
if (ret < 0)
{
return ret;
}
/* If there are no writers on the pipe, then return end of file */
if (dev->d_nwriters <= 0)
{
sem_post(&dev->d_wrsem);
pipecommon_pollnotify(dev, POLLOUT);
sem_post(&dev->d_bfsem);
return nread;
}
}
/* Notify all waiting writers that bytes have been removed from the buffer */
while (sem_getvalue(&dev->d_wrsem, &sval) == 0 && sval == 0)
{
sem_post(&dev->d_wrsem);
}
/* Notify all poll/select waiters that they can write to the FIFO */
pipecommon_pollnotify(dev, POLLOUT);
sem_post(&dev->d_bfsem);
return nread;
}
/****************************************************************************
* Name: pipecommon_write
****************************************************************************/
ssize_t pipecommon_write(FAR struct file *filep, FAR const char *buffer,
size_t len)
{
FAR struct inode *inode = filep->f_inode;
FAR struct pipe_dev_s *dev = inode->i_private;
ssize_t nwritten = 0;
ssize_t last;
int nxtwrndx;
int sval;
int ret;
if (dev == NULL)
{
return -EINVAL;
}
/* Handle zero-length writes */
if (len == 0)
{
return 0;
}
if (len > MAX_READ_WRITE_LEN)
{
return -EINVAL;
}
/* REVISIT: "If all file descriptors referring to the read end of a pipe
* have been closed, then a write will cause a SIGPIPE signal to be
* generated for the calling process. If the calling process is ignoring
* this signal, then write(2) fails with the error EPIPE."
*/
if (dev->d_nreaders <= 0)
{
return -EPIPE;
}
/* At present, this method cannot be called from interrupt handlers. That
* is because it calls sem_wait (via pipecommon_semtake below) and
* sem_wait cannot be called from interrupt level. This actually
* happens fairly commonly IF [a-z]err() is called from interrupt handlers
* and stdout is being redirected via a pipe. In that case, the debug
* output will try to go out the pipe (interrupt handlers should use the
* _err() APIs).
*
* On the other hand, it would be very valuable to be able to feed the pipe
* from an interrupt handler! TODO: Consider disabling interrupts instead
* of taking semaphores so that pipes can be written from interrupt handlers
*/
/* Make sure that we have exclusive access to the device structure */
ret = sem_wait(&dev->d_bfsem);
if (ret < 0)
{
return ret;
}
/* Loop until all of the bytes have been written */
last = 0;
for (; ; )
{
/* Calculate the write index AFTER the next byte is written */
nxtwrndx = dev->d_wrndx + 1;
if (nxtwrndx >= dev->d_bufsize)
{
nxtwrndx = 0;
}
/* Would the next write overflow the circular buffer? */
if (nxtwrndx != dev->d_rdndx)
{
/* No... copy the byte */
ret = LOS_ArchCopyFromUser(dev->d_buffer + dev->d_wrndx, buffer, sizeof(char));
if (ret != 0)
{
sem_post(&dev->d_bfsem);
return -EFAULT;
}
buffer++;
dev->d_wrndx = nxtwrndx;
/* Is the write complete? */
nwritten++;
if ((size_t)nwritten >= len)
{
/* Yes.. Notify all of the waiting readers that more data is available */
while (sem_getvalue(&dev->d_rdsem, &sval) == 0 && sval == 0)
{
sem_post(&dev->d_rdsem);
}
/* Notify all poll/select waiters that they can read from the FIFO */
pipecommon_pollnotify(dev, POLLIN);
/* Return the number of bytes written */
sem_post(&dev->d_bfsem);
return len;
}
}
else
{
/* There is not enough room for the next byte. Was anything written in this pass? */
if (last < nwritten)
{
/* Yes.. Notify all of the waiting readers that more data is available */
while (sem_getvalue(&dev->d_rdsem, &sval) == 0 && sval == 0)
{
sem_post(&dev->d_rdsem);
}
/* Notify all poll/select waiters that they can read from the FIFO */
pipecommon_pollnotify(dev, POLLIN);
}
last = nwritten;
/* If O_NONBLOCK was set, then return partial bytes written or EGAIN */
if (filep->f_oflags & O_NONBLOCK)
{
if (nwritten == 0)
{
nwritten = -EAGAIN;
}
sem_post(&dev->d_bfsem);
return nwritten;
}
/* There is more to be written.. wait for data to be removed from the pipe */
sem_post(&dev->d_bfsem);
pipecommon_semtake(&dev->d_wrsem);
pipecommon_semtake(&dev->d_bfsem);
}
}
}
/****************************************************************************
* Name: pipecommon_poll
****************************************************************************/
int pipecommon_poll(FAR struct file *filep, poll_table *table)
{
FAR struct inode *inode = filep->f_inode;
FAR struct pipe_dev_s *dev = inode->i_private;
pollevent_t eventset;
pipe_ndx_t nbytes;
int ret = OK;
if (dev == NULL || table == NULL)
{
return -EINVAL;
}
/* Are we setting up the poll? Or tearing it down? */
pipecommon_semtake(&dev->d_bfsem);
/* Should immediately notify on any of the requested events?
* First, determine how many bytes are in the buffer
*/
if (dev->d_wrndx >= dev->d_rdndx)
{
nbytes = dev->d_wrndx - dev->d_rdndx;
}
else
{
nbytes = dev->d_bufsize + dev->d_wrndx - dev->d_rdndx;
}
/* Notify the POLLOUT event if the pipe is not full, but only if
* there is readers.
*/
eventset = 0;
if (((filep->f_oflags & O_WRONLY) != 0) && (nbytes < (dev->d_bufsize - 1)))
{
eventset |= POLLOUT;
}
/* Notify the POLLIN event if the pipe is not empty */
if (((filep->f_oflags & O_WRONLY) == 0) && (nbytes > 0))
{
eventset |= POLLIN;
}
/* Notify the POLLHUP event if the pipe is empty and no writers */
if (nbytes == 0 && dev->d_nwriters <= 0)
{
eventset |= POLLHUP;
}
/* Change POLLOUT to POLLERR, if no readers and policy 0. */
if ((eventset | POLLOUT) &&
PIPE_IS_POLICY_0(dev->d_flags) &&
dev->d_nreaders <= 0)
{
eventset |= POLLERR;
}
ret = eventset & table->key;
if (ret == 0)
{
poll_wait(NULL, &dev->wq, table);
}
sem_post(&dev->d_bfsem);
return ret;
}
/****************************************************************************
* Name: pipecommon_ioctl
****************************************************************************/
int pipecommon_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
return -ENOSYS;
}
/****************************************************************************
* Name: pipecommon_unlink
****************************************************************************/
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
int pipecommon_unlink(FAR struct inode *inode)
{
FAR struct pipe_dev_s *dev;
if (inode == NULL || inode->i_private == NULL)
{
return -EINVAL;
}
dev = (FAR struct pipe_dev_s *)inode->i_private;
/* Are the any open references to the driver? */
if (inode->i_crefs == 1)
{
/* No.. free the buffer (if there is one) */
if (dev->d_buffer)
{
free(dev->d_buffer);
}
/* And free the device structure. */
unregister_driver(dev->name);
pipecommon_freedev(dev);
}
else
{
PRINTK("Device busy!\n");
return -EBUSY;
}
return OK;
}
#endif
#endif /* LOSCFG_KERNEL_PIPE */
+173
View File
@@ -0,0 +1,173 @@
/****************************************************************************
* drivers/pipe/pipe_common.h
*
* Copyright (C) 2008-2009, 2015-2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __DRIVERS_PIPES_PIPE_COMMON_H
#define __DRIVERS_PIPES_PIPE_COMMON_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/types.h>
#include <limits.h>
#include <stdint.h>
#include <stdbool.h>
#include <poll.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Pipe/FIFO support */
/* Pipe/FIFO size */
#ifndef MAX_READ_WRITE_LEN
# define MAX_READ_WRITE_LEN 0x1000000
#endif
#ifndef CONFIG_DEV_PIPE_MAXSIZE
# define CONFIG_DEV_PIPE_MAXSIZE 1024
#endif
#if CONFIG_DEV_PIPE_MAXSIZE <= 0
# undef CONFIG_PIPES
# undef CONFIG_DEV_PIPE_SIZE
# undef CONFIG_DEV_FIFO_SIZE
# define CONFIG_DEV_PIPE_SIZE 0
# define CONFIG_DEV_FIFO_SIZE 0
#endif
#ifndef CONFIG_DEV_PIPE_SIZE
# define CONFIG_DEV_PIPE_SIZE 1024
#endif
#ifndef CONFIG_DEV_FIFO_SIZE
# define CONFIG_DEV_FIFO_SIZE 1024
#endif
/* Maximum number of threads than can be waiting for POLL events */
#ifndef CONFIG_DEV_PIPE_NPOLLWAITERS
# define CONFIG_DEV_PIPE_NPOLLWAITERS 2
#endif
/* Maximum number of open's supported on pipe */
#define CONFIG_DEV_PIPE_MAXUSER 255
/* d_flags values */
#define PIPE_FLAG_POLICY (1 << 0) /* Bit 0: Policy=Free buffer when empty */
#define PIPE_FLAG_UNLINKED (1 << 1) /* Bit 1: The driver has been unlinked */
#define PIPE_POLICY_0(f) do { (f) &= ~PIPE_FLAG_POLICY; } while (0)
#define PIPE_POLICY_1(f) do { (f) |= PIPE_FLAG_POLICY; } while (0)
#define PIPE_IS_POLICY_0(f) (((f) & PIPE_FLAG_POLICY) == 0)
#define PIPE_IS_POLICY_1(f) (((f) & PIPE_FLAG_POLICY) != 0)
#define PIPE_UNLINK(f) do { (f) |= PIPE_FLAG_UNLINKED; } while (0)
#define PIPE_IS_UNLINKED(f) (((f) & PIPE_FLAG_UNLINKED) != 0)
/****************************************************************************
* Public Types
****************************************************************************/
/* Make the buffer index as small as possible for the configured pipe size */
#if CONFIG_DEV_PIPE_MAXSIZE > 65535
typedef uint32_t pipe_ndx_t; /* 32-bit index */
#elif CONFIG_DEV_PIPE_MAXSIZE > 255
typedef uint16_t pipe_ndx_t; /* 16-bit index */
#else
typedef uint8_t pipe_ndx_t; /* 8-bit index */
#endif
/* This structure represents the state of one pipe. A reference to this
* structure is retained in the i_private field of the inode whenthe pipe/fifo
* device is registered.
*/
struct pipe_dev_s
{
char name[PATH_MAX + 1];
sem_t d_bfsem; /* Used to serialize access to d_buffer and indices */
sem_t d_rdsem; /* Empty buffer - Reader waits for data write */
sem_t d_wrsem; /* Full buffer - Writer waits for data read */
pipe_ndx_t d_wrndx; /* Index in d_buffer to save next byte written */
pipe_ndx_t d_rdndx; /* Index in d_buffer to return the next byte read */
pipe_ndx_t d_bufsize; /* allocated size of d_buffer in bytes */
uint8_t d_nwriters; /* Number of reference counts for write access */
uint8_t d_nreaders; /* Number of reference counts for read access */
uint8_t d_pipeno; /* Pipe minor number */
uint8_t d_flags; /* See PIPE_FLAG_* definitions */
uint8_t *d_buffer; /* Buffer allocated when device opened */
wait_queue_head_t wq; /* It is a list if poll structures of threads waiting for driver events */
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#ifdef __cplusplus
# define EXTERN extern "C"
extern "C"
{
#else
# define EXTERN extern
#endif
struct file; /* Forward reference */
struct inode; /* Forward reference */
FAR struct pipe_dev_s *pipecommon_allocdev(size_t bufsize, const char *name);
void pipecommon_freedev(FAR struct pipe_dev_s *dev);
int pipecommon_open(FAR struct file *filep);
int pipecommon_close(FAR struct file *filep);
ssize_t pipecommon_read(FAR struct file *, FAR char *, size_t);
ssize_t pipecommon_write(FAR struct file *, FAR const char *, size_t);
int pipecommon_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
int pipecommon_poll(FAR struct file *filep, poll_table *fds);
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
int pipecommon_unlink(FAR struct inode *priv);
#endif
int pipe_init(void);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __DRIVERS_PIPES_PIPE_COMMON_H */
+871
View File
@@ -0,0 +1,871 @@
/****************************************************************************
* graphics/fb/fb.c
* Framebuffer character driver
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "fb.h"
#include "fs/fs.h"
#include "assert.h"
#include "errno.h"
#include "user_copy.h"
#define gerr PRINT_ERR
/****************************************************************************
* Private Types
****************************************************************************/
/* This structure defines one framebuffer device. Note that which is
* everything in this structure is constant data set up and initialization
* time. Therefore, no there is requirement for serialized access to this
* structure.
*/
struct fb_chardev_s
{
FAR struct fb_vtable_s *vtable; /* Framebuffer interface */
FAR void *fbmem; /* Start of frame buffer memory */
size_t fblen; /* Size of the framebuffer */
uint8_t plane; /* Video plan number */
uint8_t bpp; /* Bits per pixel */
};
#define FB_DEV_MAXNUM 32
static struct fb_chardev_s *g_fb_dev[FB_DEV_MAXNUM] = {NULL};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static int fb_open(FAR struct file *filep);
static int fb_close(FAR struct file *filep);
static ssize_t fb_read(FAR struct file *filep, FAR char *buffer,
size_t buflen);
static ssize_t fb_write(FAR struct file *filep, FAR const char *buffer,
size_t buflen);
static off_t fb_seek(FAR struct file *filep, off_t offset, int whence);
static int fb_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
static ssize_t fb_mmap(FAR struct file* filep, FAR LosVmMapRegion *region);
/****************************************************************************
* Private Data
****************************************************************************/
static const struct file_operations_vfs fb_fops =
{
fb_open, /* open */
fb_close, /* close */
fb_read, /* read */
fb_write, /* write */
fb_seek, /* seek */
fb_ioctl, /* ioctl */
fb_mmap, /* mmap */
#ifndef CONFIG_DISABLE_POLL
NULL, /* poll */
#endif
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
NULL, /* unlink */
#endif
};
/****************************************************************************
* Private Functions
****************************************************************************/
static ssize_t fb_mmap(FAR struct file *filep, FAR LosVmMapRegion *region)
{
int ret = -EINVAL;
struct fb_chardev_s *fb;
struct fb_vtable_s *vtable;
fb = (struct fb_chardev_s *)filep->f_inode->i_private;
if (fb == NULL)
{
return -ENODEV;
}
vtable = fb->vtable;
if (vtable == NULL)
{
return -EINVAL;
}
if (vtable->fb_mmap != NULL)
{
ret = vtable->fb_mmap(vtable, region);
}
return ret;
}
/****************************************************************************
* Name: fb_open
*
* Description:
* This function is called whenever the framebuffer device is opened.
*
****************************************************************************/
static int fb_open(FAR struct file *filep)
{
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
struct fb_chardev_s *fb;
struct fb_vtable_s *vtable;
int ret = -EINVAL;
fb = (struct fb_chardev_s *)filep->f_inode->i_private;
if (fb == NULL)
{
return -ENODEV;
}
vtable = fb->vtable;
if (vtable == NULL)
{
return -EINVAL;
}
if (vtable->fb_open)
{
ret = vtable->fb_open(vtable);
}
return ret;
}
/****************************************************************************
* Name: fb_close
*
* Description:
* This function is called when the framebuffer device is closed.
*
****************************************************************************/
static int fb_close(FAR struct file *filep)
{
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
struct fb_chardev_s *fb;
struct fb_vtable_s *vtable;
int ret = -EINVAL;
fb = (struct fb_chardev_s *)filep->f_inode->i_private;
if (fb == NULL)
{
return -ENODEV;
}
vtable = fb->vtable;
if (vtable == NULL)
{
return -EINVAL;
}
if (vtable->fb_release)
{
ret = vtable->fb_release(vtable);
}
return ret;
}
/****************************************************************************
* Name: fb_read
****************************************************************************/
static ssize_t fb_read(FAR struct file *filep, FAR char *buffer, size_t len)
{
FAR struct inode *inode;
FAR struct fb_chardev_s *fb;
size_t start;
size_t end;
size_t size;
int ret;
/* Get the framebuffer instance */
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
inode = filep->f_inode;
fb = (FAR struct fb_chardev_s *)inode->i_private;
/* Get the start and size of the transfer */
start = filep->f_pos;
if (start >= fb->fblen)
{
return 0; /* Return end-of-file */
}
end = start + len;
if (end >= fb->fblen)
{
end = fb->fblen;
}
size = end - start;
/* And transfer the data from the frame buffer */
ret = LOS_ArchCopyToUser(buffer, fb->fbmem, size);
if (ret)
{
return -EFAULT;
}
filep->f_pos += size;
return size;
}
/****************************************************************************
* Name: fb_write
****************************************************************************/
static ssize_t fb_write(FAR struct file *filep, FAR const char *buffer,
size_t len)
{
FAR struct inode *inode;
FAR struct fb_chardev_s *fb;
size_t start;
size_t end;
size_t size;
int ret;
/* Get the framebuffer instance */
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
inode = filep->f_inode;
fb = (FAR struct fb_chardev_s *)inode->i_private;
/* Get the start and size of the transfer */
start = filep->f_pos;
if (start >= fb->fblen)
{
return -EFBIG; /* Cannot extend the framebuffer */
}
end = start + len;
if (end >= fb->fblen)
{
end = fb->fblen;
}
size = end - start;
/* And transfer the data into the frame buffer */
ret = LOS_ArchCopyFromUser(fb->fbmem, buffer, size);
if (ret)
{
return -EFAULT;
}
filep->f_pos += size;
return size;
}
/****************************************************************************
* Name: fb_seek
*
* Description:
* Seek the logical file pointer to the specified position. The offset
* is in units of pixels, with offset zero being the beginning of the
* framebuffer.
*
****************************************************************************/
static off_t fb_seek(FAR struct file *filep, off_t offset, int whence)
{
FAR struct inode *inode;
FAR struct fb_chardev_s *fb;
off_t newpos;
int ret;
/* Get the framebuffer instance */
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
inode = filep->f_inode;
fb = (FAR struct fb_chardev_s *)inode->i_private;
/* Determine the new, requested file position */
switch (whence)
{
case SEEK_CUR:
newpos = filep->f_pos + offset;
break;
case SEEK_SET:
newpos = offset;
break;
case SEEK_END:
newpos = fb->fblen + offset;
break;
default:
/* Return EINVAL if the whence argument is invalid */
return -EINVAL;
}
/* Opengroup.org:
*
* "The lseek() function shall allow the file offset to be set beyond the end
* of the existing data in the file. If data is later written at this point,
* subsequent reads of data in the gap shall return bytes with the value 0
* until data is actually written into the gap."
*
* We can conform to the first part, but not the second. But return EINVAL if
*
* "...the resulting file offset would be negative for a regular file, block
* special file, or directory."
*/
if (newpos >= 0)
{
filep->f_pos = newpos;
ret = newpos;
}
else
{
ret = -EINVAL;
}
return ret;
}
/****************************************************************************
* Name: fb_ioctl
*
* Description:
* The standard ioctl method.
*
****************************************************************************/
static int fb_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
FAR struct inode *inode;
FAR struct fb_chardev_s *fb;
int ret;
/* Get the framebuffer instance */
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
inode = filep->f_inode;
fb = (FAR struct fb_chardev_s *)inode->i_private;
/* Process the IOCTL command */
switch (cmd)
{
case FIOC_MMAP: /* Get color plane info */
{
FAR void **ppv = (FAR void **)((uintptr_t)arg);
uintptr_t fbmem = (uintptr_t)fb->fbmem;
/* Return the address corresponding to the start of frame buffer. */
ret = LOS_ArchCopyToUser(ppv, &fbmem, sizeof(uintptr_t));
if (ret)
{
ret = -EFAULT;
}
}
break;
case FBIOGET_VIDEOINFO: /* Get color plane info */
{
struct fb_videoinfo_s vinfo;
DEBUGASSERT(fb->vtable != NULL &&
fb->vtable->getvideoinfo != NULL);
ret = fb->vtable->getvideoinfo(fb->vtable, &vinfo);
if (ret == ENOERR)
{
ret = LOS_ArchCopyToUser((void *)arg, &vinfo, sizeof(struct fb_videoinfo_s));
if (ret)
{
ret = -EFAULT;
}
}
}
break;
case FBIOGET_PLANEINFO: /* Get video plane info */
{
struct fb_planeinfo_s pinfo;
DEBUGASSERT(fb->vtable != NULL &&
fb->vtable->getplaneinfo != NULL);
ret = fb->vtable->getplaneinfo(fb->vtable, fb->plane, &pinfo);
if (ret == ENOERR)
{
ret = LOS_ArchCopyToUser((void *)arg, &pinfo, sizeof(struct fb_planeinfo_s));
if (ret)
{
ret = -EFAULT;
}
}
}
break;
#ifdef CONFIG_FB_CMAP
case FBIOGET_CMAP: /* Get RGB color mapping */
{
struct fb_cmap_s cmap;
DEBUGASSERT(fb->vtable != NULL &&
fb->vtable->getcmap != NULL);
ret = fb->vtable->getcmap(fb->vtable, &cmap);
if (ret == ENOERR)
{
ret = LOS_ArchCopyToUser((void *)arg, &cmap, sizeof(struct fb_cmap_s));
if (ret)
{
ret = -EFAULT;
}
}
}
break;
case FBIOPUT_CMAP: /* Put RGB color mapping */
{
struct fb_cmap_s cmap;
DEBUGASSERT(fb->vtable != NULL &&
fb->vtable->putcmap != NULL);
ret = LOS_ArchCopyFromUser(&cmap, (const void *)arg, sizeof(struct fb_cmap_s));
if (ret)
{
ret = -EFAULT;
break;
}
ret = fb->vtable->putcmap(fb->vtable, &cmap);
}
break;
#endif
#ifdef CONFIG_FB_HWCURSOR
case FBIOGET_CURSOR: /* Get cursor attributes */
{
struct fb_cursorattrib_s attrib;
DEBUGASSERT(fb->vtable != NULL &&
fb->vtable->getcursor != NULL);
ret = fb->vtable->getcursor(fb->vtable, &attrib);
if (ret == ENOERR)
{
ret = LOS_ArchCopyToUser((void *)arg, &attrib, sizeof(struct fb_cursorattrib_s));
if (ret)
{
ret = -EFAULT;
}
}
}
break;
case FBIOPUT_CURSOR: /* Set cursor attibutes */
{
struct fb_setcursor_s cursor;
DEBUGASSERT(fb->vtable != NULL &&
fb->vtable->setcursor != NULL);
ret = LOS_ArchCopyFromUser(&cursor, (const void *)arg, sizeof(struct fb_setcursor_s));
if (ret)
{
ret = -EFAULT;
break;
}
ret = fb->vtable->setcursor(fb->vtable, &cursor);
}
break;
#endif
#ifdef CONFIG_LCD_UPDATE
case FBIO_UPDATE: /* Update the LCD with the modified framebuffer data */
{
struct nxgl_rect_s rect;
struct fb_planeinfo_s pinfo;
DEBUGASSERT(fb->vtable != NULL && fb->vtable->getplaneinfo != NULL);
ret = LOS_ArchCopyFromUser(&rect, (const void *)arg, sizeof(struct nxgl_rect_s));
if (ret)
{
ret = -EFAULT;
break;
}
ret = fb->vtable->getplaneinfo(fb->vtable, fb->plane, &pinfo);
if (ret >= 0)
{
nx_notify_rectangle((FAR NX_PLANEINFOTYPE *)&pinfo, &rect);
}
}
break;
#endif
#ifdef CONFIG_FB_SYNC
case FBIO_WAITFORVSYNC: /* Wait upon vertical sync */
{
ret = fb->vtable->waitforvsync(fb->vtable);
}
break;
#endif
#ifdef CONFIG_FB_OVERLAY
case FBIO_SELECT_OVERLAY: /* Select video overlay */
{
struct fb_overlayinfo_s oinfo;
DEBUGASSERT(fb->vtable != NULL && fb->vtable->getoverlayinfo != NULL);
ret = fb->vtable->getoverlayinfo(fb->vtable, arg, &oinfo);
if (ret == OK)
{
fb->fbmem = oinfo.fbmem;
fb->fblen = oinfo.fblen;
fb->bpp = oinfo.bpp;
}
}
break;
case FBIOGET_OVERLAYINFO: /* Get video overlay info */
{
struct fb_overlayinfo_s oinfo;
DEBUGASSERT(fb->vtable != NULL &&
fb->vtable->getoverlayinfo != NULL);
ret = LOS_ArchCopyFromUser(&oinfo, (const void *)arg, sizeof(struct fb_overlayinfo_s));
if (ret)
{
ret = -EFAULT;
break;
}
ret = fb->vtable->getoverlayinfo(fb->vtable, oinfo.overlay, &oinfo);
if (ret == ENOERR)
{
ret = LOS_ArchCopyToUser((void *)arg, &oinfo, sizeof(struct fb_overlayinfo_s));
if (ret)
{
ret = -EFAULT;
}
}
}
break;
case FBIOSET_TRANSP: /* Set video overlay transparency */
{
struct fb_overlayinfo_s oinfo;
DEBUGASSERT(fb->vtable != NULL &&
fb->vtable->settransp != NULL);
ret = LOS_ArchCopyFromUser(&oinfo, (const void *)arg, sizeof(struct fb_overlayinfo_s));
if (ret)
{
ret = -EFAULT;
break;
}
ret = fb->vtable->settransp(fb->vtable, &oinfo);
}
break;
case FBIOSET_CHROMAKEY: /* Set video overlay chroma key */
{
struct fb_overlayinfo_s oinfo;
DEBUGASSERT(fb->vtable != NULL &&
fb->vtable->setchromakey != NULL);
ret = LOS_ArchCopyFromUser(&oinfo, (const void *)arg, sizeof(struct fb_overlayinfo_s));
if (ret)
{
ret = -EFAULT;
break;
}
ret = fb->vtable->setchromakey(fb->vtable, &oinfo);
}
break;
case FBIOSET_COLOR: /* Set video overlay color */
{
struct fb_overlayinfo_s oinfo;
DEBUGASSERT(fb->vtable != NULL &&
fb->vtable->setcolor != NULL);
ret = LOS_ArchCopyFromUser(&oinfo, (const void *)arg, sizeof(struct fb_overlayinfo_s));
if (ret)
{
ret = -EFAULT;
break;
}
ret = fb->vtable->setcolor(fb->vtable, &oinfo);
}
break;
case FBIOSET_BLANK: /* Blank or unblank video overlay */
{
struct fb_overlayinfo_s oinfo;
DEBUGASSERT(fb->vtable != NULL &&
fb->vtable->setblank != NULL);
ret = LOS_ArchCopyFromUser(&oinfo, (const void *)arg, sizeof(struct fb_overlayinfo_s));
if (ret)
{
ret = -EFAULT;
break;
}
ret = fb->vtable->setblank(fb->vtable, &oinfo);
}
break;
case FBIOSET_AREA: /* Set active video overlay area */
{
struct fb_overlayinfo_s oinfo;
DEBUGASSERT(fb->vtable != NULL &&
fb->vtable->setarea != NULL);
ret = LOS_ArchCopyFromUser(&oinfo, (const void *)arg, sizeof(struct fb_overlayinfo_s));
if (ret)
{
ret = -EFAULT;
break;
}
ret = fb->vtable->setarea(fb->vtable, &oinfo);
}
break;
#ifdef CONFIG_FB_OVERLAY_BLIT
case FBIOSET_BLIT: /* Blit operation between video overlays */
{
struct fb_overlayblit_s blit;
DEBUGASSERT(fb->vtable != NULL &&
fb->vtable->blit != NULL);
ret = LOS_ArchCopyFromUser(&blit, (const void *)arg, sizeof(struct fb_overlayblit_s));
if (ret)
{
ret = -EFAULT;
break;
}
ret = fb->vtable->blit(fb->vtable, &blit);
}
break;
case FBIOSET_BLEND: /* Blend operation between video overlays */
{
struct fb_overlayblend_s blend;
DEBUGASSERT(fb->vtable != NULL &&
fb->vtable->blend != NULL);
ret = LOS_ArchCopyFromUser(&blend, (const void *)arg, sizeof(struct fb_overlayblend_s));
if (ret)
{
ret = -EFAULT;
break;
}
ret = fb->vtable->blend(fb->vtable, &blend);
}
break;
#endif
#endif /* CONFIG_FB_OVERLAY */
default:
DEBUGASSERT(fb->vtable != NULL && fb->vtable->fb_ioctl != NULL);
ret = fb->vtable->fb_ioctl(fb->vtable, cmd, arg);
break;
}
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: fb_register
*
* Description:
* Register the framebuffer character device at /dev/fbN where N is the
* display number if the devices supports only a single plane. If the
* hardware supports multiple color planes, then the device will be
* registered at /dev/fbN.M where N is the again display number but M
* is the display plane.
*
* Input Parameters:
* display - The display number for the case of boards supporting multiple
* displays or for hardware that supports multiple
* layers (each layer is consider a display). Typically zero.
* plane - Identifies the color plane on hardware that supports separate
* framebuffer "planes" for each color component.
*
* Returned Value:
* Zero (OK) is returned success; a negated errno value is returned on any
* failure.
*
****************************************************************************/
int fb_register(int display, int plane)
{
FAR struct fb_chardev_s *fb;
struct fb_videoinfo_s vinfo;
struct fb_planeinfo_s pinfo;
#ifdef CONFIG_FB_OVERLAY
struct fb_overlayinfo_s oinfo;
#endif
char devname[16];
int nplanes;
int ret;
if (display < 0 || display >= FB_DEV_MAXNUM)
return -EINVAL;
/* Allocate a framebuffer state instance */
fb = (FAR struct fb_chardev_s *)malloc(sizeof(struct fb_chardev_s));
if (fb == NULL)
{
return -ENOMEM;
}
/* Initialize the frame buffer device. */
ret = up_fbinitialize(display);
if (ret < 0)
{
gerr("ERROR: up_fbinitialize() failed for display %d: %d\n", display, ret);
goto errout_with_fb;
}
DEBUGASSERT((unsigned)plane <= UINT8_MAX);
fb->plane = plane;
fb->vtable = up_fbgetvplane(display, plane);
if (fb->vtable == NULL)
{
gerr("ERROR: up_fbgetvplane() failed, vplane=%d\n", plane);
goto errout_with_fb;
}
/* Initialize the frame buffer instance. */
DEBUGASSERT(fb->vtable->getvideoinfo != NULL);
ret = fb->vtable->getvideoinfo(fb->vtable, &vinfo);
if (ret < 0)
{
gerr("ERROR: getvideoinfo() failed: %d\n", ret);
goto errout_with_fb;
}
nplanes = vinfo.nplanes;
DEBUGASSERT(vinfo.nplanes > 0 && (unsigned)plane < vinfo.nplanes);
DEBUGASSERT(fb->vtable->getplaneinfo != NULL);
ret = fb->vtable->getplaneinfo(fb->vtable, plane, &pinfo);
if (ret < 0)
{
gerr("ERROR: getplaneinfo() failed: %d\n", ret);
goto errout_with_fb;
}
fb->fbmem = pinfo.fbmem;
fb->fblen = pinfo.fblen;
fb->bpp = pinfo.bpp;
/* Clear the framebuffer memory */
memset(pinfo.fbmem, 0, pinfo.fblen);
#ifdef CONFIG_FB_OVERLAY
/* Initialize first overlay but do not select */
DEBUGASSERT(fb->vtable->getoverlayinfo != NULL);
ret = fb->vtable->getoverlayinfo(fb->vtable, 0, &oinfo);
if (ret < 0)
{
gerr("ERROR: getoverlayinfo() failed: %d\n", ret);
goto errout_with_fb;
}
/* Clear the overlay memory. Necessary when plane 0 and overlay 0
* different.
*/
memset(oinfo.fbmem, 0, oinfo.fblen);
#endif
/* Register the framebuffer device */
if (nplanes < 2)
{
(void)snprintf(devname, 16, "/dev/fb%d", display);
}
else
{
(void)snprintf(devname, 16, "/dev/fb%d.%d", display, plane);
}
ret = register_driver(devname, &fb_fops, 0666, (FAR void *)fb);
if (ret < 0)
{
gerr("ERROR: register_driver() failed: %d\n", ret);
goto errout_with_fb;
}
g_fb_dev[display] = fb;
return OK;
errout_with_fb:
free(fb);
return ret;
}
int fb_unregister(int display)
{
FAR struct fb_chardev_s *fb;
if (display < 0 || display >= FB_DEV_MAXNUM)
return -EINVAL;
fb = g_fb_dev[display];
up_fbuninitialize(display);
free(fb);
g_fb_dev[display] = NULL;
return 0;
}
+162
View File
@@ -0,0 +1,162 @@
/****************************************************************************
* fs/dirent/fs_closedir.c
*
* Copyright (C) 2007-2009, 2011, 2013-2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "dirent.h"
#include "errno.h"
#include "stdlib.h"
#include "fs/fs.h"
#include "fs/dirent_fs.h"
#include "inode/inode.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: closedir
*
* Description:
* The closedir() function closes the directory stream associated with
* 'dirp'. The directory stream descriptor 'dirp' is not available after
* this call.
*
* Input Parameters:
* dirp -- An instance of type DIR created by a previous call to opendir();
*
* Returned Value:
* The closedir() function returns 0 on success. On error, -1 is
* returned, and errno is set appropriately.
*
****************************************************************************/
int closedir(FAR DIR *dirp)
{
struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp;
#ifndef CONFIG_DISABLE_MOUNTPOINT
struct inode *inode;
#endif
int ret;
/* Verify that we were provided with a valid directory structure */
if (!idir || idir->fd_status != DIRENT_MAGIC)
{
ret = EBADF;
goto errout;
}
/* A special case is when we enumerate an "empty", unused inode. That is
* an inode in the pseudo-filesystem that has no operations and no children.
* This is a "dangling" directory entry that has lost its childre.
*/
if (idir->fd_root)
{
/* This is the 'root' inode of the directory. This means different
* things wih different filesystems.
*/
#ifndef CONFIG_DISABLE_MOUNTPOINT
inode = idir->fd_root;
/* The way that we handle the close operation depends on what kind of
* root inode we have open.
*/
if (INODE_IS_MOUNTPT(inode) && !DIRENT_ISPSEUDONODE(idir->fd_flags))
{
/* The node is a file system mointpoint. Verify that the
* mountpoint supports the closedir() method (not an error if it
* does not)
*/
if (inode->u.i_mops && inode->u.i_mops->closedir)
{
/* Perform the closedir() operation */
ret = inode->u.i_mops->closedir(inode, idir);
if (ret < 0)
{
ret = -ret;
goto errout_with_inode;
}
}
}
else
#endif
{
/* The node is part of the root pseudo file system, release
* our contained reference to the 'next' inode.
*/
if (idir->u.pseudo.fd_next)
{
inode_release(idir->u.pseudo.fd_next);
}
}
/* Release our references on the contained 'root' inode */
inode_release(idir->fd_root);
}
/* Then release the container */
idir->fd_status = 0;
free(idir);
return OK;
#ifndef CONFIG_DISABLE_MOUNTPOINT
errout_with_inode:
inode_release(inode);
free(idir);
#endif
errout:
set_errno(ret);
return VFS_ERROR;
}
+528
View File
@@ -0,0 +1,528 @@
/****************************************************************************
* fs/dirent/fs_opendir.c
*
* Copyright (C) 2007-2009, 2011, 2013-2014, 2017-2018 Gregory Nutt. All
* rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "dirent.h"
#include "string.h"
#include "assert.h"
#include "errno.h"
#include "stdlib.h"
#include "fs/fs.h"
#include "fs/dirent_fs.h"
#include "inode/inode.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: open_mountpoint
*
* Description:
* Handle the case where the inode to be opened is within a mountpoint.
*
* Input Parameters:
* inode -- the inode of the mountpoint to open
* relpath -- the relative path within the mountpoint to open
* dir -- the dirent structure to be initialized
*
* Returned Value:
* On success, OK is returned; Otherwise, a positive errno is returned.
*
****************************************************************************/
#ifndef CONFIG_DISABLE_MOUNTPOINT
static inline int open_mountpoint(FAR struct inode *inode,
FAR const char *relpath,
FAR struct fs_dirent_s *dir)
{
int ret;
/* The inode itself as the 'root' of mounted volume. The actually
* directory is at relpath into the* mounted filesystem.
*
* Verify that the mountpoint inode supports the opendir() method
*/
if (!inode->u.i_mops || !inode->u.i_mops->opendir)
{
return ENOSYS;
}
/* Take reference to the mountpoint inode. Note that we do not use
* inode_addref() because we already hold the tree semaphore.
*/
inode->i_crefs++;
/* Perform the opendir() operation */
ret = inode->u.i_mops->opendir(inode, relpath, dir);
if (ret < 0)
{
/* We now need to back off our reference to the inode. We can't
* call inode_release() to do that unless we release the tree
* semaphore. The following should be safe because: (1) after the
* reference count was incremented above it should be >=1 so it should
* not decrement below zero, and (2) we hold the tree semaphore so no
* other thread should be able to change the reference count.
*/
inode->i_crefs--;
DEBUGASSERT(inode->i_crefs >= 0);
/* Negate the error value so that it can be used to set errno */
return -ret;
}
return OK;
}
#endif
/****************************************************************************
* Name: open_pseudodir
*
* Description:
* Handle the case where the inode to be opened is within the top-level
* pseudo-file system.
*
* Input Parameters:
* inode -- the inode of the mountpoint to open
* dir -- the dirent structure to be initialized
*
* Returned Value:
* None
*
****************************************************************************/
static void open_pseudodir(FAR struct inode *inode, FAR struct fs_dirent_s *dir)
{
/* We have a valid pseudo-filesystem node. Take two references on the
* inode -- one for the parent (fd_root) and one for the child (fd_next).
* Note that we do not call inode_addref because we are holding the tree
* semaphore and that would result in deadlock.
*/
inode->i_crefs++;
inode->i_child->i_crefs++;
dir->fd_root = inode; /* Save the inode where we start */
dir->u.pseudo.fd_next = inode->i_child; /* This is the next node to use for readdir() */
/* Flag the inode as belonging to the pseudo-filesystem */
#ifndef CONFIG_DISABLE_MOUNTPOINT
DIRENT_SETPSEUDONODE(dir->fd_flags);
#endif
}
/****************************************************************************
* Name: open_emptydir
*
* Description:
* Handle the case where the inode to be opened is an empty, directory node
* within the top-level pseudo-file system. That is, it has no operations
* and, therefore, it must be a directory node. But is has no children
* to be enumerated either.
*
* Input Parameters:
* dir -- the dirent structure to be initialized
*
* Returned Value:
* None
*
****************************************************************************/
static inline void open_emptydir(FAR struct fs_dirent_s *dir)
{
/* We have a valid, but empty pseudo-filesystem node. fd_next is NULL
* meaning that we are already at the end of the list of its children.
* fd_root is NULL so that if the directory is rewound, it will still be
* at the end of the list.
*/
/* Flag the inode as belonging to the pseudo-filesystem */
#ifndef CONFIG_DISABLE_MOUNTPOINT
DIRENT_SETPSEUDONODE(dir->fd_flags);
#endif
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: opendir
*
* Description:
* The opendir() function opens a directory stream corresponding to the
* directory name, and returns a pointer to the directory stream. The
* stream is positioned at the first entry in the directory.
*
* Input Parameters:
* path -- the directory to open
*
* Returned Value:
* The opendir() function returns a pointer to the directory stream. On
* error, NULL is returned, and errno is set appropriately.
*
* EACCES - Permission denied.
* EMFILE - Too many file descriptors in use by process.
* ENFILE - Too many files are currently open in the
* system.
* ENOENT - Directory does not exist, or name is an empty
* string.
* ENOMEM - Insufficient memory to complete the operation.
* ENOTDIR - 'path' is not a directory.
*
****************************************************************************/
FAR DIR *opendir(FAR const char *path)
{
FAR struct inode *inode;
FAR struct fs_dirent_s *dir;
FAR const char *relpath;
int ret;
char *fullpath;
char *fullpath_bak;
/* If we are given 'nothing' then we will interpret this as
* request for the root inode.
*/
ret = vfs_normalize_path((const char *)NULL, path, &fullpath);
if (ret < 0)
{
ret = -ret;
goto errout;
}
fullpath_bak = fullpath;
inode_semtake();
/* We don't know what to do with relative pathes */
if (*fullpath != '/')
{
ret = ENOTDIR;
goto errout_with_semaphore;
}
/* Find the node matching the path. */
inode = inode_search((FAR const char **)&fullpath, (FAR struct inode**)NULL,
(FAR struct inode**)NULL, &relpath);
/* Did we get an inode? */
if (inode == NULL)
{
/* 'path' does not exist. */
ret = ENOTDIR;
goto errout_with_semaphore;
}
/* Allocate a type DIR -- which is little more than an inode
* container.
*/
dir = (FAR struct fs_dirent_s *)zalloc(sizeof(struct fs_dirent_s));
if (!dir)
{
/* Insufficient memory to complete the operation. */
ret = ENOMEM;
goto errout_with_semaphore;
}
/* Populate the DIR structure and return it to the caller. The way that
* we do this depends on whenever this is a "normal" pseudo-file-system
* inode or a file system mountpoint.
*/
dir->fd_position = 0; /* This is the position in the read stream */
/* The node is part of the root pseudo file system. Does the inode
* have a child? If so that the child would be the 'root' of a list
* of nodes under the directory.
*/
FAR struct inode *child = inode->i_child;
if (!*relpath && child)
{
/* It looks we have a valid pseudo-filesystem directory node. */
open_pseudodir(inode, dir);
}
#ifndef CONFIG_DISABLE_MOUNTPOINT
if (INODE_IS_MOUNTPT(inode))
{
/* Yes, the node is a file system mountpoint */
dir->fd_root = inode; /* Save the inode where we start */
/* Open the directory at the relative path */
ret = open_mountpoint(inode, relpath, dir);
if (ret != OK)
{
goto errout_with_direntry;
}
}
else
#endif
if (!*relpath && child == NULL)
{
if (inode->u.i_ops == NULL)
{
/* This is a dangling node with no children and no operations. Set
* up to enumerate an empty directory.
*/
open_emptydir(dir);
}
else
{
ret = ENOTDIR;
goto errout_with_direntry;
}
}
else if (*relpath)
{
ret = ENOENT;
goto errout_with_direntry;
}
dir->fd_status = DIRENT_MAGIC;
inode_semgive();
free(fullpath_bak);
return ((DIR *)dir);
/* Nasty goto's make error handling simpler */
errout_with_direntry:
free(dir);
errout_with_semaphore:
inode_semgive();
free(fullpath_bak);
errout:
set_errno(ret);
return NULL;
}
int do_opendir(const char *path, int oflags)
{
int ret;
int fd;
FAR struct inode *inode = NULL;
FAR struct fs_dirent_s *dir = NULL;
FAR const char *relpath = NULL;
char *fullpath = NULL;
FAR struct file *filep = NULL;
FAR struct inode *child = NULL;
struct inode_search_s desc;
/* If we are given 'nothing' then we will interpret this as
* request for the root inode.
*/
ret = vfs_normalize_path((const char *)NULL, path, &fullpath);
if (ret < 0)
{
ret = -ret;
goto errout;
}
/* We don't know what to do with relative pathes */
if (*fullpath != '/')
{
ret = ENOTDIR;
goto errout_with_path;
}
/* Get an inode for this file */
SETUP_SEARCH(&desc, fullpath, false);
ret = inode_find(&desc);
if (ret < 0)
{
PRINTK("ERROR: Failed to find %s\n", fullpath);
/* 'path' does not exist. */
ret = ENOTDIR;
goto errout_with_path;
}
inode = desc.node;
relpath = desc.relpath;
/* Associate the inode with a file structure */
fd = files_allocate(inode, oflags, 0, NULL, 3); /* 3: file start fd */
if (fd < 0)
{
ret = EMFILE;
goto errout_with_inode;
}
/* Get the file structure corresponding to the file descriptor. */
ret = fs_getfilep(fd, &filep);
if (ret < 0)
{
ret = EPERM;
/* The errno value has already been set */
goto errout_with_fd;
}
/* 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;
filep->f_path = fullpath; /* The mem will free in close(fd); */
filep->f_relpath = relpath;
/* Allocate a type DIR -- which is little more than an inode
* container.
*/
dir = (FAR struct fs_dirent_s *)zalloc(sizeof(struct fs_dirent_s));
if (!dir)
{
/* Insufficient memory to complete the operation. */
ret = ENOMEM;
goto errout_with_fd;
}
/* Populate the DIR structure and return it to the caller. The way that
* we do this depends on whenever this is a "normal" pseudo-file-system
* inode or a file system mountpoint.
*/
dir->fd_position = 0; /* This is the position in the read stream */
/* The node is part of the root pseudo file system. Does the inode
* have a child? If so that the child would be the 'root' of a list
* of nodes under the directory.
*/
child = inode->i_child;
if (!*relpath && child)
{
/* It looks we have a valid pseudo-filesystem directory node. */
open_pseudodir(inode, dir);
}
#ifndef CONFIG_DISABLE_MOUNTPOINT
if (INODE_IS_MOUNTPT(inode))
{
/* Yes, the node is a file system mountpoint */
dir->fd_root = inode; /* Save the inode where we start */
/* Open the directory at the relative path */
ret = open_mountpoint(inode, relpath, dir);
if (ret != OK)
{
goto errout_with_direntry;
}
}
else
#endif
if (!*relpath && child == NULL)
{
if (inode->u.i_ops == NULL)
{
/* This is a dangling node with no children and no operations. Set
* up to enumerate an empty directory.
*/
open_emptydir(dir);
}
else
{
ret = ENOTDIR;
goto errout_with_direntry;
}
}
else if (*relpath)
{
ret = ENOENT;
goto errout_with_direntry;
}
dir->fd_status = DIRENT_MAGIC;
filep->f_dir = (struct fs_dirent_s *)dir;
return fd;
/* Nasty goto's make error handling simpler */
errout_with_direntry:
free(dir);
errout_with_fd:
files_release(fd);
errout_with_inode:
inode_release(inode);
errout_with_path:
free(fullpath);
errout:
set_errno(ret);
return -1;
}
+338
View File
@@ -0,0 +1,338 @@
/****************************************************************************
* fs/dirent/fs_readdir.c
*
* Copyright (C) 2007-2009, 2011, 2017-2018 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "string.h"
#include "dirent.h"
#include "errno.h"
#include "unistd.h"
#include "fs/fs.h"
#include "fs/dirent_fs.h"
#include "inode/inode.h"
#include "user_copy.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: readpseudodir
****************************************************************************/
static inline int readpseudodir(struct fs_dirent_s *idir)
{
FAR struct inode *prev;
int ret;
/* Check if we are at the end of the list */
if (!idir->u.pseudo.fd_next)
{
/* End of file and error conditions are not distinguishable with
* readdir. Here we return -ENOENT to signal the end of the
* directory.
*/
return -ENOENT;
}
/* Copy the inode name into the dirent structure */
ret = strncpy_s(idir->fd_dir.d_name, NAME_MAX + 1, idir->u.pseudo.fd_next->i_name, NAME_MAX);
if (ret != EOK)
{
return -ENAMETOOLONG;
}
/* If the node has file operations, we will say that it is a file. */
idir->fd_dir.d_type = 0;
idir->fd_dir.d_off = idir->fd_position;
idir->fd_dir.d_reclen = sizeof(struct dirent);
if (idir->u.pseudo.fd_next->u.i_ops)
{
#ifndef CONFIG_DISABLE_MOUNTPOINT
if (INODE_IS_BLOCK(idir->u.pseudo.fd_next))
{
idir->fd_dir.d_type |= DT_BLK;
}
if (INODE_IS_MOUNTPT(idir->u.pseudo.fd_next))
{
idir->fd_dir.d_type |= DT_DIR;
}
else
#endif
{
idir->fd_dir.d_type |= DT_CHR;
}
}
/* If the node has child node(s) or no operations, then we will say that
* it is a directory rather than a special file. NOTE: that the node can
* be both!
*/
if (idir->u.pseudo.fd_next->i_child || !idir->u.pseudo.fd_next->u.i_ops)
{
idir->fd_dir.d_type |= DT_DIR;
}
/* Now get the inode to vist next time that readdir() is called */
inode_semtake();
prev = idir->u.pseudo.fd_next;
idir->u.pseudo.fd_next = prev->i_peer; /* The next node to visit */
if (idir->u.pseudo.fd_next)
{
/* Increment the reference count on this next node */
idir->u.pseudo.fd_next->i_crefs++;
}
inode_semgive();
if (prev)
{
inode_release(prev);
}
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: do_readdir
*
* Description:
* The do_readdir() function returns a pointer to a dirent structure
* representing the next directory entry in the directory stream pointed
* to by dir. It returns NULL on reaching the end-of-file or if an error
* occurred.
*
* Input Parameters:
* dirp -- An instance of type DIR created by a previous call to opendir();
*
* Returned Value:
* The do_readdir() function returns a pointer to a dirent structure, or NULL
* if an error occurs or end-of-file is reached. On error, errno is set
* appropriately.
*
* EBADF - Invalid directory stream descriptor dir
*
****************************************************************************/
static struct dirent *__readdir(DIR *dirp)
{
FAR struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp;
struct inode *inode_ptr = NULL;
int ret = 0;
/* Verify that we were provided with a valid directory structure */
if (!idir || idir->fd_status != DIRENT_MAGIC)
{
ret = EBADF;
goto errout;
}
/* A special case is when we enumerate an "empty", unused inode. That is
* an inode in the pseudo-filesystem that has no operations and no children.
* This is a "dangling" directory entry that has lost its children.
*/
inode_ptr = idir->fd_root;
if (inode_ptr == NULL)
{
/* End of file and error conditions are not distinguishable
* with readdir. We return NULL to signal either case.
*/
ret = ENOENT;
goto errout;
}
/* The way we handle the readdir depends on the type of inode
* that we are dealing with.
*/
if (DIRENT_ISPSEUDONODE(idir->fd_flags))
{
/* The node is part of the root pseudo file system */
ret = readpseudodir(idir);
if (!ret)
{
idir->fd_position++;
return &idir->fd_dir;
}
}
#ifndef CONFIG_DISABLE_MOUNTPOINT
if (INODE_IS_MOUNTPT(inode_ptr))
{
/* The node is a file system mointpoint. Verify that the mountpoint
* supports the readdir() method
*/
if (!inode_ptr->u.i_mops || !inode_ptr->u.i_mops->readdir)
{
ret = EACCES;
goto errout;
}
/* Perform the readdir() operation */
ret = inode_ptr->u.i_mops->readdir(inode_ptr, idir);
if (!ret)
{
idir->fd_position++;
return &idir->fd_dir;
}
}
#endif
ret = -ret;
errout:
if (ret != OK)
{
set_errno(ret);
}
return (struct dirent *)NULL;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: readdir
*
* Description:
* The readdir() function returns a pointer to a dirent structure
* representing the next directory entry in the directory stream pointed
* to by dir. It returns NULL on reaching the end-of-file or if an error
* occurred.
*
* Inputs:
* dirp -- An instance of type DIR created by a previous call to opendir();
*
* Return:
* The readdir() function returns a pointer to a dirent structure, or NULL
* if an error occurs or end-of-file is reached. On error, errno is set
* appropriately.
*
* EBADF - Invalid directory stream descriptor dir
*
****************************************************************************/
FAR struct dirent *readdir(DIR *dirp)
{
int ret;
int old_err = get_errno();
struct dirent *de = __readdir(dirp);
if (de == NULL)
{
ret = get_errno();
/* Special case: ret = -ENOENT is end of file */
if (ret == ENOENT)
{
set_errno(old_err);
}
}
return de;
}
/* readdir syscall routine */
int do_readdir(int fd, struct dirent **de, unsigned int count)
{
struct dirent *de_src = NULL;
/* Did we get a valid file descriptor? */
#if CONFIG_NFILE_DESCRIPTORS > 0
FAR struct file *filep = NULL;
if (de == NULL)
{
return -EINVAL;
}
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
{
return -EBADF;
}
else
{
/* The descriptor is in a valid range to file descriptor... do the
* read. First, get the file structure.
*/
int ret = fs_getfilep(fd, &filep);
if (ret < 0)
{
/* The errno value has already been set */
return -get_errno();
}
/* Then let do_readdir do all of the work */
de_src = __readdir(filep->f_dir);
if (de_src == NULL)
{
/* Special case: ret = -ENOENT is end of file */
return -get_errno();
}
*de = de_src;
return sizeof(*de_src);
}
#endif
return 0;
}
+155
View File
@@ -0,0 +1,155 @@
/****************************************************************************
* fs/dirent/fs_rewinddir.c
*
* Copyright (C) 2007-2009, 2011, 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "dirent.h"
#include "errno.h"
#include "fs/fs.h"
#include "fs/dirent_fs.h"
#include "inode/inode.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: rewindpseudodir
****************************************************************************/
static inline void rewindpseudodir(struct fs_dirent_s *idir)
{
struct inode *prev;
inode_semtake();
/* Reset the position to the beginning */
prev = idir->u.pseudo.fd_next; /* (Save to delete later) */
idir->u.pseudo.fd_next = idir->fd_root->i_child; /* The next node to visit */
idir->fd_position = 0; /* Reset position */
/* Increment the reference count on the root=next node. We
* should now have two references on the inode.
*/
idir->fd_root->i_child->i_crefs++;
inode_semgive();
/* Then release the reference to the old next inode */
if (prev != NULL)
{
inode_release(prev);
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: rewinddir
*
* Description:
* The rewinddir() function resets the position of the
* directory stream dir to the beginning of the directory.
*
* Input Parameters:
* dirp -- An instance of type DIR created by a previous
* call to opendir();
*
* Returned Value:
* None
*
****************************************************************************/
void rewinddir(FAR DIR *dirp)
{
struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp;
#ifndef CONFIG_DISABLE_MOUNTPOINT
struct inode *inode_ptr;
#endif
/* Verify that we were provided with a valid directory structure,
* A special case is when we enumerate an "empty", unused inode (fd_root
* == 0). That is an inode in the pseudo-filesystem that has no
* operations and no children. This is a "dangling" directory entry that
* has lost its children.
*/
if (!idir || !idir->fd_root || idir->fd_status != DIRENT_MAGIC)
{
set_errno(EBADF);
return;
}
/* The way we handle the readdir depends on the type of inode
* that we are dealing with.
*/
#ifndef CONFIG_DISABLE_MOUNTPOINT
inode_ptr = idir->fd_root;
if (INODE_IS_MOUNTPT(inode_ptr))
{
/* The node is a file system mointpoint. Verify that the mountpoint
* supports the rewinddir() method
*/
if (inode_ptr->u.i_mops && inode_ptr->u.i_mops->rewinddir)
{
/* Perform the rewinddir() operation */
(void)inode_ptr->u.i_mops->rewinddir(inode_ptr, idir);
}
/* Reset position for telldir() */
idir->fd_position = 0;
}
else
#endif
{
/* The node is part of the root pseudo file system */
rewindpseudodir(idir);
}
}
+242
View File
@@ -0,0 +1,242 @@
/****************************************************************************
* fs/dirent/fs_seekdir.c
*
* Copyright (C) 2007, 2008, 2011, 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "sys/types.h"
#include "dirent.h"
#include "errno.h"
#include "fs/fs.h"
#include "fs/dirent_fs.h"
#include "inode/inode.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: seekpseudodir
****************************************************************************/
static inline void seekpseudodir(struct fs_dirent_s *idir, off_t offset)
{
struct inode *curr;
struct inode *prev;
off_t pos;
/* Determine a starting point for the seek. If the seek
* is "forward" from the current position, then we will
* start at the current poisition. Otherwise, we will
* "rewind" to the root dir.
*/
if (offset < idir->fd_position)
{
pos = 0;
curr = idir->fd_root;
}
else
{
pos = idir->fd_position;
curr = idir->u.pseudo.fd_next;
}
/* Traverse the peer list starting at the 'root' of the
* the list until we find the node at 'offset". If devices
* are being registered and unregistered, then this can
* be a very unpredictable operation.
*/
inode_semtake();
for (; curr && pos != offset; pos++, curr = curr->i_peer);
/* Now get the inode to vist next time that readdir() is called */
prev = idir->u.pseudo.fd_next;
idir->u.pseudo.fd_next = curr; /* The next node to visit (might be null) */
idir->fd_position = pos; /* Might be beyond the last dirent */
if (curr)
{
/* Increment the reference count on this next node */
curr->i_crefs++;
}
inode_semgive();
if (prev)
{
inode_release(prev);
}
}
/****************************************************************************
* Name: seekmountptdir
****************************************************************************/
#ifndef CONFIG_DISABLE_MOUNTPOINT
static inline void seekmountptdir(struct fs_dirent_s *idir, off_t offset)
{
struct inode *inode;
off_t pos;
/* Determine a starting point for the seek. If the seek
* is "forward" from the current position, then we will
* start at the current poisition. Otherwise, we will
* "rewind" to the root dir.
*/
inode = idir->fd_root;
if (offset < idir->fd_position)
{
if (inode->u.i_mops && inode->u.i_mops->rewinddir)
{
/* Perform the rewinddir() operation */
inode->u.i_mops->rewinddir(inode, idir);
pos = 0;
}
else
{
/* We can't do the seek and there is no way to return
* an error indication.
*/
return;
}
}
else
{
pos = idir->fd_position;
}
/* This is a brute force approach... we will just read
* directory entries until we are at the desired position.
*/
while (pos < offset)
{
if (!inode->u.i_mops || !inode->u.i_mops->readdir ||
inode->u.i_mops->readdir(inode, idir) < 0)
{
/* We can't read the next entry and there is no way to return
* an error indication.
*/
return;
}
/* Increment the position on each successful read */
pos++;
}
/* If we get here the directory position has been successfully set */
idir->fd_position = pos;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: seekdir
*
* Description:
* The seekdir() function sets the location in the directory stream from
* which the next readdir() call will start. seekdir() should be used with
* an offset returned by telldir().
*
* Input Parameters:
* dirp -- An instance of type DIR created by a previous
* call to opendir();
* offset -- offset to seek to
*
* Returned Value:
* None
*
****************************************************************************/
void seekdir(DIR *dirp, long offset)
{
struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp;
/* Verify that we were provided with a valid directory structure,
* A special case is when we enumerate an "empty", unused inode (fd_root
* == 0). That is an inode in the pseudo-filesystem that has no
* operations and no children. This is a "dangling" directory entry that
* has lost its children.
*/
if (!idir || !idir->fd_root || idir->fd_status != DIRENT_MAGIC)
{
set_errno(EBADF);
return;
}
if (offset < 0)
{
set_errno(EINVAL);
return;
}
/* The way we handle the readdir depends on the type of inode
* that we are dealing with.
*/
#ifndef CONFIG_DISABLE_MOUNTPOINT
if (INODE_IS_MOUNTPT(idir->fd_root))
{
/* The node is a file system mointpoint */
seekmountptdir(idir, offset);
}
else
#endif
{
/* The node is part of the root pseudo file system */
seekpseudodir(idir, offset);
}
}
+88
View File
@@ -0,0 +1,88 @@
/****************************************************************************
* fs/dirent/fs_telldir.c
*
* Copyright (C) 2007-2008, 2011-2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "sys/types.h"
#include "dirent.h"
#include "errno.h"
#include "fs/fs.h"
#include "fs/dirent_fs.h"
#include "inode/inode.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: telldir
*
* Description:
* The telldir() function returns the current location
* associated with the directory stream dirp.
*
* Inputs:
* dirp -- An instance of type DIR created by a previous
* call to opendir();
*
* Return:
* On success, the telldir() function returns the current
* location in the directory stream. On error, -1 is
* returned, and errno is set appropriately.
*
* EBADF - Invalid directory stream descriptor dir
*
****************************************************************************/
long telldir(FAR DIR *dirp)
{
struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp;
if (!idir || !idir->fd_root)
{
set_errno(EBADF);
return (off_t)-1;
}
/* Just return the current position */
return idir->fd_position;
}
+252
View File
@@ -0,0 +1,252 @@
/****************************************************************************
* fs/driver/fs_blockproxy.c
*
* Copyright (C) 2015-2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <semaphore.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include "fs/fs.h"
#include "driver/blockproxy.h"
#if !defined(CONFIG_DISABLE_MOUNTPOINT)
#ifdef LOSCFG_FS_VFS_BLOCK_DEVICE
/****************************************************************************
* Private Data
****************************************************************************/
static uint32_t g_devno;
static sem_t g_devno_sem;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: unique_chardev
*
* Description:
* Create a unique temporary device name in the /dev/ directory of the
* pseudo-file system. We cannot use mktemp for this because it will
* attempt to open() the file.
*
* Input Parameters:
* None
*
* Returned Value:
* The allocated path to the device. This must be released by the caller
* to prevent memory links. NULL will be returned only the case where
* we fail to allocate memory.
*
****************************************************************************/
static char *unique_chardev(void)
{
struct stat statbuf;
char devbuf[16];
uint32_t devno;
int ret;
/* Loop until we get a unique device name */
for (; ;)
{
/* Get the semaphore protecting the path number */
while (sem_wait(&g_devno_sem) != 0)
{
/* The only case that an error should occur here is if the wait
* was awakened by a signal.
*/
ret = get_errno();
LOS_ASSERT(ret == EINTR);
}
/* Get the next device number and release the semaphore */
devno = ++g_devno;
(void)sem_post(&g_devno_sem);
/* Construct the full device number */
devno &= 0xffffff;
ret = snprintf_s(devbuf, 16, 14, "/dev/tmp%06lx", (unsigned long)devno);
/* length of the format string is 14 */
if (ret < 0)
{
set_errno(ENAMETOOLONG);
return strdup(devbuf);
}
/* Make sure that file name is not in use */
ret = stat(devbuf, &statbuf);
if (ret < 0)
{
DEBUGASSERT(errno == ENOENT);
return strdup(devbuf);
}
/* It is in use, try again */
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: block_proxy
*
* Description:
* Create a temporary char driver using drivers/bch to mediate character
* oriented accessed to the block driver.
*
* Input Parameters:
* blkdev - The path to the block driver
* oflags - Character driver open flags
*
* Returned Value:
* If positive, non-zero file descriptor is returned on success. This
* is the file descriptor of the nameless character driver that mediates
* accesses to the block driver.
*
* Errors that may be returned:
*
* ENOMEM - Failed to create a temporay path name.
*
* Plus:
*
* - Errors reported from bchdev_register()
* - Errors reported from open() or unlink()
*
****************************************************************************/
int block_proxy(FAR const char *blkdev, int oflags)
{
FAR char *chardev;
bool readonly;
int ret;
int fd;
DEBUGASSERT(blkdev);
(void)sem_init(&g_devno_sem, 0, 1);
/* Create a unique temporary file name for the character device */
chardev = unique_chardev();
if (chardev == NULL)
{
PRINTK("ERROR: Failed to create temporary device name\n");
(void)sem_destroy(&g_devno_sem);
return -ENOMEM;
}
/* Should this character driver be read-only? */
readonly = (((unsigned int)oflags & O_ACCMODE) == O_RDONLY);
/* Wrap the block driver with an instance of the BCH driver */
ret = bchdev_register(blkdev, chardev, readonly);
if (ret < 0)
{
PRINTK("ERROR: bchdev_register(%s, %s) failed: %d\n", blkdev, chardev, ret);
goto errout_with_chardev;
}
/* Open the newly created character driver */
oflags =(unsigned int)oflags & (~(O_CREAT | O_EXCL | O_APPEND | O_TRUNC));
fd = open(chardev, oflags);
if (fd < 0)
{
ret = -errno;
PRINTK("ERROR: Failed to open %s: %d\n", chardev, ret);
goto errout_with_bchdev;
}
/* Unlink the character device name. The driver instance will persist,
* provided that CONFIG_DISABLE_PSEUDOFS_OPERATIONS=y (otherwise, we have
* a problem here!)
*/
ret = unlink(chardev);
if (ret < 0)
{
ret = -errno;
PRINTK("ERROR: Failed to unlink %s: %d\n", chardev, ret);
}
ret = unregister_driver(chardev);
if (ret < 0 && ret != -EBUSY)
{
PRINTK("ERROR: Failed to unregister %s: %d\n", chardev, ret);
}
/* Free the allocate character driver name and return the open file
* descriptor.
*/
(void)free(chardev);
(void)sem_destroy(&g_devno_sem);
return fd;
errout_with_bchdev:
(void)bchdev_unregister(chardev);
(void)unlink(chardev);
(void)unregister_driver(chardev);
errout_with_chardev:
(void)free(chardev);
(void)sem_destroy(&g_devno_sem);
return ret;
}
#endif
#endif /* !CONFIG_DISABLE_MOUNTPOINT */
+146
View File
@@ -0,0 +1,146 @@
/****************************************************************************
* fs/driver/fs_closeblockdriver.c
*
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in pathname and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of pathname code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "fs/fs.h"
#include "vfs_config.h"
#include "debug.h"
#include "errno.h"
#include "inode/inode.h"
#include "disk.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: close_blockdriver
*
* Description:
* Call the close method and release the inode
*
* Input Parameters:
* inode - reference to the inode of a block driver opened by open_blockdriver
*
* Returned Value:
* Returns zero on success or a negated errno on failure:
*
* EINVAL - inode is NULL
* ENOTBLK - The inode is not a block driver
*
****************************************************************************/
int close_blockdriver(FAR struct inode *inode_ptr)
{
int ret = 0; /* Assume success */
los_part *part = NULL;
los_disk *disk = NULL;
/* Sanity checks */
if (!inode_ptr || !inode_ptr->u.i_bops)
{
ret = -EINVAL;
goto errout;
}
/* Verify that the inode is a block driver. */
if (!INODE_IS_BLOCK(inode_ptr))
{
fdbg("inode is not a block driver\n");
ret = -ENOTBLK;
goto errout;
}
part = los_part_find(inode_ptr);
if (part != NULL)
{
disk = get_disk(part->disk_id);
if (disk == NULL)
{
ret = -EINVAL;
goto errout_with_inode;
}
if (pthread_mutex_lock(&disk->disk_mutex) != ENOERR)
{
PRINT_ERR("%s %d, mutex lock fail!\n", __FUNCTION__, __LINE__);
inode_release(inode_ptr);
return -1;
}
if (disk->disk_status == STAT_INUSED)
{
/* Close the block driver. Not that no mutually exclusive access
* to the driver is enforced here. That must be done in the driver
* if needed.
*/
if (inode_ptr->u.i_bops->close != NULL)
{
ret = inode_ptr->u.i_bops->close(inode_ptr);
}
}
if (pthread_mutex_unlock(&disk->disk_mutex) != ENOERR)
{
PRINT_ERR("%s %d, mutex unlock fail!\n", __FUNCTION__, __LINE__);
inode_release(inode_ptr);
return -1;
}
}
else
{
if ((inode_ptr->i_flags & FSNODEFLAG_DELETED) == 0 && inode_ptr->u.i_bops->close != NULL)
{
ret = inode_ptr->u.i_bops->close(inode_ptr);
}
}
errout_with_inode:
/* Then release the reference on the inode */
inode_release(inode_ptr);
errout:
return ret;
}
+544
View File
@@ -0,0 +1,544 @@
/****************************************************************************
* fs/driver/fs_devsyslog.c
*
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "los_task.h"
#include "vfs_config.h"
#include "sys/types.h"
#include "stdint.h"
#include "stdio.h"
#include "unistd.h"
#include "fcntl.h"
#include "semaphore.h"
#include "assert.h"
#include "fs/fs.h"
#include "inode/inode.h"
#if defined(CONFIG_SYSLOG) && defined(CONFIG_SYSLOG_CHAR)
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Open the device/file write-only, try to create (file) it if it doesn't
* exist, if the file that already exists, then append the new log data to
* end of the file.
*/
#define SYSLOG_OFLAGS (O_WRONLY | O_CREAT | O_APPEND)
/* An invalid thread ID */
#define NO_HOLDER ((pid_t)-1)
/****************************************************************************
* Private Types
****************************************************************************/
/* This enumeration represents the state of the SYSLOG device interface */
enum syslog_state_e
{
SYSLOG_UNINITIALIZED = 0, /* SYSLOG has not been initialized */
SYSLOG_INITIALIZING, /* SYSLOG is being initialized */
SYSLOG_REOPEN, /* SYSLOG open failed... try again later */
SYSLOG_FAILURE, /* SYSLOG open failed... don't try again */
SYSLOG_OPENED, /* SYSLOG device is open and ready to use */
};
/* This structure contains all SYSLOGing state information */
struct syslog_dev_s
{
uint8_t sl_state; /* See enum syslog_state_e */
sem_t sl_sem; /* Enforces mutually exclusive access */
pid_t sl_holder; /* PID of the thread that holds the semaphore */
struct file sl_file; /* The syslog file structure */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/* This is the device structure for the console or syslogging function. */
static struct syslog_dev_s g_sysdev;
static const uint8_t g_syscrlf[2] =
{
'\r', '\n'
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: syslog_takesem
*
* Description:
* Write to the syslog device
*
****************************************************************************/
static inline int syslog_takesem(void)
{
pid_t me = getpid();
int ret;
/* Does this thread already hold the semaphore? That could happen if
* we wer called recursively, i.e., if the logic kicked off by
* syslog_write() where to generate more debug output. Return an error
* in that case.
*/
if (g_sysdev.sl_holder == me)
{
/* Return an error (instead of deadlocking) */
return -EWOULDBLOCK;
}
/* Either the semaphore is available or is currently held by another
* thread. Wait for it to become available.
*/
ret = sem_wait(&g_sysdev.sl_sem);
if (ret < 0)
{
return -get_errno();
}
/* We hold the semaphore. We can safely mark ourself as the holder
* of the semaphore.
*/
g_sysdev.sl_holder = me;
return OK;
}
/****************************************************************************
* Name: syslog_givesem
*
* Description:
* Write to the syslog device
*
****************************************************************************/
static inline void syslog_givesem(void)
{
#ifdef CONFIG_DEBUG
pid_t me = getpid();
DEBUGASSERT(g_sysdev.sl_holder == me);
#endif
/* Relinquish the semaphore */
g_sysdev.sl_holder = NO_HOLDER;
(void)sem_post(&g_sysdev.sl_sem);
}
/****************************************************************************
* Name: syslog_write
*
* Description:
* Write to the syslog device
*
****************************************************************************/
static inline ssize_t syslog_write(FAR const void *buf, size_t nbytes)
{
FAR struct inode *inode_ptr;
/* Let the driver perform the write */
inode_ptr = g_sysdev.sl_file.f_inode;
return inode_ptr->u.i_ops->write(&g_sysdev.sl_file, (const char *)buf, nbytes);
}
/****************************************************************************
* Name: syslog_flush
*
* Description:
* Flush any buffer data in the file system to media.
*
****************************************************************************/
#ifndef CONFIG_DISABLE_MOUNTPOINT
static inline void syslog_flush(void)
{
FAR struct inode *inode_ptr = g_sysdev.sl_file.f_inode;
/* Is this a mountpoint? Does it support the sync method? */
if (INODE_IS_MOUNTPT(inode_ptr) && inode_ptr->u.i_mops->sync)
{
/* Yes... synchronize to the stream */
(void)inode_ptr->u.i_mops->sync(&g_sysdev.sl_file);
}
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: syslog_initialize
*
* Description:
* Initialize to use the character device (or file) at
* CONFIG_SYSLOG_DEVPATH as the SYSLOG sink.
*
* NOTE that this implementation excludes using a network connection as
* SYSLOG device. That would be a good extension.
*
****************************************************************************/
int syslog_initialize(void)
{
FAR struct inode *inode_ptr;
FAR const char *relpath = NULL;
int ret;
struct inode_search_s desc;
/* 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 */
SETUP_SEARCH(&desc, CONFIG_SYSLOG_DEVPATH, false);
ret = inode_find(&desc);
/* Get the search results */
if (ret < 0)
{
/* 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 -EACCES;
}
inode_ptr = desc.node;
relpath = desc.relpath;
/* Verify that the inode is valid and either a character driver or a
* mountpoint.
*/
#ifndef CONFIG_DISABLE_MOUNTPOINT
if ((!INODE_IS_DRIVER(inode_ptr) && !INODE_IS_MOUNTPT(inode_ptr)))
#else
if (!INODE_IS_DRIVER(inode_ptr))
#endif
{
ret = -ENXIO;
goto errout_with_inode;
}
/* Make sure that the "entity" at this inode supports write access */
if (!inode_ptr->u.i_ops || !inode_ptr->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_ptr;
/* Perform the low-level open operation. */
ret = OK;
if (inode_ptr->u.i_ops->open)
{
/* Is the inode a mountpoint? */
#ifndef CONFIG_DISABLE_MOUNTPOINT
if (INODE_IS_MOUNTPT(inode_ptr))
{
/* 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_ptr->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_ptr->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. */
(void)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_ptr);
g_sysdev.sl_state = SYSLOG_FAILURE;
return ret;
}
/****************************************************************************
* Name: syslog_putc
*
* Description:
* This is the low-level system logging interface. The debugging/syslogging
* interfaces are syslog() and lowsyslog(). The difference is is that
* the syslog() function writes to syslogging device (usually fd=1, stdout)
* whereas lowsyslog() uses a lower level interface that works from
* interrupt handlers. This function is a a low-level interface used to
* implement lowsyslog().
*
****************************************************************************/
int syslog_putc(int ch)
{
ssize_t nbytes;
uint8_t uch;
int errcode;
int ret;
/* Ignore any output:
*
* (1) Before the SYSLOG device has been initialized. This could happen
* from debug output that occurs early in the boot sequence before
* syslog_initialize() is called (SYSLOG_UNINITIALIZED).
* (2) While the device is being initialized. The case could happen if
* debug output is generated while syslog_initialize() executes
* (SYSLOG_INITIALIZING).
* (3) While we are generating SYSLOG output. The case could happen if
* debug output is generated while syslog_putc() executes
* (This case is actually handled inside of syslog_semtake()).
* (4) Any debug output generated from interrupt handlers. A disadvantage
* of using the generic character device for the SYSLOG is that it
* cannot handle debug output generated from interrupt level handlers.
* (5) Any debug output generated from the IDLE loop. The character
* driver interface is blocking and the IDLE thread is not permitted
* to block.
* (6) If an irrecoverable failure occurred during initialization. In
* this case, we won't ever bother to try again (ever).
*
* NOTE: That the third case is different. It applies only to the thread
* that currently holds the sl_sem sempaphore. Other threads should wait.
* that is why that case is handled in syslog_semtake().
*/
/* Cases (4) and (5) */
if (OS_INT_ACTIVE || getpid() == 0)
{
errcode = ENOSYS;
goto errout_with_errcode;
}
/* We can save checks in the usual case: That after the SYSLOG device
* has been successfully opened.
*/
if (g_sysdev.sl_state != SYSLOG_OPENED)
{
/* Case (1) and (2) */
if (g_sysdev.sl_state == SYSLOG_UNINITIALIZED ||
g_sysdev.sl_state == SYSLOG_INITIALIZING)
{
errcode = EAGAIN; /* Can't access the SYSLOG now... maybe next time? */
goto errout_with_errcode;
}
/* Case (6) */
if (g_sysdev.sl_state == SYSLOG_FAILURE)
{
errcode = ENXIO; /* There is no SYSLOG device */
goto errout_with_errcode;
}
/* syslog_initialize() is called as soon as enough of the operating
* system is in place to support the open operation... but it is
* possible that the SYSLOG device is not yet registered at that time.
* In this case, we know that the system is sufficiently initialized
* to support an attempt to re-open the SYSLOG device.
*
* NOTE that the scheduler is locked. That is because we do not have
* fully initialized semaphore capability until the SYSLOG device is
* successfully initialized
*/
LOS_TaskLock();
if (g_sysdev.sl_state == SYSLOG_REOPEN)
{
/* Try again to initialize the device. We may do this repeatedly
* because the log device might be something that was not ready
* the first time that syslog_initializee() was called (such as a
* USB serial device that has not yet been connected or a file in
* an NFS mounted file system that has not yet been mounted).
*/
ret = syslog_initialize();
if (ret < 0)
{
LOS_TaskUnlock();
errcode = -ret;
goto errout_with_errcode;
}
}
LOS_TaskUnlock();
DEBUGASSERT(g_sysdev.sl_state == SYSLOG_OPENED);
}
/* Ignore carriage returns */
if (ch == '\r')
{
return ch;
}
/* The syslog device is ready for writing and we have something of
* value to write.
*/
ret = syslog_takesem();
if (ret < 0)
{
/* We probably already hold the semaphore and were probably
* re-entered by the logic kicked off by syslog_write().
* We might also have been interrupted by a signal. Either
* way, we are outta here.
*/
errcode = -ret;
goto errout_with_errcode;
}
/* Pre-pend a newline with a carriage return. */
if (ch == '\n')
{
/* Write the CR-LF sequence */
nbytes = syslog_write(g_syscrlf, 2);
/* Synchronize the file when each CR-LF is encountered (i.e.,
* implements line buffering always).
*/
#ifndef CONFIG_DISABLE_MOUNTPOINT
if (nbytes > 0)
{
syslog_flush();
}
#endif
}
else
{
/* Write the non-newline character (and don't flush) */
uch = (uint8_t)ch;
nbytes = syslog_write(&uch, 1);
}
syslog_givesem();
/* Check if the write was successful. If not, nbytes will be
* a negated errno value.
*/
if (nbytes < 0)
{
errcode = -ret;
goto errout_with_errcode;
}
return ch;
errout_with_errcode:
if (errcode != 0)
{
set_errno(errcode);
}
return EOF;
}
#endif /* CONFIG_SYSLOG && CONFIG_SYSLOG_CHAR */
+134
View File
@@ -0,0 +1,134 @@
/****************************************************************************
* fs/driver/fs_findblockdriver.c
*
* Copyright (C) 2008, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in pathname and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of pathname code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "sys/types.h"
#include "sys/mount.h"
#include "debug.h"
#include "errno.h"
#include "fs/fs.h"
#include "inode/inode.h"
#include "driver/driver.h"
#include "string.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: find_blockdriver
*
* Description:
* Return the inode of the block driver specified by 'pathname'
*
* Input Parameters:
* pathname - The full path to the block driver to be located
* mountflags - If MS_RDONLY is not set, then driver must support write
* operations (see include/sys/mount.h)
* ppinode - Address of the location to return the inode reference
*
* Returned Value:
* Returns zero on success or a negated errno on failure:
*
* ENOENT - No block driver of this name is registered
* ENOTBLK - The inode associated with the pathname is not a block driver
* EACCESS - The MS_RDONLY option was not set but this driver does not
* support write access
*
****************************************************************************/
int find_blockdriver(FAR const char *pathname, int mountflags,
FAR struct inode **ppinode)
{
FAR struct inode *inode_ptr = NULL;
int ret = 0; /* Assume success */
struct inode_search_s desc;
/* Sanity checks */
#ifdef CONFIG_DEBUG
if (pathname == NULL || ppinode == NULL)
{
ret = -EINVAL;
goto errout;
}
#endif
/* Find the inode registered with this pathname */
SETUP_SEARCH(&desc, pathname, false);
ret = inode_find(&desc);
if (ret < 0)
{
ret = -EACCES;
goto errout;
}
/* Get the search results */
inode_ptr = desc.node;
/* Verify that the inode is a block driver. */
if (!INODE_IS_BLOCK(inode_ptr))
{
fdbg("%s is not a block driver\n", pathname);
ret = -ENOTBLK;
goto errout_with_inode;
}
/* Make sure that the inode supports the requested access */
if (inode_ptr->u.i_bops == NULL || inode_ptr->u.i_bops->read == NULL ||
(inode_ptr->u.i_bops->write == NULL && (mountflags & MS_RDONLY) == 0))
{
fdbg("%s does not support requested access\n", pathname);
ret = -EACCES;
goto errout_with_inode;
}
*ppinode = inode_ptr;
return OK;
errout_with_inode:
inode_release(inode_ptr);
errout:
return ret;
}
+170
View File
@@ -0,0 +1,170 @@
/****************************************************************************
* fs/driver/fs_openblockdriver.c
*
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in pathname and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of pathname code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "debug.h"
#include "errno.h"
#include "fs/fs.h"
#include "inode/inode.h"
#include "driver/driver.h"
#include "disk.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: open_blockdriver
*
* Description:
* Return the inode of the block driver specified by 'pathname'
*
* Input Parameters:
* pathname - the full path to the block driver to be opened
* mountflags - if MS_RDONLY is not set, then driver must support write
* operations (see include/sys/mount.h)
* ppinode - address of the location to return the inode reference
*
* Returned Value:
* Returns zero on success or a negated errno on failure:
*
* EINVAL - pathname or pinode is NULL
* ENOENT - No block driver of this name is registered
* ENOTBLK - The inode associated with the pathname is not a block driver
* EACCESS - The MS_RDONLY option was not set but this driver does not
* support write access
*
****************************************************************************/
int open_blockdriver(FAR const char *pathname, int mountflags,
FAR struct inode **ppinode)
{
FAR struct inode *inode_ptr = NULL;
los_part *part = NULL;
los_disk *disk = NULL;
int ret;
/* Minimal sanity checks */
#ifdef CONFIG_DEBUG
if (ppinode == NULL)
{
ret = -EINVAL;
goto errout;
}
#endif
/* Find the inode associated with this block driver name. find_blockdriver
* will perform all additional error checking.
*/
ret = find_blockdriver(pathname, mountflags, &inode_ptr);
if (ret < 0)
{
fdbg("Failed to file %s block driver\n", pathname);
goto errout;
}
/* Open the block driver. Note that no mutually exclusive access
* to the driver is enforced here. That must be done in the driver
* if needed.
*/
part = los_part_find(inode_ptr);
if (part != NULL)
{
disk = get_disk(part->disk_id);
if (disk == NULL)
{
ret = -EINVAL;
goto errout_with_inode;
}
if (pthread_mutex_lock(&disk->disk_mutex) != ENOERR)
{
PRINT_ERR("%s %d, mutex lock fail!\n", __FUNCTION__, __LINE__);
inode_release(inode_ptr);
return -1;
}
if (disk->disk_status == STAT_INUSED)
{
if (inode_ptr->u.i_bops->open != NULL)
{
ret = inode_ptr->u.i_bops->open(inode_ptr);
if (ret < 0)
{
fdbg("%s driver open failed\n", pathname);
(void)pthread_mutex_unlock(&disk->disk_mutex);
goto errout_with_inode;
}
}
}
if (pthread_mutex_unlock(&disk->disk_mutex) != ENOERR)
{
PRINT_ERR("%s %d, mutex unlock fail!\n", __FUNCTION__, __LINE__);
inode_release(inode_ptr);
return -1;
}
}
else
{
if ((inode_ptr->i_flags & FSNODEFLAG_DELETED) == 0 && inode_ptr->u.i_bops->open != NULL)
{
ret = inode_ptr->u.i_bops->open(inode_ptr);
if (ret < 0)
{
fdbg("%s driver open failed\n", pathname);
goto errout_with_inode;
}
}
}
*ppinode = inode_ptr;
return OK;
errout_with_inode:
inode_release(inode_ptr);
errout:
return ret;
}
+118
View File
@@ -0,0 +1,118 @@
/****************************************************************************
* fs/driver/fs_registerblockdriver.c
*
* Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "sys/types.h"
#include "errno.h"
#include "fs/fs.h"
#include "inode/inode.h"
#include "string.h"
#ifndef CONFIG_DISABLE_MOUNTPOINT
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: register_blockdriver
*
* Description:
* Register a block driver inode the pseudo file system.
*
* Input parameters:
* path - The path to the inode to create
* bops - The block driver operations structure
* mode - inmode priviledges (not used)
* priv - Private, user data that will be associated with the inode.
*
* Returned Value:
* Zero on success (with the inode point in 'inode'); A negated errno
* value is returned on a failure (all error values returned by
* inode_reserve):
*
* EINVAL - 'path' is invalid for this operation
* EEXIST - An inode already exists at 'path'
* ENOMEM - Failed to allocate in-memory resources for the operation
*
****************************************************************************/
int register_blockdriver(FAR const char *path,
FAR const struct block_operations *bops,
mode_t mode, FAR void *priv)
{
FAR struct inode *node;
int ret;
if (path == NULL || strlen(path) >= PATH_MAX || strncmp("/dev/", path, DEV_PATH_LEN) != 0)
{
return EINVAL;
}
/* Insert an inode for the device driver -- we need to hold the inode
* semaphore to prevent access to the tree while we this. This is because
* we will have a momentarily bad true until we populate the inode with
* valid data.
*/
inode_semtake();
ret = inode_reserve(path, &node);
if (ret >= 0)
{
/* We have it, now populate it with block driver specific information. */
INODE_SET_BLOCK(node);
node->u.i_bops = bops;
#ifdef LOSCFG_FILE_MODE
node->i_mode = mode;
#endif
node->i_private = priv;
ret = OK;
}
inode_semgive();
return ret;
}
#endif /* !CONFIG_DISABLE_MOUNTPOINT */
+112
View File
@@ -0,0 +1,112 @@
/****************************************************************************
* fs/driver/fs_registerdriver.c
*
* Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "sys/types.h"
#include "errno.h"
#include "fs/fs.h"
#include "inode/inode.h"
#include "string.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: register_driver
*
* Description:
* Register a character driver inode the pseudo file system.
*
* Input Parameters:
* path - The path to the inode to create
* fops - The file operations structure
* mode - inmode priviledges (not used)
* priv - Private, user data that will be associated with the inode.
*
* Returned Value:
* Zero on success (with the inode point in 'inode'); A negated errno
* value is returned on a failure (all error values returned by
* inode_reserve):
*
* EINVAL - 'path' is invalid for this operation
* EEXIST - An inode already exists at 'path'
* ENOMEM - Failed to allocate in-memory resources for the operation
*
****************************************************************************/
int register_driver(FAR const char *path, FAR const struct file_operations_vfs *fops,
mode_t mode, FAR void *priv)
{
FAR struct inode *node;
int ret;
if (path == NULL || strlen(path) >= PATH_MAX || strncmp("/dev/", path, DEV_PATH_LEN) != 0)
{
return -EINVAL;
}
/* Insert a dummy node -- we need to hold the inode semaphore because we
* will have a momentarily bad structure.
*/
inode_semtake();
ret = inode_reserve(path, &node);
if (ret >= 0)
{
/* We have it, now populate it with driver specific information.
* NOTE that the initial reference count on the new inode is zero.
*/
INODE_SET_DRIVER(node);
node->u.i_ops = fops;
#ifdef LOSCFG_FILE_MODE
node->i_mode = mode & (S_IRWXU|S_IRWXG|S_IRWXO);
#endif
node->i_private = priv;
ret = OK;
}
inode_semgive();
return ret;
}
+73
View File
@@ -0,0 +1,73 @@
/****************************************************************************
* fs/driver/fs_unregisterblockdriver.c
*
* Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "fs/fs.h"
#include "inode/inode.h"
#include "string.h"
#include "errno.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: unregister_blockdriver
*
* Description:
* Remove the block driver inode at 'path' from the pseudo-file system
*
****************************************************************************/
int unregister_blockdriver(const char *path)
{
int ret;
if (path == NULL || strlen(path) >= PATH_MAX || strncmp("/dev/", path, DEV_PATH_LEN) != 0)
{
return EINVAL;
}
inode_semtake();
ret = inode_remove(path);
inode_semgive();
return ret;
}
+73
View File
@@ -0,0 +1,73 @@
/****************************************************************************
* fs/driver/fs_unregisterdriver.c
*
* Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "fs/fs.h"
#include "inode/inode.h"
#include "string.h"
#include "errno.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: unregister_driver
*
* Description:
* Remove the character driver inode at 'path' from the pseudo-file system
*
****************************************************************************/
int unregister_driver(FAR const char *path)
{
int ret;
if (path == NULL || strlen(path) >= PATH_MAX || strncmp("/dev/", path, DEV_PATH_LEN) != 0)
{
return -EINVAL;
}
inode_semtake();
ret = inode_remove(path);
inode_semgive();
return ret;
}
+62
View File
@@ -0,0 +1,62 @@
/****************************************************************************
* fs/fs_initialize.c
*
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "inode.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: fs_initialize
*
* Description:
* This is called from the OS initialization logic to configure the file
* system.
*
****************************************************************************/
void fs_initialize(void)
{
/* Initial inode, file, and VFS data structures */
inode_initialize();
}
+1001
View File
File diff suppressed because it is too large Load Diff
+231
View File
@@ -0,0 +1,231 @@
/****************************************************************************
* fs/inode/fs_foreachinode.c
*
* Copyright (C) 2012-2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "errno.h"
#include "fs/fs.h"
#include "inode/inode.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Is it better to allocate the struct inode_path_s from the heap? or
* from the stack? This decision depends on how often this is down and
* how much stack space you can afford.
*/
#define ENUM_INODE_ALLOC 1
/****************************************************************************
* Private Types
****************************************************************************/
/* This structure manages the full path to the inode. */
struct inode_path_s
{
foreach_inode_t handler;
FAR void *arg;
char path[CONFIG_PATH_MAX];
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: foreach_inodelevel
*
* Description:
* This is the recursive 'heart' of foreach_inode. It will visit each
* inode at this level in the hierarchy and recurse handle each inode
* at the next level down.
*
* Assumptions:
* The caller holds the inode semaphore.
*
****************************************************************************/
static int foreach_inodelevel(FAR struct inode *node, struct inode_path_s *info)
{
int ret = OK;
/* Visit each node at this level */
for (; node; node = node->i_peer)
{
/* Give the next inode to the callback */
ret = info->handler(node, info->path, info->arg);
/* Break out of the loop early if the handler returns a non-zero
* value.
*/
if (ret != 0)
{
break;
}
/* If there is a level 'beneath' this one, then recurse to visit all
* of the inodes at that level.
*/
if (node->i_child)
{
/* Construct the path to the next level */
int pathlen = strlen(info->path);
int namlen = strlen(node->i_name) + 1;
/* Make sure that this would not exceed the maximum path length */
if (pathlen + namlen >= PATH_MAX)
{
ret = -ENAMETOOLONG;
break;
}
/* Append the path segment to this inode and recurse */
ret = snprintf_s(&info->path[pathlen], CONFIG_PATH_MAX - pathlen,
CONFIG_PATH_MAX - pathlen - 1, "/%s", node->i_name);
if (ret < 0)
{
ret = -ENAMETOOLONG;
break;
}
ret = foreach_inodelevel(node->i_child, info);
/* Truncate the path name back to the correct length */
info->path[pathlen] = '\0';
/* Return early if the handler at the lower level returned a non-
* zero value
*/
if (ret != 0)
{
break;
}
}
}
/* Return the result of the traversal. */
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: foreach_inode
*
* Description:
* Visit each inode in the pseudo-file system. The traversal is terminated
* when the callback 'handler' returns a non-zero value, or when all of
* the inodes have been visited.
*
* NOTE 1: Use with caution... The pseudo-file system is locked throughout
* the traversal.
* NOTE 2: The search algorithm is recursive and could, in principle, use
* an indeterminant amount of stack space. This will not usually be a
* real work issue.
*
****************************************************************************/
int foreach_inode(foreach_inode_t handler, FAR void *arg)
{
#ifdef ENUM_INODE_ALLOC
FAR struct inode_path_s *info;
int ret;
/* Allocate the mountpoint info structure */
info = (FAR struct inode_path_s *)malloc(sizeof(struct inode_path_s));
if (!info)
{
return -ENOMEM;
}
/* Initialize the info structure */
info->handler = handler;
info->arg = arg;
info->path[0] = '\0';
/* Start the recursion at the root inode */
inode_semtake();
ret = foreach_inodelevel(g_root_inode, info);
inode_semgive();
/* Free the info structure and return the result */
free(info);
return ret;
#else
struct inode_path_s info;
int ret;
/* Initialize the info structure */
info.handler = handler;
info.arg = arg;
info.path[0] = '\0';
/* Start the recursion at the root inode */
inode_semtake();
ret = foreach_inodelevel(g_root_inode, &info);
inode_semgive();
return ret;
#endif
}
+188
View File
@@ -0,0 +1,188 @@
/****************************************************************************
* fs/inode/fs_inode.c
*
* Copyright (C) 2007-2009, 2011-2012, 2016-2017 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "assert.h"
#include "errno.h"
#include "semaphore.h"
#include "stdlib.h"
#include "fs/fs.h"
#include "unistd.h"
#include "inode/inode.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define NO_HOLDER ((pid_t)-1)
/****************************************************************************
* Private Types
****************************************************************************/
/* Implements a re-entrant mutex for inode access. This must be re-entrant
* because there can be cycles. For example, it may be necessary to destroy
* a block driver inode on umount() after a removable block device has been
* removed. In that case umount() holds the inode semaphore, but the block
* driver may callback to unregister_blockdriver() after the un-mount,
* requiring the semaphore again.
*/
struct inode_sem_s
{
sem_t sem; /* The semaphore */
pid_t holder; /* The current holder of the semaphore */
int16_t count; /* Number of counts held */
};
/****************************************************************************
* Private Data
****************************************************************************/
static struct inode_sem_s g_inode_sem;
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: inode_initialize
*
* Description:
* This is called from the OS initialization logic to configure the file
* system.
*
****************************************************************************/
void inode_initialize(void)
{
/* Initialize the semaphore to one (to support one-at-a-time access to the
* inode tree).
*/
(void)sem_init(&g_inode_sem.sem, 0, 1);
g_inode_sem.holder = NO_HOLDER;
g_inode_sem.count = 0;
/* Initialize files array (if it is used) */
#ifdef CONFIG_HAVE_WEAKFUNCTIONS
if (files_initialize != NULL)
#endif
{
files_initialize();
}
}
/****************************************************************************
* Name: inode_semtake
*
* Description:
* Get exclusive access to the in-memory inode tree (g_inode_sem).
*
****************************************************************************/
void inode_semtake(void)
{
pid_t me;
/* Do we already hold the semaphore? */
me = getpid();
if (me == g_inode_sem.holder)
{
/* Yes... just increment the count */
g_inode_sem.count++;
DEBUGASSERT(g_inode_sem.count > 0);
}
/* Take the semaphore (perhaps waiting) */
else
{
while (sem_wait(&g_inode_sem.sem) != 0)
{
/* The only case that an error should occur here is if the wait
* was awakened by a signal.
*/
LOS_ASSERT(get_errno() == EINTR);
}
/* No we hold the semaphore */
g_inode_sem.holder = me;
g_inode_sem.count = 1;
}
}
/****************************************************************************
* Name: inode_semgive
*
* Description:
* Relinquish exclusive access to the in-memory inode tree (g_inode_sem).
*
****************************************************************************/
void inode_semgive(void)
{
DEBUGASSERT(g_inode_sem.holder == getpid());
/* Is this our last count on the semaphore? */
if (g_inode_sem.count > 1)
{
/* No.. just decrement the count */
g_inode_sem.count--;
}
/* Yes.. then we can really release the semaphore */
else
{
g_inode_sem.holder = NO_HOLDER;
g_inode_sem.count = 0;
(void)sem_post(&g_inode_sem.sem);
}
}
+67
View File
@@ -0,0 +1,67 @@
/****************************************************************************
* fs/inode/fs_inodeaddref.c
*
* Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <vfs_config.h>
#include <errno.h>
#include <fs/fs.h>
#include "inode/inode.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: inode_addref
*
* Description:
* Increment the reference count on an inode (as when a file descriptor
* is dup'ed).
*
****************************************************************************/
void inode_addref(FAR struct inode *inode)
{
if (inode)
{
inode_semtake();
inode->i_crefs++;
inode_semgive();
}
}
+93
View File
@@ -0,0 +1,93 @@
/****************************************************************************
* fs/inode/fs_inodefind.c
*
* Copyright (C) 2007-2009, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <vfs_config.h>
#include <errno.h>
#include <fs/fs.h>
#include "inode/inode.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: inode_find
*
* Description:
* This is called from the open() logic to get a reference to the inode
* associated with a path. This is accomplished by calling inode_search().
* inode_find() is a simple wrapper around inode_search(). The primary
* difference between inode_find() and inode_search is that inode_find()
* will lock the inode tree and increment the reference count on the inode.
*
****************************************************************************/
int inode_find(FAR struct inode_search_s *desc)
{
int ret;
FAR const char *path = desc->path;
FAR const char **relpath = &(desc->relpath);
FAR struct inode **peer = &(desc->peer);
FAR struct inode **parent = &(desc->parent);
/* Find the node matching the path. If found, increment the count of
* references on the node.
*/
inode_semtake();
desc->node = inode_search(&path, peer, parent, relpath);
if (desc->node != NULL)
{
/* Found it */
FAR struct inode *node = desc->node;
/* Increment the reference count on the inode */
node->i_crefs++;
ret = 0;
}
else
{
ret = -1;
}
inode_semgive();
return ret;
}
+91
View File
@@ -0,0 +1,91 @@
/****************************************************************************
* fs/inode/fs_inoderelease.c
*
* Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "errno.h"
#include "stdlib.h"
#include "fs/fs.h"
#include "inode/inode.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: inode_release
*
* Description:
* This is called from close() logic when it no longer refers to the inode.
*
****************************************************************************/
void inode_release(FAR struct inode *node)
{
if (node)
{
/* Decrement the references of the inode */
inode_semtake();
if (node->i_crefs)
{
node->i_crefs--;
}
/* If the subtree was previously deleted and the reference
* count has decrement to zero, then delete the inode
* now.
*/
if (node->i_crefs <= 0 && (node->i_flags & FSNODEFLAG_DELETED) != 0)
{
/* If the inode has been properly unlinked, then the peer pointer
* should be NULL.
*/
inode_free(node->i_child);
(void)LOS_MemFree(m_aucSysMem0, node);
inode_semgive();
}
else
{
inode_semgive();
}
}
}
+169
View File
@@ -0,0 +1,169 @@
/****************************************************************************
* fs/inode/fs_inoderemove.c
*
* Copyright (C) 2007-2009, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "errno.h"
#include "stdlib.h"
#include "fs/fs.h"
#include "inode/inode.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: inode_unlink
*
* Description:
* Given a path, remove a the node from the in-memory, inode tree that the
* path refers to. This is normally done in preparation to removing or
* moving an inode.
*
* In symbolic links in the pseduo file system are enabled, then this
* logic will follow the symbolic links up until the terminal node. Then
* that link in removed. So if this the terminal node is a symbolic link,
* the symbolic link node will be removed, not the target of the link.
*
* Assumptions/Limitations:
* The caller must hold the inode semaphore
*
****************************************************************************/
FAR struct inode *inode_unlink(FAR const char *path)
{
const char *name = path;
FAR struct inode *node;
FAR struct inode *peer;
FAR struct inode *parent;
/* Verify parameters. Ignore null paths and relative paths */
if (path == NULL || *path == '\0' || path[0] != '/')
{
return NULL;
}
/* Find the node to unlink */
node = inode_search(&name, &peer, &parent, (const char **)NULL);
if (node)
{
/* If peer is non-null, then remove the node from the right of
* of that peer node.
*/
if (peer)
{
peer->i_peer = node->i_peer;
}
/* If parent is non-null, then remove the node from head of
* of the list of children.
*/
else if (parent)
{
parent->i_child = node->i_peer;
}
/* Otherwise, we must be removing the root inode. */
else
{
g_root_inode = node->i_peer;
}
node->i_peer = NULL;
}
return node;
}
/****************************************************************************
* Name: inode_remove
*
* Description:
* Given a path, remove a the node from the in-memory, inode tree that the
* path refers to and free all resources related to the inode. If the
* inode is in-use, then it will be unlinked, but will not be freed until
* the last reference to the inode is released.
*
* Assumptions/Limitations:
* The caller must hold the inode semaphore
*
****************************************************************************/
int inode_remove(FAR const char *path)
{
FAR struct inode *node;
/* Find the inode and unlink it from the in-memory inode tree */
node = inode_unlink(path);
if (node)
{
/* Found it! But we cannot delete the inode if there are references
* to it
*/
if (node->i_crefs)
{
/* In that case, we will mark it deleted, when the filesystem
* releases the inode, we will then, finally delete the subtree
*/
node->i_flags |= FSNODEFLAG_DELETED;
return -EBUSY;
}
else
{
/* And delete it now -- recursively to delete all of its children.
* Since it has been unlinked, then the peer pointer should be NULL.
*/
inode_free(node->i_child);
(void)LOS_MemFree(m_aucSysMem0, node);
return OK;
}
}
/* The node does not exist */
return -ENOENT;
}
+320
View File
@@ -0,0 +1,320 @@
/****************************************************************************
* fs/inode/fs_registerreserve.c
*
* Copyright (C) 2007-2009, 2011-2012, 2015, 2017 Gregory Nutt. All
* rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "assert.h"
#include "errno.h"
#include "stdlib.h"
#include "fs/fs.h"
#include "fs/dirent_fs.h"
#include "string.h"
#include "inode/inode.h"
#include "capability_api.h"
#include "fs_other.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: check_name
****************************************************************************/
static bool check_name(FAR const char *name)
{
while (*name != '\0')
{
if ((*name == '/') && *(name+1) != '\0')
{
return false;
}
name ++;
}
return true;
}
/****************************************************************************
* Name: inode_namelen
****************************************************************************/
static int inode_namelen(FAR const char *name)
{
const char *tmp = name;
while (*tmp && *tmp != '/')
{
tmp++;
}
return tmp - name;
}
/****************************************************************************
* Name: inode_namecpy
****************************************************************************/
static void inode_namecpy(char *dest, const char *src)
{
while (*src && *src != '/')
{
*dest++ = *src++;
}
*dest = '\0';
}
/****************************************************************************
* Name: inode_alloc
****************************************************************************/
static FAR struct inode *inode_alloc(FAR const char *name)
{
FAR struct inode *node;
int namelen;
namelen = inode_namelen(name);
node = (FAR struct inode*)LOS_MemAlloc(m_aucSysMem0, FSNODE_SIZE(namelen));
if (node)
{
(void)memset_s(node, FSNODE_SIZE(namelen), 0, FSNODE_SIZE(namelen));
inode_namecpy(node->i_name, name);
}
return node;
}
/****************************************************************************
* Name: IsInRootfs
****************************************************************************/
bool IsInRootfs(const char *relpath)
{
bool ret = true;
char *name = NULL;
char *path = NULL;
struct stat statInfo;
if ((!g_root_inode->u.i_mops) || (!g_root_inode->u.i_mops->stat)) {
return false;
}
name = strdup(relpath);
if (name) {
path = strsep(&name, "/");
if (g_root_inode->u.i_mops->stat(g_root_inode, path, &statInfo) == -ENOENT) {
ret = false;
}
free(path);
}
return ret;
}
/****************************************************************************
* Name: inode_insert
****************************************************************************/
static void inode_insert(FAR struct inode *node,
FAR struct inode *peer,
FAR struct inode *parent)
{
/* If peer is non-null, then new node simply goes to the right
* of that peer node.
*/
if (peer)
{
node->i_peer = peer->i_peer;
peer->i_peer = node;
}
/* If parent is non-null, then it must go at the head of its
* list of children.
*/
else if (parent)
{
node->i_peer = parent->i_child;
parent->i_child = node;
}
/* Otherwise, this must be the new root_inode */
else
{
node->i_peer = g_root_inode;
g_root_inode = node;
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: inode_reserve
*
* Description:
* Reserve an (initialized) inode the pseudo file system. The initial
* reference count on the new inode is zero.
*
* Input Parameters:
* path - The path to the inode to create
* inode - The location to return the inode pointer
*
* Returned Value:
* Zero on success (with the inode point in 'inode'); A negated errno
* value is returned on failure:
*
* EINVAL - 'path' is invalid for this operation
* EEXIST - An inode already exists at 'path'
* ENOMEM - Failed to allocate in-memory resources for the operation
*
* Assumptions:
* Caller must hold the inode semaphore
*
****************************************************************************/
int inode_reserve(FAR const char *path, FAR struct inode **inode_ptr)
{
FAR const char *name = path;
FAR const char *relpath;
FAR struct inode *pathnode;
FAR struct inode *left;
FAR struct inode *parent;
/* Assume failure */
DEBUGASSERT(path && inode_ptr);
*inode_ptr = NULL;
/* Handle paths that are interpreted as the root directory */
if (!*path || path[0] != '/')
{
return -EINVAL;
}
/* Find the location to insert the new subtree */
pathnode = inode_search(&name, &left, &parent, &relpath);
if (pathnode)
{
if (!*(relpath))
{
/* It is an error if the node already exists in the tree */
return -EEXIST;
}
#ifndef CONFIG_DISABLE_MOUNTPOINT
else if (INODE_IS_MOUNTPT(pathnode))
{
if ((pathnode != g_root_inode) || IsInRootfs(relpath))
{
/* The node cannot be a child of a mounted point, except the root node. */
return -EINVAL;
}
}
#endif
}
else
{
/* not find pathnode and the node is not g_root_inode express you have no access authority */
if (g_root_inode != NULL)
{
return -EACCES;
}
}
if (check_name(name) == false)
{
/* check the path has no '/' symbol, prevent to create multilevel directory */
return -EINVAL;
}
/* Now we now where to insert the subtree */
for (; ; )
{
FAR struct inode *node;
/* Create a new node -- we need to know if this is the
* the leaf node or some intermediary. We can find this
* by looking at the next name.
*/
FAR const char *next_name = inode_nextname(name);
if (*next_name)
{
/* Insert an operationless node */
node = inode_alloc(name);
if (node)
{
inode_insert(node, left, parent);
/* Set up for the next time through the loop */
name = next_name;
left = NULL;
parent = node;
continue;
}
}
else
{
node = inode_alloc(name);
if (node)
{
inode_insert(node, left, parent);
*inode_ptr = node;
return OK;
}
}
/* We get here on failures to allocate node memory */
return -ENOMEM;
}
}
+338
View File
@@ -0,0 +1,338 @@
/****************************************************************************
* fs/inode/fs_inodesearch.c
*
* Copyright (C) 2007-2009, 2011-2012, 2016-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "assert.h"
#include "errno.h"
#include "semaphore.h"
#include "stdlib.h"
#include "fs/fs.h"
#include "fs_other.h"
#include "inode/inode.h"
/****************************************************************************
* Public Data
****************************************************************************/
FAR struct inode *g_root_inode = NULL;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: _inode_compare
*
* Description:
* Compare two inode names
*
****************************************************************************/
static int _inode_compare(FAR const char *fname, FAR struct inode *node)
{
char *nname = node->i_name;
if (!nname)
{
return 1;
}
if (!fname)
{
return -1;
}
for (; ; )
{
/* At the end of the node name? */
if (!*nname)
{
/* Yes.. also at the end of find name? */
if (!*fname || *fname == '/')
{
/* Yes.. return match */
return 0;
}
else
{
/* No... return find name > node name */
return 1;
}
}
/* At end of the find name? */
else if (!*fname || *fname == '/')
{
/* Yes... return find name < node name */
return -1;
}
/* Check for non-matching characters */
else if (*fname > *nname)
{
return 1;
}
else if (*fname < *nname)
{
return -1;
}
/* Not at the end of either string and all of the
* characters still match. keep looking.
*/
else
{
fname++;
nname++;
}
}
}
/****************************************************************************
* Name: inode_search
*
* Description:
* Find the inode associated with 'path' returning the inode references
* and references to its companion nodes.
*
* Assumptions:
* The caller holds the g_inode_sem semaphore
*
* TODO: Nuttx 8.2 inode_search() uses struct inode_search_s as parameter
****************************************************************************/
FAR struct inode *inode_search(FAR const char **path,
FAR struct inode **peer,
FAR struct inode **parent,
FAR const char **relpath)
{
FAR const char *name = *path;
FAR struct inode *ret_inode = NULL;
FAR struct inode *node = g_root_inode;
FAR struct inode *left = NULL;
FAR struct inode *above = NULL;
while (node)
{
int result = _inode_compare(name, node);
/* Case 1: The name is less than the name of the node.
* Since the names are ordered, these means that there
* is no peer node with this name and that there can be
* no match in the fileystem.
*/
if (result < 0)
{
node = NULL;
break;
}
/* Case 2: the name is greater than the name of the node.
* In this case, the name may still be in the list to the
* "right"
*/
else if (result > 0)
{
left = node;
node = node->i_peer;
}
/* The names match */
else
{
/* Now there are three more possibilities:
* (1) This is the node that we are looking for or,
* (2) The node we are looking for is "below" this one.
* (3) This node is a mountpoint and will absorb all request
* below this one
*/
name = inode_nextname(name);
if (!INODE_IS_MOUNTPT(g_root_inode))
{
/* This g_root_inode is not a mountpoint and will handle the
* remaining part of the pathname
*/
if (relpath != NULL)
{
ret_inode = node;
*relpath = name;
}
}
if (INODE_IS_MOUNTPT(node))
{
/* This node is a mountpoint and will handle the
* remaining part of the pathname
*/
if (relpath != NULL)
{
ret_inode = node;
*relpath = name;
}
}
if (!*name)
{
/* We are at the end of the path, so this must be the
* node we are looking for
*/
ret_inode = node;
if (relpath != NULL)
{
*relpath = name;
}
break;
}
else
{
/* More to go, keep looking at the next level "down" */
above = node;
left = NULL;
if ((g_root_inode != NULL) && VfsPermissionCheck(node->i_uid, node->i_gid, node->i_mode, EXEC_OP))
{
/* If g_root_inode has set and node has not execution authority, while break */
ret_inode = NULL;
node = NULL;
break;
}
node = node->i_child;
}
}
}
/* The node may or may not be null as per one of the following four cases
* cases:
*
* With node = NULL
*
* (1) We went left past the final peer: The new node name is larger
* than any existing node name at that level.
* (2) We broke out in the middle of the list of peers because the name
* was not found in the ordered list.
* (3) We went down past the final parent: The new node name is
* "deeper" than anything that we currently have in the tree.
*
* With node != NULL
*
* (4) When the node matching the full path is found
*/
if (peer != NULL)
{
*peer = left;
}
if (parent != NULL)
{
*parent = above;
}
*path = name;
return ret_inode;
}
/****************************************************************************
* Name: inode_free
*
* Description:
* Free resources used by an inode
*
****************************************************************************/
void inode_free(FAR struct inode *node)
{
if (node != NULL)
{
inode_free(node->i_peer);
inode_free(node->i_child);
(VOID)LOS_MemFree(m_aucSysMem0, node);
}
}
/****************************************************************************
* Name: inode_nextname
*
* Description:
* Given a path with node names separated by '/', return the next path
* segment name.
*
****************************************************************************/
FAR const char *inode_nextname(FAR const char *name)
{
/* Search for the '/' delimiter or the NUL terminator at the end of the
* path segment.
*/
while (*name != '\0' && *name != '/')
{
name++;
}
/* If we found the '/' delimiter, then the path segment we want begins at
* the next character (which might also be the NUL terminator).
*/
while (*name == '/')
{
name++;
}
return name;
}
+482
View File
@@ -0,0 +1,482 @@
/****************************************************************************
* fs/inode/inode.h
*
* Copyright (C) 2007, 2009, 2012, 2014, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __FS_INODE_H
#define __FS_INODE_H
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "sys/types.h"
#include "dirent.h"
#include "limits.h"
#include "fs/fs.h"
#include "fs/file.h"
#include "fs/fs_operation.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define DEV_PATH_LEN 5
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Inode i_flag values */
#define FSNODEFLAG_TYPE_MASK 0x00000007 /* Isolates type field */
#define FSNODEFLAG_TYPE_DRIVER 0x00000000 /* Character driver */
#define FSNODEFLAG_TYPE_BLOCK 0x00000001 /* Block driver */
#define FSNODEFLAG_TYPE_MOUNTPT 0x00000002 /* Mount point */
#define FSNODEFLAG_TYPE_SPECIAL 0x00000004 /* Special OS type */
#define FSNODEFLAG_TYPE_NAMEDSEM 0x00000004 /* Named semaphore */
#define FSNODEFLAG_TYPE_MQUEUE 0x00000005 /* Message Queue */
#define FSNODEFLAG_TYPE_SHM 0x00000006 /* Shared memory region */
#define FSNODEFLAG_DELETED 0x00000008 /* Unlinked */
#define INODE_IS_TYPE(i,t) \
(((i)->i_flags & FSNODEFLAG_TYPE_MASK) == (t))
#define INODE_IS_SPECIAL(i) \
(((i)->i_flags & FSNODEFLAG_TYPE_SPECIAL) != 0)
#define INODE_IS_DRIVER(i) INODE_IS_TYPE(i,FSNODEFLAG_TYPE_DRIVER)
#define INODE_IS_BLOCK(i) INODE_IS_TYPE(i,FSNODEFLAG_TYPE_BLOCK)
#define INODE_IS_MOUNTPT(i) INODE_IS_TYPE(i,FSNODEFLAG_TYPE_MOUNTPT)
#define INODE_IS_NAMEDSEM(i) INODE_IS_TYPE(i,FSNODEFLAG_TYPE_NAMEDSEM)
#define INODE_IS_MQUEUE(i) INODE_IS_TYPE(i,FSNODEFLAG_TYPE_MQUEUE)
#define INODE_IS_SHM(i) INODE_IS_TYPE(i,FSNODEFLAG_TYPE_SHM)
#define INODE_GET_TYPE(i) ((i)->i_flags & FSNODEFLAG_TYPE_MASK)
#define INODE_SET_TYPE(i,t) \
do \
{ \
(i)->i_flags = ((i)->i_flags & ~FSNODEFLAG_TYPE_MASK) | (t); \
} \
while (0)
#define INODE_SET_DRIVER(i) INODE_SET_TYPE(i,FSNODEFLAG_TYPE_DRIVER)
#define INODE_SET_BLOCK(i) INODE_SET_TYPE(i,FSNODEFLAG_TYPE_BLOCK)
#define INODE_SET_MOUNTPT(i) INODE_SET_TYPE(i,FSNODEFLAG_TYPE_MOUNTPT)
#define INODE_SET_NAMEDSEM(i) INODE_SET_TYPE(i,FSNODEFLAG_TYPE_NAMEDSEM)
#define INODE_SET_MQUEUE(i) INODE_SET_TYPE(i,FSNODEFLAG_TYPE_MQUEUE)
#define INODE_SET_SHM(i) INODE_SET_TYPE(i,FSNODEFLAG_TYPE_SHM)
/* Mountpoint fd_flags values */
#define DIRENTFLAGS_PSEUDONODE 1
#define DIRENT_SETPSEUDONODE(f) do (f) |= DIRENTFLAGS_PSEUDONODE; while (0)
#define DIRENT_ISPSEUDONODE(f) (((f) & DIRENTFLAGS_PSEUDONODE) != 0)
#ifdef CONFIG_PSEUDOFS_SOFTLINKS
# define SETUP_SEARCH(d,p,n) \
do \
{ \
(d)->path = (p); \
(d)->node = NULL; \
(d)->peer = NULL; \
(d)->parent = NULL; \
(d)->relpath = NULL; \
(d)->linktgt = NULL; \
(d)->buffer = NULL; \
(d)->nofollow = (n); \
} \
while (0)
# define RELEASE_SEARCH(d) \
if ((d)->buffer != NULL) \
{ \
kmm_free((d)->buffer); \
(d)->buffer = NULL; \
}
#else
# define SETUP_SEARCH(d,p,n) \
do \
{ \
(d)->path = (p); \
(d)->node = NULL; \
(d)->peer = NULL; \
(d)->parent = NULL; \
(d)->relpath = NULL; \
} \
while (0)
# define RELEASE_SEARCH(d)
#endif
/****************************************************************************
* Public Types
****************************************************************************/
/* This is the type of the argument to inode_search().
*
* path - INPUT: Path of inode to find
* OUTPUT: Residual part of path not traversed
* node - INPUT: (not used)
* OUTPUT: On success, holds the pointer to the inode found.
* peer - INPUT: (not used)
* OUTPUT: The inode to the "left" of the inode found.
* parent - INPUT: (not used)
* OUTPUT: The inode to the "above" of the inode found.
* relpath - INPUT: (not used)
* OUTPUT: If the returned inode is a mountpoint, this is the
* relative path from the mountpoint.
* linktgt - INPUT: (not used)
* OUTPUT: If a symobolic link into a mounted file system is
* detected while traversing the path, then the link
* will be converted to a mountpoint inode if the
* mountpoint link is in an intermediate node of the
* path or at the final node of the path with nofollow=true.
* nofollow - INPUT: true: terminal node is returned; false: if the
* terminal is a soft link, then return the inode of
* the link target.
* - OUTPUT: (not used)
* buffer - INPUT: Not used
* - OUTPUT: May hold an allocated intermediate path which is
* probably of no interest to the caller unless it holds
* the relpath.
*/
struct inode_search_s
{
FAR const char *path; /* Path of inode to find */
FAR struct inode *node; /* Pointer to the inode found */
FAR struct inode *peer; /* Node to the "left" for the found inode */
FAR struct inode *parent; /* Node "above" the found inode */
FAR const char *relpath; /* Relative path into the mountpoint */
#ifdef CONFIG_PSEUDOFS_SOFTLINKS
FAR const char *linktgt; /* Target of symbolic link if linked to a directory */
FAR char *buffer; /* Path expansion buffer */
bool nofollow; /* true: Don't follow terminal soft link */
#endif
};
/* Callback used by foreach_inode to traverse all inodes in the pseudo-
* file system.
*/
typedef int (*foreach_inode_t)(FAR struct inode *node,
FAR char dirpath[PATH_MAX],
FAR void *arg);
/****************************************************************************
* Public Data
****************************************************************************/
extern FAR struct inode *g_root_inode;
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: inode_initialize
*
* Description:
* This is called from the OS initialization logic to configure the file
* system.
*
****************************************************************************/
void inode_initialize(void);
/****************************************************************************
* Name: inode_semtake
*
* Description:
* Get exclusive access to the in-memory inode tree (tree_sem).
*
****************************************************************************/
void inode_semtake(void);
/****************************************************************************
* Name: inode_semgive
*
* Description:
* Relinquish exclusive access to the in-memory inode tree (tree_sem).
*
****************************************************************************/
void inode_semgive(void);
/****************************************************************************
* Name: inode_search
*
* Description:
* Find the inode associated with 'path' returning the inode references
* and references to its companion nodes.
*
* If a mountpoint is encountered in the search prior to encountering the
* terminal node, the search will terminate at the mountpoint inode. That
* inode and the relative path from the mountpoint, 'relpath' will be
* returned.
*
* inode_search will follow soft links in path leading up to the terminal
* node. Whether or no inode_search() will deference that terminal node
* depends on the 'nofollow' input.
*
* If a soft link is encountered that is not the terminal node in the path,
* that link WILL be deferenced unconditionally.
*
* Assumptions:
* The caller holds the g_inode_sem semaphore
*
****************************************************************************/
FAR struct inode *inode_search(FAR const char **path,
FAR struct inode **peer,
FAR struct inode **parent,
FAR const char **relpath);
/****************************************************************************
* Name: inode_find
*
* Description:
* This is called from the open() logic to get a reference to the inode
* associated with a path. This is accomplished by calling inode_search().
* inode_find() is a simple wrapper around inode_search(). The primary
* difference between inode_find() and inode_search is that inode_find()
* will lock the inode tree and increment the reference count on the inode.
*
****************************************************************************/
int inode_find(FAR struct inode_search_s *desc);
/****************************************************************************
* Name: inode_stat
*
* Description:
* The inode_stat() function will obtain information about an 'inode' in
* the pseudo file system 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:
* inode - The indoe of interest
* buf - The caller provide location in which to return information about
* the inode.
*
* Returned Value:
* Zero (OK) returned on success. Otherwise, a negated errno value is
* returned to indicate the nature of the failure.
*
****************************************************************************/
struct stat; /* Forward reference */
int inode_stat(FAR struct inode *inode, FAR struct stat *buf);
/****************************************************************************
* Name: inode_free
*
* Description:
* Free resources used by an inode
*
****************************************************************************/
void inode_free(FAR struct inode *node);
/****************************************************************************
* Name: inode_nextname
*
* Description:
* Given a path with node names separated by '/', return the next node
* name.
*
****************************************************************************/
const char *inode_nextname(FAR const char *name);
bool IsInRootfs(const char *relpath);
/****************************************************************************
* Name: inode_reserve
*
* Description:
* Reserve an (initialized) inode the pseudo file system.
*
* NOTE: Caller must hold the inode semaphore
*
* Input Parameters:
* path - The path to the inode to create
* inode - The location to return the inode pointer
*
* Returned Value:
* Zero on success (with the inode point in 'inode'); A negated errno
* value is returned on failure:
*
* EINVAL - 'path' is invalid for this operation
* EEXIST - An inode already exists at 'path'
* ENOMEM - Failed to allocate in-memory resources for the operation
*
****************************************************************************/
int inode_reserve(FAR const char *path, FAR struct inode **inode);
/****************************************************************************
* Name: inode_unlink
*
* Description:
* Given a path, remove a the node from the in-memory, inode tree that the
* path refers to. This is normally done in preparation to removing or
* moving an inode.
*
* Assumptions/Limitations:
* The caller must hold the inode semaphore
*
****************************************************************************/
FAR struct inode *inode_unlink(FAR const char *path);
/****************************************************************************
* Name: inode_remove
*
* Description:
* Given a path, remove a the node from the in-memory, inode tree that the
* path refers to and free all resources related to the inode. If the
* inode is in-use, then it will be unlinked, but will not be freed until
* the last reference to the inode is released.
*
* Assumptions/Limitations:
* The caller must hold the inode semaphore
*
****************************************************************************/
int inode_remove(FAR const char *path);
/****************************************************************************
* Name: inode_addref
*
* Description:
* Increment the reference count on an inode (as when a file descriptor
* is dup'ed).
*
****************************************************************************/
void inode_addref(FAR struct inode *inode);
/****************************************************************************
* Name: inode_release
*
* Description:
* This is called from close() logic when it no longer refers to the inode.
*
****************************************************************************/
void inode_release(FAR struct inode *inode);
/****************************************************************************
* Name: foreach_inode
*
* Description:
* Visit each inode in the pseudo-file system. The traversal is terminated
* when the callback 'handler' returns a non-zero value, or when all of
* the inodes have been visited.
*
* NOTE 1: Use with caution... The pseudo-file system is locked throughout
* the traversal.
* NOTE 2: The search algorithm is recursive and could, in principle, use
* an indeterminant amount of stack space. This will not usually be a
* real work issue.
*
****************************************************************************/
int foreach_inode(foreach_inode_t handler, FAR void *arg);
/****************************************************************************
* Name: files_initialize
*
* Description:
* This is called from the FS initialization logic to configure the files.
*
****************************************************************************/
void weak_function files_initialize(void);
/****************************************************************************
* Name: files_allocate
*
* Description:
* Allocate a struct files instance and associate it with an inode instance.
* Returns the file descriptor == index into the files array.
*
****************************************************************************/
int files_allocate(FAR struct inode *inode, int oflags, off_t pos,void *priv, int minfd);
/****************************************************************************
* Name: files_close
*
* Description:
* Close an inode (if open)
*
* Assumuptions:
* Caller holds the list semaphore because the file descriptor will be freed.
*
****************************************************************************/
int files_close(int fd);
/****************************************************************************
* Name: files_release
*
* Assumuptions:
* Similar to files_close(). Called only from open() logic on error
* conditions.
*
****************************************************************************/
void files_release(int fd);
int vfs_normalize_path(const char *directory, const char *filename, char **pathname);
int vfs_normalize_pathat(int fd, const char *filename, char **pathname);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __FS_INODE_H */
+173
View File
@@ -0,0 +1,173 @@
/****************************************************************************
* fs/mount/fs_foreachmountpoint.c
*
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "sys/statfs.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "assert.h"
#include "errno.h"
#include "fs/fs.h"
#include "inode/inode.h"
#ifndef CONFIG_DISABLE_MOUNTPOINT
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/* This structure just remembers the final consumer of the mountpoint
* information (and its argument).
*/
struct enum_mountpoint_s
{
foreach_mountpoint_t handler;
FAR void *arg;
};
/****************************************************************************
* Private Functions
****************************************************************************/
static int mountpoint_filter(FAR struct inode *node,
FAR char dirpath[PATH_MAX], FAR void *arg)
{
FAR struct enum_mountpoint_s *info = (FAR struct enum_mountpoint_s *)arg;
struct statfs statbuf;
int pathlen;
int namlen;
int ret = OK;
DEBUGASSERT(node && info && info->handler);
/* Check if the inode is a mountpoint. Mountpoints must support statfs.
* If this one does not for some reason, then it will be ignored.
*
* The root node is a special case: It has no operations (u.i_mops == NULL)
*/
if (INODE_IS_MOUNTPT(node) && node->u.i_mops && node->u.i_mops->statfs)
{
/* Yes... get the full path to the inode by concatenating the inode
* name and the path to the directory containing the inode.
*/
pathlen = strlen(dirpath);
namlen = strlen(node->i_name) + 1;
/* Make sure that this would not exceed the maximum path length */
if (pathlen + namlen >= PATH_MAX)
{
return -ENAMETOOLONG;
}
/* Append the inode name to the directory path */
ret = snprintf_s(&dirpath[pathlen], PATH_MAX - pathlen, PATH_MAX - pathlen - 1, "/%s", node->i_name);
if (ret < 0)
{
return -ENAMETOOLONG;
}
/* Get the status of the file system */
ret = node->u.i_mops->statfs(node, &statbuf);
if (ret == OK)
{
/* And pass the full path and file system status to the handler */
ret = info->handler(dirpath, &statbuf, info->arg);
}
/* Truncate the path name back to the correct length */
dirpath[pathlen] = '\0';
}
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: foreach_mountpoint
*
* Description:
* Visit each mountpoint in the pseudo-file system. The traversal is
* terminated when the callback 'handler' returns a non-zero value, or when
* all of the mountpoints have been visited.
*
* This is just a front end "filter" to foreach_inode() that forwards only
* mountpoint inodes. It is intended to support the mount() command to
* when the mount command is used to enumerate mounts.
*
* NOTE 1: Use with caution... The pseudo-file system is locked throughout
* the traversal.
* NOTE 2: The search algorithm is recursive and could, in principle, use
* an indeterminant amount of stack space. This will not usually be a
* real work issue.
*
****************************************************************************/
int foreach_mountpoint(foreach_mountpoint_t handler, FAR void *arg)
{
struct enum_mountpoint_s info;
/* Let foreach_inode do the real work */
info.handler = handler;
info.arg = arg;
return foreach_inode(mountpoint_filter, (FAR void *)&info);
}
#endif
+392
View File
@@ -0,0 +1,392 @@
/****************************************************************************
* fs/mount/fs_mount.c
*
* Copyright (C) 2007-2009, 2011-2013, 2015, 2017-2019 Gregory Nutt. All
* rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "sys/mount.h"
#include "string.h"
#include "errno.h"
#include "assert.h"
#include "debug.h"
#include "fs/fs.h"
#include "inode/inode.h"
#include "stdlib.h"
#include "driver/driver.h"
#if defined(LOSCFG_FS_JFFS)
#include "mtd_partition.h"
#endif
#ifdef LOSCFG_FS_FAT_VIRTUAL_PARTITION
#include "errcode_fat.h"
#endif
#include "los_tables.h"
/* At least one filesystem must be defined, or this file will not compile.
* It may be desire-able to make filesystems dynamically registered at
* some time in the future, but at present, this file needs to know about
* every configured filesystem.
*/
#ifdef CONFIG_FS_READABLE
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Configuration ************************************************************/
/* In the canonical case, a file system is bound to a block driver. However,
* some less typical cases a block driver is not required. Examples are
* pseudo file systems (like BINFS or PROCFS) and MTD file systems (like NXFFS).
*
* These file systems all require block drivers:
*/
#define BLKDRVR_NOT_MOUNTED 2
extern struct fsmap_t g_fsmap[];
LOS_HAL_TABLE_BEGIN(g_fsmap, fsmap);
extern struct fsmap_t g_fsmap_end;
LOS_HAL_TABLE_END(g_fsmap_end, fsmap);
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: mount_findfs
*
* Description:
* find the specified filesystem
*
****************************************************************************/
static const struct fsmap_t *mount_findfs(const char *filesystemtype)
{
struct fsmap_t *m = NULL;
for (m = &g_fsmap[0]; m != &g_fsmap_end; ++m)
{
if (m->fs_filesystemtype &&
strcmp(filesystemtype, m->fs_filesystemtype) == 0)
{
return m;
}
}
return (const struct fsmap_t *)NULL;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: mount
*
* Description:
* mount() attaches the filesystem specified by the 'source' block device
* name into the root file system at the path specified by 'target.'
*
* Return:
* Zero is returned on success; -1 is returned on an error and errno is
* set appropriately:
*
* EACCES A component of a path was not searchable or mounting a read-only
* filesystem was attempted without giving the MS_RDONLY flag.
* EBUSY 'source' is already mounted.
* EFAULT One of the pointer arguments points outside the user address
* space.
* EINVAL 'source' had an invalid superblock.
* ENODEV 'filesystemtype' not configured
* ENOENT A pathname was empty or had a nonexistent component.
* ENOMEM Could not allocate a memory to copy filenames or data into.
* ENOTBLK 'source' is not a block device
*
****************************************************************************/
int mount(const char *source, const char *target,
const char *filesystemtype, unsigned long mountflags,
const void *data)
{
int ret;
void *fshandle = NULL;
int errcode = 0;
char *fullpath = NULL;
char *fullpath_bak = NULL;
struct inode *blkdrvr_inode = NULL;
struct inode *mountpt_inode = NULL;
const struct fsmap_t *fsmap = NULL;
const struct mountpt_operations *mops = NULL;
#if defined(LOSCFG_FS_JFFS)
mtd_partition *partition = NULL;
#endif
if (filesystemtype == NULL)
{
errcode = EINVAL;
goto errout;
}
/* Verify required pointer arguments */
DEBUGASSERT(target && filesystemtype);
ret = vfs_normalize_path((const char *)NULL, target, &fullpath);
if (ret < 0)
{
PRINT_ERR("Failed to get fullpath,target: %s\n", target);
errcode = -ret;
goto errout;
}
fullpath_bak = fullpath;
/* Find the specified filesystem. Try the block driver file systems first */
if ((fsmap = mount_findfs(filesystemtype)) == NULL ||
(fsmap->is_bdfs && !source))
{
PRINT_ERR("Failed to find file system %s\n", filesystemtype);
errcode = ENODEV;
free(fullpath_bak);
goto errout;
}
mops = fsmap->fs_mops;
if (fsmap->is_bdfs && source)
{
/* Make sure that a block driver argument was provided */
DEBUGASSERT(source);
/* Find the block driver */
ret = find_blockdriver(source, mountflags, &blkdrvr_inode);
if (ret < 0)
{
PRINT_ERR("Failed to find block driver %s\n", source);
errcode = -ret;
free(fullpath_bak);
goto errout;
}
}
/* Insert a dummy node -- we need to hold the inode semaphore
* to do this because we will have a momentarily bad structure.
*/
inode_semtake();
mountpt_inode = inode_search((const char **)&fullpath, (struct inode **)NULL, (struct inode **)NULL, \
(const char **)NULL);
/* The mount point must be an existed inode. */
if (mountpt_inode == NULL)
{
PRINT_ERR("Failed to find valid mountpoint %s\n", target);
errcode = EINVAL;
goto errout_with_semaphore;
}
/* The mount point must be a dangling node with no children and
* no operations. If this inode is mounted, or it has children
* (except "/"), or it has operations, it cannot be mounted.
*/
if (INODE_IS_MOUNTPT(mountpt_inode) || (mountpt_inode->i_child && strcmp(target, "/")) || mountpt_inode->u.i_ops)
{
PRINT_ERR("Can't to mount to this inode %s\n", target);
errcode = EINVAL;
goto errout_with_semaphore;
}
mountpt_inode ->mountflags = mountflags;
/* Bind the block driver to an instance of the file system. The file
* system returns a reference to some opaque, fs-dependent structure
* that encapsulates this binding.
*/
if (mops->bind == NULL)
{
/* The filesystem does not support the bind operation ??? */
fdbg("ERROR: Filesystem does not support bind\n");
errcode = EINVAL;
goto errout_with_mountpt;
}
/* Increment reference count for the reference we pass to the file system */
if (blkdrvr_inode != NULL)
{
blkdrvr_inode->i_crefs++;
/* On failure, the bind method returns -errorcode */
if (blkdrvr_inode->e_status != STAT_UNMOUNTED)
{
fdbg("ERROR: The node is busy\n");
errcode = EBUSY;
blkdrvr_inode->i_crefs--;
goto errout_with_mountpt;
}
}
#if defined(LOSCFG_FS_JFFS)
if (fsmap->is_mtd_support && (blkdrvr_inode != NULL))
{
partition = (mtd_partition *)blkdrvr_inode->i_private;
partition->mountpoint_name = (char *)zalloc(strlen(target) + 1);
if (partition->mountpoint_name == NULL)
{
errcode = ENOMEM;
blkdrvr_inode->i_crefs--;
goto errout_with_mountpt;
}
(void)strncpy_s(partition->mountpoint_name, strlen(target) + 1, target, strlen(target));
partition->mountpoint_name[strlen(target)] = '\0';
}
#endif
mountpt_inode ->mountflags = mountflags;
ret = mops->bind(blkdrvr_inode, data, &fshandle, fullpath_bak);
#ifdef LOSCFG_FS_FAT_VIRTUAL_PARTITION
if (ret >= VIRERR_BASE)
{
errcode = ret;
}
else
#endif
if (ret != 0)
{
/* The inode is unhappy with the blkdrvr for some reason. Back out
* the count for the reference we failed to pass and exit with an
* error.
*/
fdbg("ERROR: Bind method failed: %d\n", ret);
if (blkdrvr_inode != NULL)
{
blkdrvr_inode->i_crefs--;
}
errcode = -ret;
#if defined(LOSCFG_FS_JFFS)
if (fsmap->is_mtd_support && (blkdrvr_inode != NULL) && (partition != NULL))
{
free(partition->mountpoint_name);
partition->mountpoint_name = NULL;
}
#endif
goto errout_with_mountpt;
}
/* We have it, now populate it with driver specific information. */
INODE_SET_MOUNTPT(mountpt_inode);
mountpt_inode->u.i_mops = mops;
mountpt_inode->i_private = fshandle;
#ifdef LOSCFG_FILE_MODE
struct stat statinfo = {0};
if ((g_root_inode != mountpt_inode) && (stat(target, &statinfo) == 0))
{
mountpt_inode->i_mode = statinfo.st_mode;
mountpt_inode->i_uid = statinfo.st_uid;
mountpt_inode->i_gid = statinfo.st_gid;
}
#endif
if (blkdrvr_inode)
{
blkdrvr_inode->e_status = STAT_MOUNTED;
}
inode_semgive();
/* We can release our reference to the blkdrver_inode, if the filesystem
* wants to retain the blockdriver inode (which it should), then it must
* have called inode_addref(). There is one reference on mountpt_inode
* that will persist until umount() is called.
*/
if (blkdrvr_inode != NULL)
{
inode_release(blkdrvr_inode);
}
free(fullpath_bak);
#ifdef LOSCFG_FS_FAT_VIRTUAL_PARTITION
if (errcode >= VIRERR_BASE)
{
set_errno(errcode);
}
#endif
return OK;
/* A lot of goto's! But they make the error handling much simpler */
errout_with_mountpt:
(void)inode_remove(fullpath);
errout_with_semaphore:
inode_semgive();
if (blkdrvr_inode != NULL)
{
inode_release(blkdrvr_inode);
}
free(fullpath_bak);
errout:
set_errno(errcode);
return VFS_ERROR;
}
#endif /* CONFIG_FS_READABLE */
+238
View File
@@ -0,0 +1,238 @@
/****************************************************************************
* fs/mount/fs_umount.c
*
* Copyright (C) 2007-2009, 2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "sys/mount.h"
#include "errno.h"
#include "fs/fs.h"
#include "inode/inode.h"
#include "stdlib.h"
#include "string.h"
#include "disk.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Variables
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: umount
*
* Description:
* umount() detaches the filesystem mounted at the path specified by
* 'target.'
*
* Return:
* Zero is returned on success; -1 is returned on an error and errno is
* set appropriately:
*
* EACCES A component of a path was not searchable or mounting a read-only
* filesystem was attempted without giving the MS_RDONLY flag.
* EBUSY The target could not be unmounted because it is busy.
* EFAULT The pointer argument points outside the user address space.
*
****************************************************************************/
int umount(const char *target)
{
FAR struct inode *mountpt_inode = NULL;
FAR struct inode *blkdrvr_inode = NULL;
int errcode = OK;
int status;
char *fullpath = NULL;
const char *relpath = NULL;
struct inode_search_s desc;
int ret;
/* Verify required pointer arguments */
if (target == NULL)
{
errcode = EFAULT;
goto errout;
}
/* Get a absolute path*/
errcode = vfs_normalize_path((const char *)NULL, target, &fullpath);
if (errcode < 0)
{
errcode = -errcode;
goto errout;
}
/* Find the mountpt */
SETUP_SEARCH(&desc, fullpath, false);
ret = inode_find(&desc);
if (ret < 0)
{
errcode = EACCES;
free(fullpath);
goto errout;
}
mountpt_inode = desc.node;
relpath = desc.relpath;
/* Verify that the inode is a mountpoint */
if (!INODE_IS_MOUNTPT(mountpt_inode))
{
errcode = EINVAL;
goto errout_with_mountpt;
}
/* Verfy the path is a mountpoint path or file path*/
if ((relpath != NULL) && strlen(relpath))
{
errcode = EPERM;
goto errout_with_mountpt;
}
/* Unbind the block driver from the file system (destroying any fs
* private data.
*/
if (mountpt_inode->u.i_mops->unbind == NULL)
{
/* The filesystem does not support the unbind operation ??? */
errcode = EINVAL;
goto errout_with_mountpt;
}
inode_semtake(); /* Hold the semaphore through the unbind logic */
if (mountpt_inode->i_crefs == 1)
{
status = mountpt_inode->u.i_mops->unbind(mountpt_inode->i_private, &blkdrvr_inode);
if (status < 0)
{
/* The inode is unhappy with the blkdrvr for some reason */
errcode = -status;
goto errout_with_semaphore;
}
else if (status > 0)
{
errcode = EBUSY;
goto errout_with_semaphore;
}
}
else
{
errcode = EBUSY;
goto errout_with_semaphore;
}
/* Successfully unbound */
mountpt_inode->i_private = NULL;
mountpt_inode->u.i_ops= (const struct file_operations_vfs *)NULL;
mountpt_inode->i_flags = 0;
inode_release(mountpt_inode);
/* Successfully unbound, remove the mountpoint inode from
* the inode tree. The inode will not be deleted yet because
* there is still at least reference on it (from the mount)
*/
if (blkdrvr_inode)
{
blkdrvr_inode->e_status = STAT_UNMOUNTED;
}
inode_semgive();
/* Did the unbind method return a contained block driver */
if (blkdrvr_inode)
{
inode_release(blkdrvr_inode);
}
free(fullpath);
return OK;
/* A lot of goto's! But they make the error handling much simpler */
errout_with_semaphore:
inode_semgive();
errout_with_mountpt:
mountpt_inode->i_crefs--;
if (blkdrvr_inode)
{
inode_release(blkdrvr_inode);
}
free(fullpath);
errout:
set_errno(errcode);
return VFS_ERROR;
}
int umount2(const char* __target, int __flags)
{
/* TODO: __flags need to be support */
if (__flags) {
set_errno(ENOSYS);
return VFS_ERROR;
}
return umount(__target);
}
Executable
+146
View File
@@ -0,0 +1,146 @@
/****************************************************************************
* fs/nfs/nfs.h
*
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved.
* Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com>
* Gregory Nutt <gnutt@nuttx.org>
*
* Leveraged from OpenBSD:
*
* Copyright (c) 1989, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Rick Macklem at The University of Guelph.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
****************************************************************************/
#ifndef __FS_NFS_NFS_H
#define __FS_NFS_NFS_H
/****************************************************************************
* Included Files
****************************************************************************/
#include "nfs_mount.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define NFS_TICKS 1 /* Number of system ticks */
#define NFS_HZ CLOCKS_PER_SEC /* Ticks/sec */
#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */
#define NFS_MINTIMEO (1 * NFS_HZ) /* Min timeout to use */
#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */
#define NFS_TIMEOUTMUL 2 /* Timeout/Delay multiplier */
#define NFS_MAXREXMIT 10 /* Stop counting after this many */
#define NFS_RETRANS 5 /* Num of retrans for soft mounts */
#define NFS_WSIZE (8192 * 4) /* Def. write data size <= 8192 */
#define NFS_RSIZE (8192 * 4) /* Def. read data size <= 8192 */
#define NFS_READDIRSIZE 1024 /* Def. readdir size */
#define NFS_NPROCS 23
/* Ideally, NFS_DIRBLKSIZ should be bigger, but I've seen servers with
* broken NFS/ethernet drivers that won't work with anything bigger (Linux..)
*/
#define NFS_DIRBLKSIZ 1024 /* Must be a multiple of DIRBLKSIZ */
/* Increment NFS statistics */
#ifdef CONFIG_NFS_STATISTICS
# define nfs_statistics(n) do { nfsstats.rpccnt[n]++; } while (0)
#else
# define nfs_statistics(n)
#endif
/****************************************************************************
* Public Data
****************************************************************************/
typedef void (*NFSMOUNT_HOOK)(struct nfs_args*);
extern uint32_t nfs_true;
extern uint32_t nfs_false;
extern NFSMOUNT_HOOK g_NFSMOUNT_HOOK;
extern uint32_t nfs_xdrneg1;
#ifdef CONFIG_NFS_STATISTICS
extern struct nfsstats nfsstats;
#endif
/****************************************************************************
* Public Types
****************************************************************************/
/* NFS statistics structure */
struct nfsstats
{
uint64_t rpccnt[NFS_NPROCS];
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
extern void nfs_mux_take(FAR struct nfsmount *nmp);
extern void nfs_mux_release(FAR struct nfsmount *nmp);
extern int nfs_checkmount(FAR struct nfsmount *nmp);
extern int nfs_fsinfo(FAR struct nfsmount *nmp);
extern int nfs_request(struct nfsmount *nmp, int procnum,
FAR void *request, size_t reqlen,
FAR void *response, size_t resplen);
extern int nfs_lookup(FAR struct nfsmount *nmp, FAR const char *filename,
FAR struct file_handle *fhandle,
FAR struct nfs_fattr *obj_attributes,
FAR struct nfs_fattr *dir_attributes);
extern int nfs_findnode(FAR struct nfsmount *nmp, FAR const char *relpath,
FAR struct file_handle *fhandle,
FAR struct nfs_fattr *obj_attributes,
FAR struct nfs_fattr *dir_attributes);
extern int nfs_finddir(FAR struct nfsmount *nmp, FAR const char *relpath,
FAR struct file_handle *fhandle,
FAR struct nfs_fattr *attributes, FAR char *filename);
extern void nfs_attrupdate(FAR struct nfsnode *np,
FAR struct nfs_fattr *attributes);
extern int nfs_mount(const char *server_ip_and_path, const char *mount_path,
unsigned int uid, unsigned int gid);
#ifdef __cplusplus
#if __cplusplus
}
#endif /*__cplusplus */
#endif /*__cplusplus */
#endif /* _NFS_NFS_H */
+178
View File
@@ -0,0 +1,178 @@
/****************************************************************************
* fs/nfs/nfs_mount.h
*
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved.
* Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com>
* Gregory Nutt <gnutt@nuttx.org>
*
* Leveraged from OpenBSD:
*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Rick Macklem at The University of Guelph.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
****************************************************************************/
#ifndef __FS_NFS_NFS_MOUNT_H
#define __FS_NFS_NFS_MOUNT_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/socket.h>
#include <semaphore.h>
#include <netinet/in.h>
#include <pthread.h>
#include "rpc.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* NFS mount option flags */
#define NFSMNT_SOFT (1 << 0) /* Soft mount (hard is default) */
#define NFSMNT_WSIZE (1 << 1) /* Set write size */
#define NFSMNT_RSIZE (1 << 2) /* Set read size */
#define NFSMNT_TIMEO (1 << 3) /* Set initial timeout */
#define NFSMNT_RETRANS (1 << 4) /* Set number of request retries */
#define NFSMNT_READDIRSIZE (1 << 5) /* Set readdir size */
/****************************************************************************
* Public Types
****************************************************************************/
/* Mount structure. One mount structure is allocated for each NFS mount. This
* structure holds NFS specific information for mount.
*/
struct nfsmount
{
struct nfsnode *nm_head; /* A list of all files opened on this mountpoint */
struct nfsdir_s *nm_dir; /* A list of all directories opened on this mountpoint */
pthread_mutex_t nm_mux; /* Used to assure thread-safe access */
nfsfh_t nm_fh; /* File handle of root dir */
char nm_path[NFS_MOUNT_PATH_MAX_SIZE]; /* server's path of the directory being mounted */
struct nfs_fattr nm_fattr; /* nfs file attribute cache */
struct rpcclnt *nm_rpcclnt; /* RPC state */
int32_t nm_so; /* RPC socket */
struct sockaddr nm_nam; /* Addr of server */
bool nm_mounted; /* true: The file system is ready */
uint8_t nm_fhsize; /* Size of root file handle (host order) */
uint8_t nm_sotype; /* Type of socket */
uint8_t nm_retry; /* Max retries */
uint32_t nm_timeo; /* Timeout value (in system clock ticks) */
uint16_t nm_rsize; /* Max size of read RPC */
uint16_t nm_wsize; /* Max size of write RPC */
uint16_t nm_readdirsize; /* Size of a readdir RPC */
uint16_t nm_buflen; /* Size of I/O buffer */
/* Set aside memory on the stack to hold the largest call message. NOTE
* that for the case of the write call message, it is the reply message that
* is in this union.
*/
union
{
struct rpc_call_pmap pmap;
struct rpc_call_mount mountd;
struct rpc_call_create create;
struct rpc_call_lookup lookup;
struct rpc_call_read read;
struct rpc_call_remove removef;
struct rpc_call_rename renamef;
struct rpc_call_mkdir mkdir;
struct rpc_call_rmdir rmdir;
struct rpc_call_readdir readdir;
struct rpc_call_fs fsstat;
struct rpc_call_setattr setattr;
struct rpc_call_fs fs;
struct rpc_reply_write write;
} nm_msgbuffer;
/* I/O buffer (must be a aligned to 32-bit boundaries). This buffer used for all
* reply messages EXCEPT for the WRITE RPC. In that case it is used for the WRITE
* call message that contains the data to be written. This buffer must be
* dynamically sized based on the characteristics of the server and upon the
* configuration of the NuttX network. It must be sized to hold the largest
* possible WRITE call message or READ response message.
*/
uint32_t nm_iobuffer[1]; /* Actual size is given by nm_buflen */
};
/* The size of the nfsmount structure will debug on the size of the allocated I/O
* buffer.
*/
#define SIZEOF_nfsmount(n) (sizeof(struct nfsmount) + ((n + 3) & ~3) - sizeof(uint32_t))
/* Mount parameters structure. This structure is use in nfs_decode_args funtion before one
* mount structure is allocated in each NFS mount.
*/
struct nfs_mount_parameters
{
uint32_t timeo; /* Timeout value (in deciseconds) */
uint8_t retry; /* Max retries */
uint16_t rsize; /* Max size of read RPC */
uint16_t wsize; /* Max size of write RPC */
uint16_t readdirsize; /* Size of a readdir RPC */
};
struct nfs_args
{
uint8_t addrlen; /* Length of address */
uint8_t sotype; /* Socket type */
uint8_t flags; /* Flags, determines if following are valid: */
uint8_t timeo; /* Time value in deciseconds (with NFSMNT_TIMEO) */
uint8_t retrans; /* Times to retry send (with NFSMNT_RETRANS) */
uint16_t wsize; /* Write size in bytes (with NFSMNT_WSIZE) */
uint16_t rsize; /* Read size in bytes (with NFSMNT_RSIZE) */
uint16_t readdirsize; /* readdir size in bytes (with NFSMNT_READDIRSIZE) */
char *path; /* Server's path of the directory being mount */
struct sockaddr addr; /* File server address (requires 32-bit alignment) */
};
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif
+99
View File
@@ -0,0 +1,99 @@
/****************************************************************************
* fs/nfs/nfs_node.h
*
* Copyright (C) 2012-2013, 2017 Gregory Nutt. All rights reserved.
* Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved.
* Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com>
* Gregory Nutt <gnutt@nuttx.org>
*
* Leveraged from OpenBSD:
*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Rick Macklem at The University of Guelph.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
****************************************************************************/
#ifndef __FS_NFS_NFS_NODE_H
#define __FS_NFS_NFS_NODE_H
/****************************************************************************
* Included Files
****************************************************************************/
#include "nfs_proto.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Flags for struct nfsnode n_flag */
#define NFSNODE_OPEN (1 << 0) /* File is still open */
#define NFSNODE_MODIFIED (1 << 1) /* Might have a modified buffer */
/****************************************************************************
* Public Types
****************************************************************************/
/* There is a unique nfsnode allocated for each active file. An nfsnode is
* 'named' by its file handle.
*/
struct nfsnode
{
struct nfsnode *n_next; /* Retained in a singly linked list. */
uint8_t n_crefs; /* Reference count (for nfs_dup) */
uint8_t n_type; /* File type */
uint8_t n_fhsize; /* Size in bytes of the file handle */
uint8_t n_flags; /* Node flags */
uint16_t n_mode; /* File mode for fstat() */
time_t n_mtime; /* File modification time */
time_t n_ctime; /* File creation time */
nfsfh_t n_fhandle; /* NFS File Handle */
uint64_t n_size; /* Current size of file */
int n_oflags; /* Flags provided when file was opened */
loff_t n_fpos; /* NFS File position */
struct file *n_filep; /* File pointer from VFS */
};
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __FS_NFS_NFS_NODE_H */
+637
View File
@@ -0,0 +1,637 @@
/****************************************************************************
* fs/nfs/nfs_proto.h
*
* Copyright (C) 2012, 2018 Gregory Nutt. All rights reserved.
* Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved.
* Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com>
* Gregory Nutt <gnutt@nuttx.org>
*
* Leveraged from OpenBSD:
*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Rick Macklem at The University of Guelph.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
****************************************************************************/
#ifndef __FS_NFS_NFS_PROTO_H
#define __FS_NFS_NFS_PROTO_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <limits.h>
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Constants as defined in the Sun NFS Version 2 and 3 specs.
* "NFS: Network File System Protocol Specification" RFC1094
* and in the "NFS: Network File System Version 3 Protocol
* Specification"
*/
#define NFS_PORT 2049
#define NFS_PROG 100003
#define NFS_VER2 2
#define NFS_VER3 3
#define NFS_VER4 4
#define NFS_MAXDGRAMDATA 32768
#define MAXBSIZE 64000
#define NFS_MAXDATA MAXBSIZE
#define NFS_MAXPATHLEN 1024
#define NFS_MAXNAMLEN 255
#define NFS_MAXPKTHDR 404
#define NFS_MAXPACKET (NFS_MAXPKTHDR + NFS_MAXDATA)
#define NFS_MINPACKET 20
#define NFS_FABLKSIZE 512 /* Size in bytes of a block wrt fa_blocks */
#define NFS_MOUNT_PATH_MAX_SIZE PATH_MAX
/* Stat numbers for rpc returns (version 2 and 3) */
#define NFS_OK 0
#define NFSERR_PERM 1
#define NFSERR_NOENT 2
#define NFSERR_IO 5
#define NFSERR_NXIO 6
#define NFSERR_ACCES 13
#define NFSERR_EXIST 17
#define NFSERR_XDEV 18 /* Version 3 only */
#define NFSERR_NODEV 19
#define NFSERR_NOTDIR 20
#define NFSERR_ISDIR 21
#define NFSERR_INVAL 22 /* Version 3 only */
#define NFSERR_FBIG 27
#define NFSERR_NOSPC 28
#define NFSERR_ROFS 30
#define NFSERR_MLINK 31 /* Version 3 only */
#define NFSERR_NAMETOL 63
#define NFSERR_NOTEMPTY 66
#define NFSERR_DQUOT 69
#define NFSERR_STALE 70
#define NFSERR_REMOTE 71 /* Version 3 only */
#define NFSERR_WFLUSH 99 /* Version 2 only */
#define NFSERR_BADHANDLE 10001 /* The rest Version 3 only */
#define NFSERR_NOT_SYNC 10002
#define NFSERR_BAD_COOKIE 10003
#define NFSERR_NOTSUPP 10004
#define NFSERR_TOOSMALL 10005
#define NFSERR_SERVERFAULT 10006
#define NFSERR_BADTYPE 10007
#define NFSERR_JUKEBOX 10008
#define NFSERR_TRYLATER NFSERR_JUKEBOX
#define NFSERR_STALEWRITEVERF 30001 /* Fake return for nfs_commit() */
#define NFSERR_RETVOID 0x20000000 /* Return void, not error */
#define NFSERR_AUTHERR 0x40000000 /* Mark an authentication error */
#define NFSERR_RETERR 0x80000000 /* Mark an error return for V3 */
/* Sizes in bytes of various NFS RPC components */
#define NFSX_UNSIGNED 4
/* Specific to NFS Version 3 */
#define NFSX_V3FH (sizeof (fhandle_t)) /* size this server uses */
#define NFSX_V3FHMAX 64 /* max. allowed by protocol */
#define NFSX_V3FATTR 84
#define NFSX_V3SATTR 60 /* max. all fields filled in */
#define NFSX_V3SRVSATTR (sizeof (struct nfsv3_sattr))
#define NFSX_V3POSTOPATTR (NFSX_V3FATTR + NFSX_UNSIGNED)
#define NFSX_V3WCCDATA (NFSX_V3POSTOPATTR + 8 * NFSX_UNSIGNED)
#define NFSX_V3COOKIEVERF 8
#define NFSX_V3WRITEVERF 8
#define NFSX_V3CREATEVERF 8
#define NFSX_V3STATFS 52
#define NFSX_V3FSINFO 48
#define NFSX_V3PATHCONF 24
/* NFS RPC procedure numbers (before version mapping) */
#define NFSPROC_NULL 0
#define NFSPROC_GETATTR 1
#define NFSPROC_SETATTR 2
#define NFSPROC_LOOKUP 3
#define NFSPROC_ACCESS 4
#define NFSPROC_READLINK 5
#define NFSPROC_READ 6
#define NFSPROC_WRITE 7
#define NFSPROC_CREATE 8
#define NFSPROC_MKDIR 9
#define NFSPROC_SYMLINK 10
#define NFSPROC_MKNOD 11
#define NFSPROC_REMOVE 12
#define NFSPROC_RMDIR 13
#define NFSPROC_RENAME 14
#define NFSPROC_LINK 15
#define NFSPROC_READDIR 16
#define NFSPROC_READDIRPLUS 17
#define NFSPROC_FSSTAT 18
#define NFSPROC_FSINFO 19
#define NFSPROC_PATHCONF 20
#define NFSPROC_COMMIT 21
#define NFSPROC_NOOP 22
#define NFS_NPROCS 23
/* Constants used by the Version 3 protocol for various RPCs */
#define NFSV3SATTRTIME_DONTCHANGE 0
#define NFSV3SATTRTIME_TOSERVER 1
#define NFSV3SATTRTIME_TOCLIENT 2
#define NFSV3ACCESS_READ 0x01
#define NFSV3ACCESS_LOOKUP 0x02
#define NFSV3ACCESS_MODIFY 0x04
#define NFSV3ACCESS_EXTEND 0x08
#define NFSV3ACCESS_DELETE 0x10
#define NFSV3ACCESS_EXECUTE 0x20
#define NFSV3WRITE_UNSTABLE 0
#define NFSV3WRITE_DATASYNC 1
#define NFSV3WRITE_FILESYNC 2
#define NFSV3CREATE_UNCHECKED 0
#define NFSV3CREATE_GUARDED 1
#define NFSV3CREATE_EXCLUSIVE 2
#define NFSV3FSINFO_LINK 0x01
#define NFSV3FSINFO_SYMLINK 0x02
#define NFSV3FSINFO_HOMOGENEOUS 0x08
#define NFSV3FSINFO_CANSETTIME 0x10
/* Conversion macros */
#define vtonfsv3_mode(m) txdr_unsigned((m) & 07777)
#define nfstov_mode(a) (fxdr_unsigned(u_int16_t, (a))&07777)
#define vtonfsv3_type(a) txdr_unsigned(nfsv3_type[((int32_t)(a))])
#define nfsv3tov_type(a) nv3tov_type[fxdr_unsigned(uint32_t,(a))&0x7]
/* Mode bit values */
#define NFSMODE_IXOTH (1 << 0) /* Execute permission for others on a file */
#define NFSMODE_IWOTH (1 << 1) /* Write permission for others */
#define NFSMODE_IROTH (1 << 2) /* Read permission for others */
#define NFSMODE_IXGRP (1 << 3) /* Execute permission for group on a file */
#define NFSMODE_IWGRP (1 << 4) /* Write permission for group */
#define NFSMODE_IRGRP (1 << 5) /* Read permission for group */
#define NFSMODE_IXUSR (1 << 6) /* Execute permission for owner on a file */
#define NFSMODE_IWUSR (1 << 7) /* Write permission for owner */
#define NFSMODE_IRUSR (1 << 8) /* Read permission for owner */
#define NFSMODE_SAVETEXT (1 << 9) /* Save swapped text */
#define NFSMODE_ISGID (1 << 10) /* Set group ID on execution */
#define NFSMODE_ISUID (1 << 11) /* Set user ID on execution */
#define DIRENT_NFS_MAXHANDLE 64 /* Maximum length of an NFSv3 file handle */
#define DIRENT_NFS_VERFLEN 8 /* Length of the copy verifier */
/* File identifier */
#define MAXFIDSZ 16
/****************************************************************************
* Public Types
****************************************************************************/
/* File types */
typedef enum
{
NFNON = 0, /* Unknown type */
NFREG = 1, /* Regular file */
NFDIR = 2, /* Directory */
NFBLK = 3, /* Block special device file */
NFCHR = 4, /* Character special device file */
NFLNK = 5, /* Symbolic link */
NFSOCK = 6, /* Socket */
NFFIFO = 7 /* Named FIFO */
} nfstype;
/* File Handle variable is up to 64 bytes for version 3. This structures a
* ariable sized and are provided only for setting aside maximum memory
* allocations for a file handle.
*/
struct nfsfh
{
uint8_t fh_bytes[NFSX_V3FHMAX];
};
typedef struct nfsfh nfsfh_t;
#define SIZEOF_nfsfh_t(n) (n)
struct nfsv3_time
{
uint32_t nfsv3_sec;
uint32_t nfsv3_nsec;
};
typedef struct nfsv3_time nfstime3;
/* Quads are defined as arrays of 2 longs to ensure dense packing for the
* protocol and to facilitate xdr conversion.
*/
struct nfs_uquad
{
uint32_t nfsuquad[2];
};
typedef struct nfs_uquad nfsuint64;
/* NFS Version 3 special file number. */
struct nfsv3_spec
{
uint32_t specdata1;
uint32_t specdata2;
};
typedef struct nfsv3_spec nfsv3spec;
/* File attributes and setable attributes. These structures cover both
* NFS version 2 and the version 3 protocol. Note that the union is only
* used so that one pointer can refer to both variants. These structures
* go out on the wire and must be densely packed, so no quad data types
* are used. (all fields are longs or u_longs or structures of same)
*/
struct nfs_fattr
{
uint32_t fa_type;
uint32_t fa_mode;
uint32_t fa_nlink;
uint32_t fa_uid;
uint32_t fa_gid;
nfsuint64 fa_size;
nfsuint64 fa_used;
nfsv3spec fa_rdev;
nfsuint64 fa_fsid;
nfsuint64 fa_fileid;
nfstime3 fa_atime;
nfstime3 fa_mtime;
nfstime3 fa_ctime;
};
/* NFS Version 3 sattr structure for the new node creation case. This is the
* maximum size of the attributes; the actual size may vary if values are not
* include.
*/
struct nfsv3_sattr
{
uint32_t sa_modefollows; /* TRUE: Mode value follows */
uint32_t sa_mode; /* Mode value */
uint32_t sa_uidfollows; /* TRUE: Uid value follows */
uint32_t sa_uid; /* Uid value */
uint32_t sa_gidfollows; /* TRUE: Mode value follows */
uint32_t sa_gid; /* Mode value */
uint32_t sa_sizefollows; /* TRUE: Size value follows */
uint32_t sa_size; /* Size value */
uint32_t sa_atimetype; /* Don't change, use server timer, or use client time */
nfstime3 sa_atime; /* Client time */
uint32_t sa_mtimetype; /* Don't change, use server timer, or use client time */
nfstime3 sa_mtime; /* Client time */
};
struct nfs_statfs
{
uint32_t attributes_follow;
struct nfs_fattr obj_attributes;
nfsuint64 sf_tbytes;
nfsuint64 sf_fbytes;
nfsuint64 sf_abytes;
nfsuint64 sf_tfiles;
nfsuint64 sf_ffiles;
nfsuint64 sf_afiles;
uint32_t sf_invarsec;
};
struct nfs_statfs_ctx
{
nfsuint64 sf_tbytes;
nfsuint64 sf_fbytes;
nfsuint64 sf_abytes;
nfsuint64 sf_tfiles;
nfsuint64 sf_ffiles;
nfsuint64 sf_afiles;
uint32_t sf_invarsec;
};
struct entry3
{
uint32_t file_id[2];
uint32_t name_len;
uint8_t *contents;
uint32_t cookie[2];
struct entry3 *next;
};
struct nfsdir_s
{
struct nfsdir_s* nfs_next; /* A list of opened directories. */
uint8_t nfs_fhsize; /* Length of the file handle */
uint8_t nfs_fhandle[DIRENT_NFS_MAXHANDLE]; /* File handle (max size allocated) */
uint8_t nfs_verifier[DIRENT_NFS_VERFLEN]; /* Cookie verifier */
uint32_t nfs_cookie[2]; /* Cookie */
struct fs_dirent_s *nfs_dir; /* Directory pointer from VFS */
struct entry3 *nfs_entries; /* Directory pointer from VFS */
};
struct post_attr
{
uint32_t obj_attribute_follow;
struct nfs_fattr attributes;
};
struct nfsv3_fsinfo
{
struct post_attr obj_attributes;
uint32_t fs_rtmax;
uint32_t fs_rtpref;
uint32_t fs_rtmult;
uint32_t fs_wtmax;
uint32_t fs_wtpref;
uint32_t fs_wtmult;
uint32_t fs_dtpref;
nfsuint64 fs_maxfilesize;
nfstime3 fs_timedelta;
uint32_t fs_properties;
};
struct nfs_fsinfo
{
uint32_t fs_rtmax;
uint32_t fs_rtpref;
uint32_t fs_rtmult;
uint32_t fs_wtmax;
uint32_t fs_wtpref;
uint32_t fs_wtmult;
uint32_t fs_dtpref;
nfsuint64 fs_maxfilesize;
nfstime3 fs_timedelta;
uint32_t fs_properties;
};
/* NFS procedures args */
struct wcc_attr
{
nfsuint64 size;
nfstime3 mtime;
nfstime3 ctime;
};
struct wcc_data
{
uint32_t wcc_attr_follows; /* True if data follows */
struct wcc_attr before;
uint32_t nfs_attr_follow; /* True if attributes present */
struct nfs_fattr after;
};
struct file_handle
{
uint32_t length;
nfsfh_t handle;
};
#define SIZEOF_file_handle(n) (sizeof(uint32_t) + SIZEOF_nfsfh_t(n))
struct diropargs3
{
struct file_handle fhandle; /* Variable length */
uint32_t length; /* Size of name[] */
uint32_t name[(NAME_MAX+3) >> 2]; /* Variable length */
};
struct CREATE3args
{
struct diropargs3 where;
uint32_t create_mode;
struct nfsv3_sattr how;
};
struct CREATE3resok
{
uint32_t handle_follows; /* True, handle follows */
struct file_handle fhandle; /* Variable length */
uint32_t attributes_follows; /* True, attributes follows */
struct nfs_fattr attributes; /* File attributes */
struct wcc_data dir_wcc;
};
/* The actual size of the lookup argument is variable. These structures are, therefore,
* only useful in setting aside maximum memory usage for the LOOKUP arguments.
*/
struct LOOKUP3filename
{
uint32_t namelen; /* Size of name[] */
uint32_t name[(NAME_MAX+3) >> 2]; /* Variable length */
};
struct LOOKUP3args
{
struct file_handle dirhandle; /* Variable length */
struct LOOKUP3filename name; /* Variable length */
};
struct SETATTR3args
{
struct file_handle fhandle; /* Variable length */
struct nfsv3_sattr new_attributes; /* Variable length */
uint32_t guard; /* Guard value */
};
struct SETATTR3resok
{
struct wcc_data wcc_data;
};
/* Actual size of LOOKUP3args */
#define SIZEOF_LOOKUP3filename(b) (sizeof(uint32_t) + (((b)+3) & ~3))
#define SIZEOF_LOOKUP3args(a,b) (SIZEOF_file_handle(a) + SIZEOF_LOOKUP3filename(b))
struct LOOKUP3resok
{
struct file_handle fhandle;
uint32_t obj_attributes_follow;
struct nfs_fattr obj_attributes;
uint32_t dir_attributes_follow;
struct nfs_fattr dir_attributes;
};
struct READ3args
{
struct file_handle fhandle; /* Variable length */
uint64_t offset;
uint32_t count;
};
struct nfs_rdhdr_s
{
uint32_t attributes_follow;
struct nfs_fattr attributes; /* Will not be present if attributes_follow == 0 */
uint32_t count; /* Number of bytes read */
uint32_t eof; /* Non-zero if at the end of file */
uint32_t length; /* Length of data (same as count?) */
};
struct READ3resok
{
struct nfs_rdhdr_s hdr;
uint8_t data[1]; /* Actual data size depends on count */
};
#define SIZEOF_READ3resok(n) (sizeof(struct nfs_rdhdr_s) + (n))
struct nfs_wrhdr_s
{
struct file_handle fhandle; /* Variable length */
uint64_t offset;
uint32_t count;
uint32_t stable;
};
struct WRITE3args
{
struct nfs_wrhdr_s hdr;
uint8_t data[1]; /* Actual data size depends on count */
};
#define SIZEOF_WRITE3args(n) (sizeof(struct nfs_wrhdr_s) + (n))
struct WRITE3resok
{
struct wcc_data file_wcc;
uint32_t count;
uint32_t committed;
uint8_t verf[NFSX_V3WRITEVERF];
};
struct REMOVE3args
{
struct diropargs3 object;
};
struct REMOVE3resok
{
struct wcc_data dir_wcc;
};
struct RENAME3args
{
struct diropargs3 from;
struct diropargs3 to;
};
struct RENAME3resok
{
struct wcc_data fromdir_wcc;
struct wcc_data todir_wcc;
};
struct MKDIR3args
{
struct diropargs3 where;
struct nfsv3_sattr how;
};
struct MKDIR3resok
{
uint32_t handle_follows; /* True, handle follows */
struct file_handle fhandle; /* Variable length */
uint32_t attributes_follows; /* True, attributes follows */
struct nfs_fattr attributes; /* Directory attributes */
struct wcc_data dir_wcc;
};
struct RMDIR3args
{
struct diropargs3 object;
};
struct RMDIR3resok
{
struct wcc_data dir_wcc;
};
/* The actual size of the lookup argument is variable. This structures is, therefore,
* only useful in setting aside maximum memory usage for the LOOKUP arguments.
*/
struct READDIR3args
{
struct file_handle dir; /* Variable length */
nfsuint64 cookie;
uint8_t cookieverf[NFSX_V3COOKIEVERF];
uint32_t count;
};
/* The READDIR reply is variable length and consists of multiple entries, each
* of form:
*
* EOF - OR -
*
* File ID (8 bytes)
* Name length (4 bytes)
* Name string (varaiable size but in multiples of 4 bytes)
* Cookie (8 bytes)
* next entry (4 bytes)
*/
struct READDIR3resok
{
uint32_t attributes_follow;
struct nfs_fattr dir_attributes;
uint8_t cookieverf[NFSX_V3COOKIEVERF];
uint32_t value_follows;
uint32_t reply[1]; /* Variable length reply begins here */
};
#define SIZEOF_READDIR3resok(n) \
(sizeof(uint32_t) + sizeof(struct nfs_fattr) + \
NFSX_V3COOKIEVERF + sizeof(uint32_t) + (n))
struct FS3args
{
struct file_handle fsroot;
};
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __FS_NFS_NFS_PROTO_H */
+571
View File
@@ -0,0 +1,571 @@
/****************************************************************************
* fs/nfs/nfs_util.c
*
* Copyright (C) 2012-2013, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/types.h>
#include <sys/time.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <debug.h>
#include <pthread.h>
#include "vfs_config.h"
#include "dirent.h"
#include "rpc.h"
#include "nfs.h"
#include "nfs_node.h"
#include "xdr_subs.h"
#undef OK
#define OK 0
/****************************************************************************
* Private Functions
****************************************************************************/
static inline int nfs_pathsegment(FAR const char **path, FAR char *buffer,
FAR char *terminator)
{
FAR const char *src = *path;
FAR char *dest = buffer;
int nbytes = 0;
char ch;
/* Loop until the name is successfully parsed or an error occurs */
for (; ; )
{
/* Get the next byte from the path */
ch = *src++;
/* Check if this the last byte in this segment name */
if (ch == '\0' || ch == '/')
{
/* This logic just supports "//" sequences in the path name */
if (ch == '\0' || nbytes > 0)
{
/* NULL terminate the parsed path segment */
*dest = '\0';
/* Return next path and the terminating character */
*terminator = ch;
*path = src;
return OK;
}
/* Just skip over any leading '/' characters */
}
else if (nbytes >= NAME_MAX)
{
ferr("ERROR: File name segment is too long: %d\n", *path);
return ENAMETOOLONG;
}
else
{
/* Save next character in the accumulated name */
*dest++ = ch;
nbytes++;
}
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: nfs_mux_take
****************************************************************************/
void nfs_mux_take(struct nfsmount *nmp)
{
(void)pthread_mutex_lock(&nmp->nm_mux);
}
/****************************************************************************
* Name: nfs_mux_release
****************************************************************************/
void nfs_mux_release(struct nfsmount *nmp)
{
(void)pthread_mutex_unlock(&nmp->nm_mux);
}
/****************************************************************************
* Name: nfs_checkmount
*
* Description: Check if the mountpoint is still valid.
*
* The caller should hold the mountpoint semaphore
*
****************************************************************************/
int nfs_checkmount(struct nfsmount *nmp)
{
struct nfsnode *file;
/* If the nm_mounted flag is false, then we have already handled the loss
* of the mount.
*/
DEBUGASSERT(nmp);
if (!nmp->nm_mounted)
{
/* Make sure that this is flagged in every opened file */
for (file = nmp->nm_head; file; file = file->n_next)
{
file->n_flags &= ~NFSNODE_OPEN;
}
return ENODEV;
}
return 0;
}
/****************************************************************************
* Name: nfs_request
*
* Description:
* Perform the NFS request. On successful receipt, it verifies the NFS level of the
* returned values.
*
* Returned Value:
* Zero on success; a positive errno value on failure.
*
****************************************************************************/
int nfs_request(struct nfsmount *nmp, int procnum,
FAR void *request, size_t reqlen,
FAR void *response, size_t resplen)
{
struct rpcclnt *clnt = nmp->nm_rpcclnt;
struct nfs_reply_header replyh;
int error;
tryagain:
error = rpcclnt_request(clnt, procnum, NFS_PROG, NFS_VER3,
request, reqlen, response, resplen);
if (error != 0)
{
ferr("ERROR: rpcclnt_request failed: %d\n", error);
return error;
}
memcpy(&replyh, response, sizeof(struct nfs_reply_header));
if (replyh.nfs_status != 0)
{
/* NFS_ERRORS are the same as NuttX errno values */
error = fxdr_unsigned(uint32_t, replyh.nfs_status);
return error;
}
if (replyh.rpc_verfi.authtype != 0)
{
error = fxdr_unsigned(int, replyh.rpc_verfi.authtype);
if (error == EAGAIN)
{
error = 0;
goto tryagain;
}
ferr("ERROR: NFS error %d from server\n", error);
return error;
}
finfo("NFS_SUCCESS\n");
return OK;
}
/****************************************************************************
* Name: nfs_lookup
*
* Description:
* Given a directory file handle, and the path to file in the directory,
* return the file handle of the path and attributes of both the file and
* the directory containing the file.
*
* NOTE: The LOOKUP call differs from other RPC messages in that the
* call message is variable length, depending upon the size of the path
* name.
*
****************************************************************************/
int nfs_lookup(struct nfsmount *nmp, FAR const char *filename,
FAR struct file_handle *fhandle,
FAR struct nfs_fattr *obj_attributes,
FAR struct nfs_fattr *dir_attributes)
{
FAR uint32_t *ptr;
uint32_t value;
int reqlen;
int namelen;
int error = 0;
DEBUGASSERT(nmp && filename && fhandle);
/* Get the length of the string to be sent */
namelen = strlen(filename);
if (namelen > NAME_MAX)
{
ferr("ERROR: Length of the string is too long: %d\n", namelen);
return E2BIG;
}
/* Initialize the request */
ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.lookup.lookup;
reqlen = 0;
/* Copy the variable length, directory file handle */
*ptr++ = txdr_unsigned(fhandle->length);
reqlen += sizeof(uint32_t);
memcpy(ptr, &fhandle->handle, fhandle->length);
reqlen += fhandle->length;
ptr += uint32_increment(fhandle->length);
/* Copy the variable-length file name */
*ptr++ = txdr_unsigned(namelen);
reqlen += sizeof(uint32_t);
memcpy(ptr, filename, namelen);
reqlen += uint32_alignup(namelen);
/* Request LOOKUP from the server */
nfs_statistics(NFSPROC_LOOKUP);
error = nfs_request(nmp, NFSPROC_LOOKUP,
(FAR void *)&nmp->nm_msgbuffer.lookup, reqlen,
(FAR void *)nmp->nm_iobuffer, nmp->nm_buflen);
if (error)
{
ferr("ERROR: nfs_request failed: %d\n", error);
return error;
}
/* Return the data to the caller's buffers. NOTE: Here we ignore the
* the exact layout of the rpc_reply_lookup structure. File handles
* may differ in size whereas struct rpc_reply_lookup uses a fixed size.
*/
ptr = (FAR uint32_t *)&((FAR struct rpc_reply_lookup *)nmp->nm_iobuffer)->lookup;
/* Get the length of the file handle */
value = *ptr++;
value = fxdr_unsigned(uint32_t, value);
if (value > NFSX_V3FHMAX)
{
ferr("ERROR: Bad file handle length: %d\n", value);
return EIO;
}
/* Return the file handle */
fhandle->length = value;
memcpy(&fhandle->handle, ptr, value);
ptr += uint32_increment(value);
/* Check if there are object attributes and, if so, copy them to the user
* buffer
*/
value = *ptr++;
if (value)
{
if (obj_attributes)
{
memcpy(obj_attributes, ptr, sizeof(struct nfs_fattr));
}
ptr += uint32_increment(sizeof(struct nfs_fattr));
}
/* Check if there are directory attributes and, if so, copy them to the
* user buffer
*/
value = *ptr++;
if (value && dir_attributes)
{
memcpy(dir_attributes, ptr, sizeof(struct nfs_fattr));
}
return OK;
}
/****************************************************************************
* Name: nfs_findnode
*
* Description:
* Given a path to something that may or may not be in the file system,
* return the handle of the directory entry of the requested object.
*
* Returned Value:
* Zero on success; a positive errno value on failure.
*
****************************************************************************/
int nfs_findnode(struct nfsmount *nmp, FAR const char *relpath,
FAR struct file_handle *fhandle,
FAR struct nfs_fattr *obj_attributes,
FAR struct nfs_fattr *dir_attributes)
{
FAR const char *path = relpath;
char buffer[NAME_MAX + 1];
char terminator;
uint32_t tmp;
int error;
/* Start with the file handle of the root directory. */
fhandle->length = nmp->nm_fhsize;
memcpy(&fhandle->handle, &nmp->nm_fh, nmp->nm_fhsize);
/* If no path was provided, then the root directory must be exactly what
* the caller is looking for.
*/
if (*path == '\0' || strlen(path) == 0)
{
/* Return the root directory attributes */
if (obj_attributes)
{
memcpy(obj_attributes, &nmp->nm_fattr, sizeof(struct nfs_fattr));
}
if (dir_attributes)
{
memcpy(dir_attributes, &nmp->nm_fattr, sizeof(struct nfs_fattr));
}
return OK;
}
/* This is not the root directory. Loop until the directory entry corresponding
* to the path is found.
*/
for (; ; )
{
/* Extract the next path segment name. */
error = nfs_pathsegment(&path, buffer, &terminator);
if (error != OK)
{
/* The filename segment contains is too long. */
ferr("ERROR: nfs_pathsegment of \"%s\" failed after \"%s\": %d\n",
relpath, buffer, error);
return error;
}
/* Look-up this path segment */
error = nfs_lookup(nmp, buffer, fhandle, obj_attributes, dir_attributes);
if (error != OK)
{
ferr("ERROR: nfs_lookup of \"%s\" failed at \"%s\": %d\n",
relpath, buffer, error);
return error;
}
/* If the terminator character in the path was the end of the string
* then we have successfully found the directory entry that describes
* the path.
*/
if (!terminator)
{
/* Return success meaning that the description the matching
* directory entry is in fhandle, obj_attributes, and dir_attributes.
*/
return OK;
}
/* No.. then we have found one of the intermediate directories on
* the way to the final path target. In this case, make sure
* the thing that we found is, indeed, a directory.
*/
tmp = fxdr_unsigned(uint32_t, obj_attributes->fa_type);
if (tmp != NFDIR)
{
/* Ooops.. we found something else */
ferr("ERROR: Intermediate segment \"%s\" of \'%s\" is not a directory\n",
buffer, path);
return ENOTDIR;
}
}
}
/****************************************************************************
* Name: nfs_finddir
*
* Description:
* Given a path to something that may or may not be in the file system,
* return the handle of the entry of the directory containing the requested
* object.
*
* Returned Value:
* Zero on success; a positive errno value on failure.
*
****************************************************************************/
int nfs_finddir(struct nfsmount *nmp, FAR const char *relpath,
FAR struct file_handle *fhandle,
FAR struct nfs_fattr *attributes, FAR char *filename)
{
FAR const char *path = relpath;
uint32_t tmp;
char terminator;
int error;
/* Verify that a path was provided */
if (*path == '\0' || strlen(path) == 0)
{
/* Return the root directory attributes */
return ENOENT;
}
/* Start with the file handle of the root directory. */
fhandle->length = nmp->nm_fhsize;
memcpy(&fhandle->handle, &nmp->nm_fh, nmp->nm_fhsize);
memcpy(attributes, &nmp->nm_fattr, sizeof(struct nfs_fattr));
/* Loop until the directory entry containing the path is found. */
for (; ; )
{
/* Extract the next path segment name. */
error = nfs_pathsegment(&path, filename, &terminator);
if (error != OK)
{
/* The filename segment contains is too long. */
ferr("ERROR: nfs_pathsegment of \"%s\" failed after \"%s\": %d\n",
relpath, filename, error);
return error;
}
/* If the terminator character in the path was the end of the string
* then we have successfully found the directory that contains the name
* of interest.
*/
if (!terminator)
{
/* Return success meaning that the description of the directory
* containing the object is in fhandle and attributes.
*/
return OK;
}
/* Look-up the next path segment */
error = nfs_lookup(nmp, filename, fhandle, attributes, NULL);
if (error != OK)
{
ferr("ERROR: fs_lookup of \"%s\" failed at \"%s\": %d\n",
relpath, filename, error);
return error;
}
/* Make sure the thing that we found is, indeed, a directory. */
tmp = fxdr_unsigned(uint32_t, attributes->fa_type);
if (tmp != NFDIR)
{
/* Ooops.. we found something else */
ferr("ERROR: Intermediate segment \"%s\" of \'%s\" is not a directory\n",
filename, path);
return ENOTDIR;
}
}
}
/****************************************************************************
* Name: nfs_attrupdate
*
* Description:
* Update file attributes on write or after the file is modified.
*
* Returned Value:
* None.
*
****************************************************************************/
void nfs_attrupdate(FAR struct nfsnode *np, FAR struct nfs_fattr *attributes)
{
struct timespec ts;
/* Save a few of the files attribute values in file structure (host order) */
np->n_type = fxdr_unsigned(uint8_t, attributes->fa_type);
np->n_mode = fxdr_unsigned(uint16_t, attributes->fa_mode);
np->n_size = fxdr_hyper(&attributes->fa_size);
fxdr_nfsv3time(&attributes->fa_mtime, &ts);
np->n_mtime = ts.tv_sec;
fxdr_nfsv3time(&attributes->fa_ctime, &ts);
np->n_ctime = ts.tv_sec;
}
+3523
View File
File diff suppressed because it is too large Load Diff
Executable
+566
View File
@@ -0,0 +1,566 @@
/****************************************************************************
* fs/nfs/rpc.h
*
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved.
* Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com>
* Gregory Nutt <gnutt@nuttx.org>
*
* Leveraged from OpenBSD:
*
* copyright (c) 2003
* the regents of the university of michigan
* all rights reserved
*
* permission is granted to use, copy, create derivative works and redistribute
* this software and such derivative works for any purpose, so long as the name
* of the university of michigan is not used in any advertising or publicity
* pertaining to the use or distribution of this software without specific,
* written prior authorization. if the above copyright notice or any other
* identification of the university of michigan is included in any copy of any
* portion of this software, then the disclaimer below must also be included.
*
* this software is provided as is, without representation from the university
* of michigan as to its fitness for any purpose, and without warranty by the
* university of michigan of any kind, either express or implied, including
* without limitation the implied warranties of merchantability and fitness for
* a particular purpose. the regents of the university of michigan shall not be
* liable for any damages, including special, indirect, incidental, or
* consequential damages, with respect to any claim arising out of or in
* connection with the use of the software, even if it has been or is hereafter
* advised of the possibility of such damages.
*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Rick Macklem at The University of Guelph.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
****************************************************************************/
#ifndef __FS_NFS_RPC_H
#define __FS_NFS_RPC_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/types.h>
#include <securec.h>
#include <netinet/in.h>
#include "nfs_proto.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Version # */
#define RPC_VER2 2
/* Authentication */
#define RPCAUTH_NULL 0
#define RPCAUTH_UNIX 1
#define RPCAUTH_SHORT 2
#define RPCAUTH_KERB4 4
#define RPCAUTH_MAXSIZ 400
#define RPCVERF_MAXSIZ 12
/* For Kerb, can actually be 400 */
#define RPCAUTH_UNIXGIDS 16
#define NFS_IPPROTO_TCP 6
#define NFS_IPPROTO_UDP 17
#define NFS_PROTO_TYPE NFS_IPPROTO_TCP
#if (NFS_PROTO_TYPE == NFS_IPPROTO_TCP)
#define NFS_PROTOTYPE IPPROTO_TCP /* Default protocol to provide */
#elif (NFS_PROTO_TYPE == NFS_IPPROTO_UDP)
#define NFS_PROTOTYPE IPPROTO_UDP
#endif
/* There is an argument we can set in nfs server influences the port number we can use.
* When it is "secure", nfs use port number under 1024.
* When it is "insecure", nfs use port number over 1024.
* And "secure" is default.
*/
#define RPCCONN_MAXPORT 1023
#define RPCCONN_MINPORT 256
/* Constants associated with authentication flavours. */
#define RPCAKN_FULLNAME 0
#define RPCAKN_NICKNAME 1
/* RPC Constants */
#define RPC_CALL 0
#define RPC_REPLY 1
#define RPC_MSGACCEPTED 0
#define RPC_MSGDENIED 1
#define RPC_PROGUNAVAIL 1
#define RPC_PROGMISMATCH 2
#define RPC_PROCUNAVAIL 3
#define RPC_GARBAGE 4
#define RPC_MISMATCH 0
#define RPC_AUTHERR 1
/* Authentication failures */
#define AUTH_BADCRED 1
#define AUTH_REJECTCRED 2
#define AUTH_BADVERF 3
#define AUTH_REJECTVERF 4
#define AUTH_TOOWEAK 5
/* Sizes of RPC header parts */
#define RPC_SIZ 24
#define RPC_REPLYSIZ 28
#define RPC_RPATH_MAXSIZE NFS_MOUNT_PATH_MAX_SIZE
#if (NFS_PROTO_TYPE == NFS_IPPROTO_TCP)
#define RPC_RMSIZE 4
#define RPC_RM_FLAGMENT_LAST_FLAG 0x80000000
#define RPC_RM_FLAGMENT_LEN_MASK 0x7FFFFFFF
#elif (NFS_PROTO_TYPE == NFS_IPPROTO_UDP)
#define RPC_RMSIZE 0
#endif
/* RPC Prog definitions */
#define RPCPROG_MNT 100005
#define RPCMNT_VER1 1
#define RPCMNT_VER3 3
#define RPCMNT_MOUNT 1
#define RPCMNT_DUMP 2
#define RPCMNT_UMOUNT 3
#define RPCMNT_UMNTALL 4
#define RPCMNT_EXPORT 5
#define RPCMNT_NAMELEN 255
#define RPCMNT_PATHLEN 1024
#define RPCPROG_NFS 100003
/* RPC definitions for the portmapper. */
#define PMAPPORT 111
#define PMAPPROG 100000
#define PMAPVERS 2
#define PMAPPROC_NULL 0
#define PMAPPROC_SET 1
#define PMAPPROC_UNSET 2
#define PMAPPROC_GETPORT 3
#define PMAPPROC_DUMP 4
#define PMAPPROC_CALLIT 5
#define RPC_SUCCESS 0
/****************************************************************************
* Public Types
****************************************************************************/
/* Global RPC statistics */
#ifdef CONFIG_NFS_STATISTICS
struct rpcstats
{
int rpcretries;
int rpcrequests;
int rpctimeouts;
int rpcinvalid;
};
#endif
/* PMAP headers */
struct call_args_pmap
{
uint32_t prog;
uint32_t vers;
uint32_t proc;
uint32_t port;
};
struct call_result_pmap
{
uint32_t port;
};
/* MOUNTD headers */
struct call_args_mount
{
uint32_t len;
char rpath[RPC_RPATH_MAXSIZE];
};
struct call_args_umount
{
uint32_t len;
char rpath[RPC_RPATH_MAXSIZE];
};
/* Generic RPC call headers */
enum auth_flavor
{
AUTH_NONE = 0,
AUTH_SYS = 1,
AUTH_SHORT = 2,
AUTH_DES = 3,
AUTH_MAX
/* and more to be defined */
};
struct call_result_mount
{
uint32_t status;
struct file_handle fhandle;
uint32_t authlen;
uint32_t autolist[AUTH_MAX];
};
/* Generic RPC call headers */
struct rpc_auth_info
{
uint32_t authtype; /* auth type */
uint32_t authlen; /* auth length */
};
struct auth_unix
{
uint32_t stamp;
uint32_t hostname_len;
/* use n uint32_t(s) to store CONFIG_NFS_MACHINE_NAME_SIZE bytes */
uint32_t hostname[(CONFIG_NFS_MACHINE_NAME_SIZE + sizeof(uint32_t) - 1) / sizeof(uint32_t)];
uint32_t uid;
uint32_t gid;
uint32_t gidlist;
uint32_t gidlist_value;
};
struct rpc_call_header
{
#if (NFS_PROTO_TYPE == NFS_IPPROTO_TCP)
uint32_t rp_recmark; /* fragment header */
#endif
uint32_t rp_xid; /* request transaction id */
int32_t rp_direction; /* call direction (0) */
uint32_t rp_rpcvers; /* RPC version (2) */
uint32_t rp_prog; /* program */
uint32_t rp_vers; /* version */
uint32_t rp_proc; /* procedure */
struct rpc_auth_info rpc_auth;
struct auth_unix rpc_auth_unix;
struct rpc_auth_info rpc_verf;
};
struct rpc_call_pmap
{
struct rpc_call_header ch;
struct call_args_pmap pmap;
};
struct rpc_call_mount
{
struct rpc_call_header ch;
struct call_args_mount mount;
};
struct rpc_call_umount
{
struct rpc_call_header ch;
struct call_args_umount umount;
};
struct rpc_call_create
{
struct rpc_call_header ch;
struct CREATE3args create;
};
struct rpc_call_lookup
{
struct rpc_call_header ch;
struct LOOKUP3args lookup;
};
#define SIZEOF_rpc_call_lookup(n) (sizeof(struct rpc_call_header) + SIZEOF_LOOKUP3args(n))
struct rpc_call_read
{
struct rpc_call_header ch;
struct READ3args read;
};
struct rpc_call_write
{
struct rpc_call_header ch;
struct WRITE3args write; /* Variable length */
};
#define SIZEOF_rpc_call_write(n) (sizeof(struct rpc_call_header) + SIZEOF_WRITE3args(n))
struct rpc_call_remove
{
struct rpc_call_header ch;
struct REMOVE3args remove;
};
struct rpc_call_rename
{
struct rpc_call_header ch;
struct RENAME3args rename;
};
struct rpc_call_mkdir
{
struct rpc_call_header ch;
struct MKDIR3args mkdir;
};
struct rpc_call_rmdir
{
struct rpc_call_header ch;
struct RMDIR3args rmdir;
};
struct rpc_call_readdir
{
struct rpc_call_header ch;
struct READDIR3args readdir;
};
struct rpc_call_setattr
{
struct rpc_call_header ch;
struct SETATTR3args setattr;
};
struct rpc_call_fs
{
struct rpc_call_header ch;
struct FS3args fs;
};
/* Generic RPC reply headers */
struct rpc_reply_header
{
#if (NFS_PROTO_TYPE == NFS_IPPROTO_TCP)
uint32_t rp_recmark; /* fragment header */
#endif
uint32_t rp_xid; /* Request transaction id */
uint32_t rp_direction; /* Call direction (1) */
uint32_t type;
struct rpc_auth_info rpc_verfi;
uint32_t status;
};
struct nfs_reply_header
{
#if (NFS_PROTO_TYPE == NFS_IPPROTO_TCP)
uint32_t rp_recmark; /* fragment header */
#endif
uint32_t rp_xid; /* Request transaction id */
uint32_t rp_direction; /* Call direction (1) */
uint32_t type;
struct rpc_auth_info rpc_verfi;
uint32_t status;
uint32_t nfs_status;
};
struct rpc_reply_pmap
{
struct rpc_reply_header rh;
struct call_result_pmap pmap;
};
struct rpc_reply_mount
{
struct rpc_reply_header rh;
struct call_result_mount mount;
};
struct rpc_reply_umount
{
struct rpc_reply_header rh;
};
struct rpc_reply_create
{
struct rpc_reply_header rh;
uint32_t status;
struct CREATE3resok create;
};
struct rpc_reply_lookup
{
struct rpc_reply_header rh;
uint32_t status;
struct LOOKUP3resok lookup;
};
struct rpc_reply_write
{
struct rpc_reply_header rh;
uint32_t status;
struct WRITE3resok write; /* Variable length */
};
struct rpc_reply_read
{
struct rpc_reply_header rh;
uint32_t status;
struct READ3resok read; /* Variable length */
};
#define SIZEOF_rpc_reply_read(n) \
(sizeof(struct rpc_reply_header) + sizeof(uint32_t) + \
SIZEOF_READ3resok(n))
struct rpc_reply_remove
{
struct rpc_reply_header rh;
uint32_t status;
struct REMOVE3resok remove;
};
struct rpc_reply_rename
{
struct rpc_reply_header rh;
uint32_t status;
struct RENAME3resok rename;
};
struct rpc_reply_mkdir
{
struct rpc_reply_header rh;
uint32_t status;
struct MKDIR3resok mkdir;
};
struct rpc_reply_rmdir
{
struct rpc_reply_header rh;
uint32_t status;
struct RMDIR3resok rmdir;
};
struct rpc_reply_readdir
{
struct rpc_reply_header rh;
uint32_t status;
struct READDIR3resok readdir;
};
#define SIZEOF_rpc_reply_readdir(n) \
(sizeof(struct rpc_reply_header) + sizeof(uint32_t) + \
SIZEOF_READDIR3resok(n))
struct rpc_reply_fsinfo
{
struct rpc_reply_header rh;
uint32_t status;
struct nfsv3_fsinfo fsinfo;
};
struct rpc_reply_fsstat
{
struct rpc_reply_header rh;
uint32_t status;
struct nfs_statfs fsstat;
};
struct rpc_reply_getattr
{
struct rpc_reply_header rh;
uint32_t status;
struct nfs_fattr attr;
};
struct rpc_reply_setattr
{
struct rpc_reply_header rh;
uint32_t status;
struct SETATTR3resok setattr;
};
struct rpcclnt
{
nfsfh_t rc_fh; /* File handle of the root directory */
unsigned int rc_fhsize; /* File size of the root directory */
char *rc_path; /* Server's path of the mounted directory */
uint32_t xid;
struct sockaddr *rc_name;
int rc_so; /* RPC socket */
bool rc_timeout; /* Receipt of reply timed out */
uint8_t rc_sotype; /* Type of socket */
uint8_t rc_retry; /* Max retries */
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
void rpcclnt_init(void);
int rpcclnt_connect(FAR struct rpcclnt *rpc);
void rpcclnt_disconnect(FAR struct rpcclnt *rpc);
int rpcclnt_umount(FAR struct rpcclnt *rpc);
void rpcclnt_safedisconnect(FAR struct rpcclnt *rpc);
int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog, int version,
FAR void *request, size_t reqlen,
FAR void *response, size_t resplen);
void rpcclnt_setuidgid(uint32_t uid, uint32_t gid);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __FS_NFS_RPC_H */
+1132
View File
File diff suppressed because it is too large Load Diff
+140
View File
@@ -0,0 +1,140 @@
/****************************************************************************
* fs/nfs/xdr_subs.h
* Definitions for Sun RPC Version 2, from
* "RPC: Remote Procedure Call Protocol Specification" RFC1057
*
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved.
* Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com>
* Gregory Nutt <gnutt@nuttx.org>
*
* Leveraged from OpenBSD:
*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Rick Macklem at The University of Guelph.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
****************************************************************************/
#ifndef __FS_NFS_XDR_SUBS_H
#define __FS_NFS_XDR_SUBS_H
/****************************************************************************
* Included Files
****************************************************************************/
#include "lwip/sockets.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Macros used for conversion to/from xdr representation by nfs...
* These use the MACHINE DEPENDENT routines ntohl, htonl
* As defined by "XDR: External Data Representation Standard" RFC1014
*
* To simplify the implementation, we use ntohl/htonl even on big-endian
* machines, and count on them being `#define'd away. Some of these
* might be slightly more efficient as int64_t copies on a big-endian,
* but we cannot count on their alignment anyway.
*/
#define fxdr_unsigned(t, v) ((t)ntohl(v))
#define txdr_unsigned(v) (htonl(v))
#define fxdr_nfsv2time(f, t) \
{ \
(t)->tv_sec = ntohl(((struct nfsv2_time *)(f))->nfsv2_sec); \
if (((struct nfsv2_time *)(f))->nfsv2_usec != 0xffffffff) \
(t)->tv_nsec = 1000 * ntohl(((struct nfsv2_time *)(f))->nfsv2_usec); \
else \
(t)->tv_nsec = 0; \
}
#define txdr_nfsv2time(f, t) \
{ \
((struct nfsv2_time *)(t))->nfsv2_sec = htonl((f)->tv_sec); \
if ((f)->tv_nsec != -1) \
((struct nfsv2_time *)(t))->nfsv2_usec = htonl((f)->tv_nsec / 1000); \
else \
((struct nfsv2_time *)(t))->nfsv2_usec = 0xffffffff; \
}
#define fxdr_nfsv3time(f, t) \
{ \
(t)->tv_sec = ntohl(((struct nfsv3_time *)(f))->nfsv3_sec); \
(t)->tv_nsec = ntohl(((struct nfsv3_time *)(f))->nfsv3_nsec); \
}
#define fxdr_nfsv3time2(f, t) { \
(t)->nfsv3_sec = ntohl(((struct nfsv3_time *)(f))->nfsv3_sec); \
(t)->nfsv3_nsec = ntohl(((struct nfsv3_time *)(f))->nfsv3_nsec); \
}
#define txdr_nfsv3time(f, t) \
{ \
((struct nfsv3_time *)(t))->nfsv3_sec = htonl((f)->tv_sec); \
((struct nfsv3_time *)(t))->nfsv3_nsec = htonl((f)->tv_nsec); \
}
#define txdr_nfsv3time2(f, t) \
{ \
((struct nfsv3_time *)(t))->nfsv3_sec = htonl((f)->nfsv3_sec); \
((struct nfsv3_time *)(t))->nfsv3_nsec = htonl((f)->nfsv3_nsec); \
}
#define fxdr_hyper(f) \
((((uint64_t)ntohl(((uint32_t *)(f))[0])) << 32) | \
(uint64_t)(ntohl(((uint32_t *)(f))[1])))
#define txdr_hyper(f, t) \
{ \
((uint32_t *)(t))[0] = htonl((uint32_t)((f) >> 32)); \
((uint32_t *)(t))[1] = htonl((uint32_t)((f) & 0xffffffff)); \
}
/* Macros for dealing with byte data saved in uint32_t aligned memory */
#define uint32_aligndown(b) ((b) & ~3)
#define uint32_alignup(b) (((b) + 3) & ~3)
#define uint32_increment(b) (((b) + 3) >> 2)
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __FS_NFS_XDR_SUBS_H */
+2390
View File
File diff suppressed because it is too large Load Diff
+214
View File
@@ -0,0 +1,214 @@
/****************************************************************************
* fs/tmpfs/fs_tmpfs.h
*
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __FS_TMPFS_FS_TMPFS_H
#define __FS_TMPFS_FS_TMPFS_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <semaphore.h>
#include "fs/fs.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#ifdef LOSCFG_FS_RAMFS
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Indicates that there is no holder of the re-entrant semaphore */
#define TMPFS_NO_HOLDER -1
/* Bit definitions for file object flags */
#define TFO_FLAG_UNLINKED (1 << 0) /* Bit 0: File is unlinked */
/****************************************************************************
* Public Types
****************************************************************************/
/* TMPFS memory object types */
enum tmpfs_objtype_e
{
TMPFS_DIRECTORY = 0, /* Directory */
TMPFS_REGULAR /* Regular file */
};
/* Values returned by tmpfs_foreach() */
enum tmpfs_foreach_e
{
TMPFS_CONTINUE = 0, /* Continue enumeration */
TMPFS_HALT, /* Stop enumeration */
TMPFS_DELETED, /* Object and directory entry deleted */
TMPFS_UNLINKED /* Only the directory entry was deleted */
};
/* Re-entrant semaphore */
struct tmpfs_sem_s
{
sem_t ts_sem; /* The actual semaphore */
pid_t ts_holder; /* Current older (-1 if not held) */
uint16_t ts_count; /* Number of counts held */
};
/* The form of one directory entry */
struct tmpfs_dirent_s
{
LOS_DL_LIST tde_node;
FAR struct tmpfs_object_s *tde_object;
FAR char *tde_name;
bool tde_inuse;
};
/* The generic form of a TMPFS memory object */
struct tmpfs_object_s
{
FAR struct tmpfs_dirent_s *to_dirent;
struct tmpfs_sem_s to_exclsem;
uint8_t to_type; /* See enum tmpfs_objtype_e */
uint8_t to_refs; /* Reference count */
time_t to_ctime; /* last changed status time */
time_t to_mtime; /* last modified time */
time_t to_atime; /* last access time */
};
/* The form of a directory memory object */
struct tmpfs_directory_s
{
/* First fields must match common TMPFS object layout */
FAR struct tmpfs_dirent_s *tdo_dirent;
struct tmpfs_sem_s tdo_exclsem;
uint8_t tdo_type; /* See enum tmpfs_objtype_e */
uint8_t tdo_refs; /* Reference count */
time_t tdo_ctime; /* last changed status time */
time_t tdo_mtime; /* last modified time */
time_t tdo_atime; /* last access time */
/* Remaining fields are unique to a directory object */
uint8_t tdo_count; /* Number of times the directory was opened */
uint16_t tdo_nentries; /* Number of directory entries */
LOS_DL_LIST tdo_entry;
};
#define SIZEOF_TMPFS_DIRECTORY(n) \
(sizeof(struct tmpfs_directory_s) + ((n) - 1) * sizeof(struct tmpfs_dirent_s))
/* The form of a regular file memory object
*
* NOTE that in this very simplified implementation, there is no per-open
* state. The file memory object also serves as the open file object,
* saving an allocation. This has the negative side effect that no per-
* open state can be retained (such as open flags).
*/
struct tmpfs_file_s
{
/* First fields must match common TMPFS object layout */
FAR struct tmpfs_dirent_s *tfo_dirent;
struct tmpfs_sem_s tfo_exclsem;
uint8_t tfo_type; /* See enum tmpfs_objtype_e */
uint8_t tfo_refs; /* Reference count */
time_t tfo_ctime; /* last changed status time */
time_t tfo_mtime; /* last modified time */
time_t tfo_atime; /* last access time */
/* Remaining fields are unique to a directory object */
uint8_t tfo_flags; /* See TFO_FLAG_* definitions */
size_t tfo_size; /* Valid file size */
char *tfo_data; /* File data pointer */
};
#define SIZEOF_TMPFS_FILE(n) (sizeof(struct tmpfs_file_s) + (n) - 1)
/* This structure represents one instance of a TMPFS file system */
struct tmpfs_s
{
/* The root directory */
FAR struct tmpfs_dirent_s tfs_root;
struct tmpfs_sem_s tfs_exclsem;
};
/* This is the type used the tmpfs_statfs_callout to accumulate memory usage */
struct tmpfs_statfs_s
{
size_t tsf_alloc; /* Total memory allocated */
size_t tsf_inuse; /* Total memory in use */
off_t tsf_files; /* Total file nodes in the file system */
off_t tsf_ffree; /* Free directory nodes in the file system */
};
/* This is the type of the for tmpfs_foreach callback */
typedef int (*tmpfs_foreach_t)(FAR struct tmpfs_directory_s *tdo,
unsigned int index, FAR void *arg);
/****************************************************************************
* Public Data
****************************************************************************/
extern void los_set_ramfs_unit(off_t size);
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __FS_TMPFS_FS_TMPFS_H */
+132
View File
@@ -0,0 +1,132 @@
/****************************************************************************
* fs/vfs/fs_close.c
*
* Copyright (C) 2007-2009, 2012, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "errno.h"
#include "unistd.h"
#include "sched.h"
#include "fs/fs.h"
#if defined(LOSCFG_NET_LWIP_SACK)
# include "net/net.h"
#endif
#include "inode/inode.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: close
*
* Description:
* close() closes a file descriptor, so that it no longer refers to any
* file and may be reused. Any record locks (see fcntl(2)) held on the file
* it was associated with, and owned by the process, are removed (regardless
* of the file descriptor that was used to obtain the lock).
*
* If fd is the last copy of a particular file descriptor the resources
* associated with it are freed; if the descriptor was the last reference
* to a file which has been removed using unlink(2) the file is deleted.
*
* Input Parameters:
* fd file descriptor to close
*
* Returned Value:
* 0 on success; -1 on error with errno set appropriately.
*
* Assumptions:
*
****************************************************************************/
int close(int fd)
{
int err;
#if CONFIG_NFILE_DESCRIPTORS > 0
int ret;
/* Did we get a valid file descriptor? */
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
#endif
{
/* Close a socket descriptor */
#if defined(LOSCFG_NET_LWIP_SACK)
if ((unsigned int)fd < (unsigned int)(CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS))
{
return socks_close(fd);
}
else
#endif
{
err = EBADF;
goto errout;
}
}
#if CONFIG_NFILE_DESCRIPTORS > 0
/* Close the driver or mountpoint. NOTES: (1) there is no
* exclusion mechanism here, the driver or mountpoint must be
* able to handle concurrent operations internally, (2) The driver
* may have been opened numerous times (for different file
* descriptors) and must also handle being closed numerous times.
* (3) for the case of the mountpoint, we depend on the close
* methods bing identical in signature and position in the operations
* vtable.
*/
ret = files_close(fd);
if (ret < 0)
{
/* An error occurred while closing the driver */
err = -ret;
goto errout;
}
return OK;
#endif
errout:
set_errno(err);
return VFS_ERROR;
}
+111
View File
@@ -0,0 +1,111 @@
/****************************************************************************
* fs/vfs/fs_dup.c
*
* Copyright (C) 2007-2009, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "errno.h"
#include "unistd.h"
#include "sched.h"
#include "fs/fs.h"
#include "inode/inode.h"
#include "net/net.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: dup
*
* Description:
* Clone a file or socket descriptor to an arbitray descriptor number
*
****************************************************************************/
int dup(int fd)
{
int ret = OK;
/* Check the range of the descriptor to see if we got a file or a socket
* descriptor.
*/
#if CONFIG_NFILE_DESCRIPTORS > 0
if ((unsigned int)fd < CONFIG_NFILE_DESCRIPTORS)
{
/* 0,1,2 fd is not opened in system, no need to dup them, return fd directly */
if ((fd >= STDIN_FILENO) && (fd <= STDERR_FILENO))
{
return fd;
}
/* Its a valid file descriptor.. dup the file descriptor using any
* other file descriptor. fd_dupfd() sets the errno value in the
* event of any failures.
*/
ret = fs_dupfd(fd, 3); /* 3: file start fd */
}
else
#endif
{
/* Not a valid file descriptor. Did we get a valid socket descriptor? */
#if defined(LOSCFG_NET_LWIP_SACK)
if ((unsigned int)fd < (unsigned int)(CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS))
{
/* Yes.. dup the socket descriptor. The errno value is not set. */
set_errno(EBADF); /* When net_dupsd is still closed,errno should set */
ret = VFS_ERROR;
}
else
#endif
{
/* No.. then it is a bad descriptor number */
set_errno(EBADF);
ret = VFS_ERROR;
}
}
return ret;
}
+104
View File
@@ -0,0 +1,104 @@
/****************************************************************************
* fs/vfs/fs_dup2.c
*
* Copyright (C) 2007-2009, 2011, 2013, 2017 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "errno.h"
#include "unistd.h"
#include "sched.h"
#include "inode/inode.h"
/* This logic in this applies only when both socket and file descriptors are
* in that case, this function descriminates which type of dup2 is being
* performed.
*/
#if CONFIG_NFILE_DESCRIPTORS > 0 && defined(LOSCFG_NET_LWIP_SACK)
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: dup2
*
* Description:
* Clone a file descriptor or socket descriptor to a specific descriptor
* number
*
****************************************************************************/
int dup2(int fd1, int fd2)
{
/* Check the range of the descriptor to see if we got a file or a socket
* descriptor.
*/
if ((unsigned int)fd1 >= CONFIG_NFILE_DESCRIPTORS)
{
/* Not a valid file descriptor. Did we get a valid socket descriptor? */
if ((unsigned int)fd1 < (unsigned int)(CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS))
{
/* Yes.. dup the socket descriptor. The errno value is not set. */
set_errno(EBADF); /* When net_dupsd2 is still closed,errno should set */
return VFS_ERROR; /* LWIP not support */
}
else
{
/* No.. then it is a bad descriptor number */
set_errno(EBADF);
return VFS_ERROR;
}
}
else
{
/* Its a valid file descriptor.. dup the file descriptor. fd_dupfd()
* sets the errno value in the event of any failures.
*/
return fs_dupfd2(fd1, fd2);
}
}
#endif /* CONFIG_NFILE_DESCRIPTORS > 0 ... */
+194
View File
@@ -0,0 +1,194 @@
/****************************************************************************
* fs/vfs/fs_dupfd.c
*
* Copyright (C) 2007-2009, 2011-2014, 2017 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "assert.h"
#include "errno.h"
#include "sched.h"
#include "fs/fs.h"
#include "fs/file.h"
#include "inode/inode.h"
#include "stdlib.h"
#include "string.h"
#if CONFIG_NFILE_DESCRIPTORS > 0
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: file_dup
*
* Description:
* Equivalent to the non-standard fs_dupfd() function except that it
* accepts a struct file instance instead of a file descriptor and does
* not set the errno variable.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned on
* any failure.
*
****************************************************************************/
int file_dup(FAR struct file *filep, int minfd)
{
int fd2;
int ret;
int err,len;
struct file *filep2 = NULL;
char *fullpath = NULL;
const char *relpath = NULL;
struct inode_search_s desc;
/* Verify that fd is a valid, open file descriptor */
if ((filep->f_inode == NULL) || (filep->f_path == NULL))
{
set_errno(EBADF);
return VFS_ERROR;
}
len = strlen(filep->f_path);
fullpath = (char *)zalloc(len + 1);
if (fullpath == NULL)
{
set_errno(ENOMEM);
return VFS_ERROR;
}
/* Then allocate a new file descriptor for the inode */
fd2 = files_allocate(filep->f_inode, filep->f_oflags, filep->f_pos, filep->f_priv, minfd);
if (fd2 < 0)
{
inode_release(filep->f_inode);
free(fullpath);
set_errno(EMFILE);
return VFS_ERROR;
}
ret = fs_getfilep(fd2, &filep2);
(void)strncpy_s(fullpath, len + 1, filep->f_path, len);
SETUP_SEARCH(&desc, fullpath, false);
if (inode_find(&desc) < 0)
{
ret = -EACCES;
goto errout_with_inode;
}
relpath = desc.relpath;
filep2->f_path = fullpath;
filep2->f_relpath = relpath;
if (filep->f_inode->u.i_mops && filep->f_inode->u.i_mops->dup)
{
ret = filep->f_inode->u.i_mops->dup(filep, filep2);
}
else
{
ret = -ENOSYS;
}
if (ret < 0)
{
goto errout_with_inode;
}
return fd2;
errout_with_inode:
clear_fd(fd2);
inode_release(filep2->f_inode);
free(fullpath);
filep2->f_oflags = 0;
filep2->f_pos = 0;
filep2->f_inode = NULL;
filep2->f_priv = NULL;
filep2->f_path = NULL;
filep2->f_relpath = NULL;
filep2->f_mapping = NULL;
err = -ret;
set_errno(err);
return VFS_ERROR;
}
/****************************************************************************
* Name: fs_dupfd OR dup
*
* Description:
* Clone a file descriptor 'fd' to an arbitray descriptor number (any value
* greater than or equal to 'minfd'). If socket descriptors are
* implemented, then this is called by dup() for the case of file
* descriptors. If socket descriptors are not implemented, then this
* function IS dup().
*
* Returned Value:
* fs_dupfd is sometimes an OS internal function and sometimes is a direct
* substitute for dup(). So it must return an errno value as though it
* were dup().
*
****************************************************************************/
int fs_dupfd(int fd, int minfd)
{
FAR struct file *filep;
/* Get the file structure corresponding to the file descriptor. */
int ret = fs_getfilep(fd, &filep);
if (ret < 0)
{
/* The errno value has already been set */
return VFS_ERROR;
}
/* Let file_dup() do the real work */
return file_dup(filep, minfd);
}
#endif /* CONFIG_NFILE_DESCRIPTORS > 0 */
+132
View File
@@ -0,0 +1,132 @@
/****************************************************************************
* fs/vfs/fs_dupfd2.c
*
* Copyright (C) 2007-2009, 2011-2014, 2017 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "errno.h"
#include "unistd.h"
#include "sched.h"
#include "inode/inode.h"
#if CONFIG_NFILE_DESCRIPTORS > 0
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: fs_dupfd2 OR dup2
*
* Description:
* Clone a file descriptor to a specific descriptor number. If socket
* descriptors are implemented, then this is called by dup2() for the
* case of file descriptors. If socket descriptors are not implemented,
* then this function IS dup2().
*
* Returned Value:
* fs_dupfd is sometimes an OS internal function and sometimes is a direct
* substitute for dup2(). So it must return an errno value as though it
* were dup2().
*
****************************************************************************/
#if defined(LOSCFG_NET_LWIP_SACK)
int fs_dupfd2(int fd1, int fd2)
#else
int dup2(int fd1, int fd2)
#endif
{
FAR struct file *filep1;
FAR struct file *filep2;
int ret;
/* Get the file structures corresponding to the file descriptors. */
ret = fs_getfilep(fd1, &filep1);
if (ret >= 0)
{
ret = fs_getfilep(fd2, &filep2);
}
if (ret < 0)
{
/* The errno value has already been set */
return VFS_ERROR;
}
/* Verify that fd1 is a valid, open file descriptor */
if (filep1->f_inode == NULL)
{
set_errno(EBADF);
return VFS_ERROR;
}
/* Handle a special case */
if (fd1 == fd2)
{
return fd1;
}
/* Perform the dup2 operation */
if (!file_dup2(filep1, filep2))
{
return fd2;
}
else
{
clear_fd(fd2);
return VFS_ERROR;
}
}
#endif /* CONFIG_NFILE_DESCRIPTORS > 0 */
+378
View File
@@ -0,0 +1,378 @@
/****************************************************************************
* fs/vfs/fs_fcntl.c
*
* Copyright (C) 2009, 2012-2014, 2016-2017 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "stdarg.h"
#include "fcntl.h"
#include "errno.h"
#include "assert.h"
#include "fs/fs.h"
#include "inode/inode.h"
#if defined(LOSCFG_NET_LWIP_SACK)
#include "lwip/sockets.h"
#endif
#define FAPPEND O_APPEND
#define FFSYNC O_SYNC
#define FNONBLOCK O_NONBLOCK
#define FNDELAY O_NDELAY
#define FFCNTL (FNONBLOCK | FNDELAY | FAPPEND | FFSYNC | FASYNC)
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: file_vfcntl
*
* Description:
* Similar to the standard vfcntl function except that is accepts a struct
* struct file instance instead of a file descriptor.
*
* Input Parameters:
* filep - Instance for struct file for the opened file.
* cmd - Indentifies the operation to be performed.
* ap - Variable argument following the command.
*
* Returned Value:
* The nature of the return value depends on the command. Non-negative
* values indicate success. Failures are reported as negated errno
* values.
*
****************************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
int file_vfcntl(FAR struct file *filep, int cmd, va_list ap)
{
int err = 0;
int ret = OK;
/* Was this file opened ? */
if (!filep || !filep->f_inode)
{
err = EBADF;
goto errout;
}
switch (cmd)
{
case F_DUPFD:
/* Return a new file descriptor which shall be the lowest numbered
* available (that is, not already open) file descriptor greater than
* or equal to the third argument, arg, taken as an integer of type
* int. The new file descriptor shall refer to the same open file
* description as the original file descriptor, and shall share any
* locks. The FD_CLOEXEC flag associated with the new file descriptor
* shall be cleared to keep the file open across calls to one of the
* exec functions.
*/
{
/* Does not set the errno variable in the event of a failure */
ret = file_dup(filep, va_arg(ap, int));
}
break;
case F_GETFD:
/* Get the file descriptor flags defined in <fcntl.h> that are associated
* with the file descriptor fd. File descriptor flags are associated
* with a single file descriptor and do not affect other file descriptors
* that refer to the same file.
*/
case F_SETFD:
/* Set the file descriptor flags defined in <fcntl.h>, that are associated
* with fd, to the third argument, arg, taken as type int. If the
* FD_CLOEXEC flag in the third argument is 0, the file shall remain open
* across the exec functions; otherwise, the file shall be closed upon
* successful execution of one of the exec functions.
*/
err = ENOSYS;
break;
case F_GETFL:
/* Get the file status flags and file access modes, defined in
* <fcntl.h>, for the file description associated with fd. The file
* access modes can be extracted from the return value using the
* mask O_ACCMODE, which is defined in <fcntl.h>. File status flags
* and file access modes are associated with the file description
* and do not affect other file descriptors that refer to the same
* file with different open file descriptions.
*/
{
ret = filep->f_oflags;
}
break;
case F_SETFL:
/* Set the file status flags, defined in <fcntl.h>, for the file
* description associated with fd from the corresponding bits in
* the third argument, arg, taken as type int. Bits corresponding
* to the file access mode and the file creation flags, as defined
* in <fcntl.h>, that are set in arg shall be ignored. If any bits
* in arg other than those mentioned here are changed by the
* application, the result is unspecified.
*/
{
int oflags = va_arg(ap, int);
oflags &= FFCNTL;
filep->f_oflags &= ~FFCNTL;
filep->f_oflags |= oflags;
}
break;
case F_GETOWN:
/* If fd refers to a socket, get the process or process group ID
* specified to receive SIGURG signals when out-of-band data is
* available. Positive values indicate a process ID; negative
* values, other than -1, indicate a process group ID. If fd does
* not refer to a socket, the results are unspecified.
*/
case F_SETOWN:
/* If fd refers to a socket, set the process or process group ID
* specified to receive SIGURG signals when out-of-band data is
* available, using the value of the third argument, arg, taken as
* type int. Positive values indicate a process ID; negative values,
* other than -1, indicate a process group ID. If fd does not refer
* to a socket, the results are unspecified.
*/
err = EBADF; /* Only valid on socket descriptors */
break;
case F_GETLK:
/* Get the first lock which blocks the lock description pointed to
* by the third argument, arg, taken as a pointer to type struct
* flock, defined in <fcntl.h>. The information retrieved shall
* overwrite the information passed to fcntl() in the structure
* flock. If no lock is found that would prevent this lock from
* being created, then the structure shall be left unchanged except
* for the lock type which shall be set to F_UNLCK.
*/
case F_SETLK:
/* Set or clear a file segment lock according to the lock
* description pointed to by the third argument, arg, taken as a
* pointer to type struct flock, defined in <fcntl.h>. F_SETLK can
* establish shared (or read) locks (F_RDLCK) or exclusive (or
* write) locks (F_WRLCK), as well as to remove either type of lock
* (F_UNLCK). F_RDLCK, F_WRLCK, and F_UNLCK are defined in
* <fcntl.h>. If a shared or exclusive lock cannot be set, fcntl()
* shall return immediately with a return value of -1.
*/
case F_SETLKW:
/* This command shall be equivalent to F_SETLK except that if a
* shared or exclusive lock is blocked by other locks, the thread
* shall wait until the request can be satisfied. If a signal that
* is to be caught is received while fcntl() is waiting for a
* region, fcntl() shall be interrupted. Upon return from the signal
* handler, fcntl() shall return -1 with errno set to [EINTR], and
* the lock operation shall not be done.
*/
err = ENOSYS; /* Not implemented */
break;
default:
err = EINVAL;
break;
}
errout:
if (err != 0)
{
set_errno(err);
return VFS_ERROR;
}
return ret;
}
#endif /* CONFIG_NFILE_DESCRIPTORS > 0 */
/****************************************************************************
* Name: fcntl
*
* Description:
* fcntl() will perform the operation specified by 'cmd' on an open file.
*
* Input Parameters:
* fd - File descriptor of the open file
* cmd - Identifies the operation to be performed. Command specific
* arguments may follow.
*
* Returned Value:
* The returned value depends on the nature of the command but for all
* commands the return value of -1 (ERROR) indicates that an error has
* occurred and, in this case, the errno variable will be set
* appropriately
*
****************************************************************************/
int fcntl(int fd, int cmd, ...)
{
FAR struct file *filep;
va_list ap;
int ret;
int val = 0;
/* 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)
{
/* The errno value has already been set */
va_end(ap);
return VFS_ERROR;
}
/* 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(LOSCFG_NET_LWIP_SACK)
if ((unsigned int)fd < (unsigned int)(CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS))
{
/* Yes.. defer socket descriptor operations to net_vfcntl() */
val = va_arg(ap, int);
ret = lwip_fcntl(fd, cmd, val);
}
else
#endif
{
/* No.. this descriptor number is out of range */
(void)val;
ret = EBADF;
set_errno(ret);
va_end(ap);
return VFS_ERROR;
}
}
va_end(ap);
return ret;
}
int fcntl64(int fd, int cmd, ...)
{
FAR struct file *filep = NULL;
va_list va_ap;
int reval;
int va_val = 0;
/* Setup to access the variable argument list */
va_start(va_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. */
int ret = fs_getfilep(fd, &filep);
if (ret < 0)
{
/* The errno value has already been set */
va_end(va_ap);
return VFS_ERROR;
}
/* Let file_vfcntl() do the real work */
reval = file_vfcntl(filep, cmd, va_ap);
}
else
#endif
{
/* No... check for operations on a socket descriptor */
#if defined(LOSCFG_NET_LWIP_SACK)
if ((unsigned int)fd < (unsigned int)(CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS))
{
/* Yes.. defer socket descriptor operations to net_vfcntl() */
va_val = va_arg(va_ap, int);
reval = lwip_fcntl(fd, cmd, va_val);
}
else
#endif
{
/* No.. this descriptor number is out of range */
(void)va_val;
reval = EBADF;
set_errno(reval);
va_end(va_ap);
return VFS_ERROR;
}
}
va_end(va_ap);
return reval;
}
+136
View File
@@ -0,0 +1,136 @@
/****************************************************************************
* fs/vfs/fs_fsync.c
*
* Copyright (C) 2007-2009, 2013-2014, 2016-2017 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "unistd.h"
#include "fcntl.h"
#include "errno.h"
#include "assert.h"
#include "fs/fs.h"
#include "inode/inode.h"
#ifndef CONFIG_DISABLE_MOUNTPOINT
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: file_fsync
*
* Description:
* Equivalent to the standard fsync() function except that is accepts a
* struct file instance instead of a file descriptor and it does not set
* the errno variable.
*
****************************************************************************/
int file_fsync(FAR struct file *filep)
{
struct inode *inode;
int ret;
/* Was this file opened for write access? */
if ((filep->f_oflags & O_ACCMODE) == 0)
{
ret = EBADF;
goto errout;
}
/* Is this inode a registered mountpoint? Does it support the
* sync operations may be relevant to device drivers but only
* the mountpoint operations vtable contains a sync method.
*/
inode = filep->f_inode;
if (!inode || !INODE_IS_MOUNTPT(inode) ||
!inode->u.i_mops || !inode->u.i_mops->sync)
{
ret = EINVAL;
goto errout;
}
/* Yes, then tell the mountpoint to sync this file */
ret = inode->u.i_mops->sync(filep);
if (ret >= 0)
{
return OK;
}
ret = -ret;
errout:
set_errno(ret);
return VFS_ERROR;
}
/****************************************************************************
* Name: fsync
*
* Description:
* This func simply binds inode sync methods to the sync system call.
*
****************************************************************************/
int fsync(int fd)
{
FAR struct file *filep;
/* Get the file structure corresponding to the file descriptor. */
int ret = fs_getfilep(fd, &filep);
if (ret < 0)
{
/* The errno value has already been set */
return VFS_ERROR;
}
/* Perform the fsync operation */
return file_fsync(filep);
}
#endif /* !CONFIG_DISABLE_MOUNTPOINT */
+113
View File
@@ -0,0 +1,113 @@
/****************************************************************************
* fs/vfs/fs_getfilep.c
*
* Copyright (C) 2014, 2016-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "sys/types.h"
#include "errno.h"
#include "sched.h"
#include "inode/inode.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: fs_getfilep
*
* Description:
* Given a file descriptor, return the corresponding instance of struct
* file. NOTE that this function will currently fail if it is provided
* with a socket descriptor.
*
* Input Parameters:
* fd - The file descriptor
* filep - The location to return the struct file instance
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned on
* any failure.
*
****************************************************************************/
int fs_getfilep_normal(int fd, FAR struct file **filep)
{
struct filelist *list;
*filep = (struct file *)NULL;
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
{
return -EBADF;
}
/* The descriptor is in a valid range to file descriptor... Get the
* thread-specific file list.
*/
list = sched_getfiles();
/* The file list can be NULL under two cases: (1) One is an obscure
* cornercase: When memory management debug output is enabled. Then
* there may be attempts to write to stdout from malloc before the group
* data has been allocated. The other other is (2) if this is a kernel
* thread. Kernel threads have no allocated file descriptors.
*/
if (list == NULL)
{
return -EAGAIN;
}
/* And return the file pointer from the list */
*filep = &list->fl_files[fd];
return OK;
}
int fs_getfilep(int fd, FAR struct file **filep)
{
int ret = fs_getfilep_normal(fd, filep);
if (ret < 0)
{
set_errno(-ret);
}
return ret;
}
+177
View File
@@ -0,0 +1,177 @@
/****************************************************************************
* fs/vfs/fs_ioctl.c
*
* Copyright (C) 2007-2010, 2012-2014, 2016-2017 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "sched.h"
#include "assert.h"
#include "errno.h"
#include "unistd.h"
#include "console.h"
#if defined(LOSCFG_NET_LWIP_SACK)
# include "net/net.h"
#endif
#include "inode/inode.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: ioctl/fs_ioctl
*
* Description:
* Perform device specific operations.
*
* Input Parameters:
* fd File/socket descriptor of device
* req The ioctl command
* arg The argument of the ioctl cmd
*
* Returned Value:
* >=0 on success (positive non-zero values are cmd-specific)
* -1 on failure with errno set properly:
*
* EBADF
* 'fd' is not a valid descriptor.
* EFAULT
* 'arg' references an inaccessible memory area.
* EINVAL
* 'cmd' or 'arg' is not valid.
* ENOTTY
* 'fd' is not associated with a character special device.
* ENOTTY
* The specified request does not apply to the kind of object that the
* descriptor 'fd' references.
*
****************************************************************************/
#ifdef CONFIG_LIBC_IOCTL_VARIADIC
int fs_ioctl(int fd, int req, ...)
#else
int ioctl(int fd, int req, ...)
#endif
{
int err;
UINTPTR arg = 0;
va_list ap;
#if CONFIG_NFILE_DESCRIPTORS > 0
FAR struct file *filep;
FAR struct inode *inode;
int ret = OK;
#endif
va_start(ap, req);
arg = va_arg(ap, UINTPTR);
va_end(ap);
#if CONFIG_NFILE_DESCRIPTORS > 0
/* Did we get a valid file descriptor? */
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
#endif
{
/* Perform the socket ioctl */
#if defined(LOSCFG_NET_LWIP_SACK)
if ((unsigned int)fd < (unsigned int)(CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS))
{
return socks_ioctl(fd, (long)req, (void *)arg);
}
else
#endif
{
err = EBADF;
ret = VFS_ERROR;
goto errout;
}
}
#if CONFIG_NFILE_DESCRIPTORS > 0
if (fd >= STDIN_FILENO && fd <= STDERR_FILENO) /* fd : [0,2] */
{
fd = ConsoleUpdateFd();
if (fd < 0)
{
err = EBADF;
ret = VFS_ERROR;
goto errout;
}
}
/* Get the file structure corresponding to the file descriptor. */
ret = fs_getfilep(fd, &filep);
if (ret < 0)
{
/* The errno value has already been set */
return VFS_ERROR;
}
/* Is a driver registered? Does it support the ioctl method? */
inode = filep->f_inode;
if (inode && inode->u.i_ops && inode->u.i_ops->ioctl)
{
/* Yes, then let it perform the ioctl */
ret = (int)inode->u.i_ops->ioctl(filep, req, arg);
if (ret < 0)
{
err = -ret;
goto errout;
}
}
else
{
err = EBADF;
ret = VFS_ERROR;
goto errout;
}
return ret;
#endif
errout:
set_errno(err);
return ret;
}
+194
View File
@@ -0,0 +1,194 @@
/****************************************************************************
* fs/vfs/fs_lseek.c
*
* Copyright (C) 2008, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <vfs_config.h>
#include "sys/types.h"
#include "unistd.h"
#include "sched.h"
#include "assert.h"
#include "errno.h"
#include "inode/inode.h"
#if CONFIG_NFILE_DESCRIPTORS > 0
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: file_seek
*
* Description:
* This is the internal implementation of lseek. See the comments in
* lseek() for further information.
*
* Input Parameters:
* file File structure instance
* offset Defines the offset to position to
* whence Defines how to use offset
*
* Returned Value:
* The resulting offset on success. A negated errno value is returned on
* any failure (see lseek comments).
*
****************************************************************************/
off_t file_seek(FAR struct file *filep, off_t offset, int whence)
{
FAR struct inode *inode;
int ret;
int err = OK;
DEBUGASSERT(filep);
inode = filep->f_inode;
if (!inode)
{
err = EBADF;
goto errout;
}
/* Invoke the file seek method if available */
if (inode->u.i_ops && inode->u.i_ops->seek)
{
ret = inode->u.i_ops->seek(filep, offset, whence);
if (ret < 0)
{
err = -ret;
goto errout;
}
}
else
{
/* No... Just set the common file position value */
switch (whence)
{
case SEEK_CUR:
offset += (off_t)filep->f_pos;
/* FALLTHROUGH */
case SEEK_SET:
if (offset >= 0)
{
filep->f_pos = (loff_t)offset; /* Might be beyond the end-of-file */
}
else
{
err = EINVAL;
goto errout;
}
break;
case SEEK_END:
err = ENOSYS;
goto errout;
default:
err = EINVAL;
goto errout;
}
}
return (off_t)filep->f_pos;
errout:
set_errno(err);
return (off_t)VFS_ERROR;
}
/****************************************************************************
* Name: lseek
*
* Description:
* The lseek() function repositions the offset of the open file associated
* with the file descriptor fd to the argument 'offset' according to the
* directive 'whence' as follows:
*
* SEEK_SET
* The offset is set to offset bytes.
* SEEK_CUR
* The offset is set to its current location plus offset bytes.
* SEEK_END
* The offset is set to the size of the file plus offset bytes.
*
* The lseek() function allows the file offset to be set beyond the end of the
* file (but this does not change the size of the file). If data is later written
* at this point, subsequent reads of the data in the gap (a "hole") return null
* bytes ('\0') until data is actually written into the gap.
*
* Input Parameters:
* fd File descriptor of device
* offset Defines the offset to position to
* whence Defines how to use offset
*
* Returned Value:
* The resulting offset on success. -1 on failure withi errno set properly:
*
* EBADF fd is not an open file descriptor.
* EINVAL whence is not one of SEEK_SET, SEEK_CUR, SEEK_END; or the
* resulting file offset would be negative, or beyond the end of a
* seekable device.
* EOVERFLOW The resulting file offset cannot be represented in an off_t.
* ESPIPE fd is associated with a pipe, socket, or FIFO.
*
****************************************************************************/
off_t lseek(int fd, off_t offset, int whence)
{
FAR struct file *filep;
/* Get the file structure corresponding to the file descriptor. */
int ret = fs_getfilep(fd, &filep);
if (ret < 0)
{
/* The errno value has already been set */
return (off_t)VFS_ERROR;
}
/* Then let file_seek do the real work */
return file_seek(filep, offset, whence);
}
#endif
+195
View File
@@ -0,0 +1,195 @@
/****************************************************************************
* fs/vfs/fs_lseek.c
*
* Copyright (C) 2008, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <vfs_config.h>
#include "sys/types.h"
#include "unistd.h"
#include "sched.h"
#include "assert.h"
#include "errno.h"
#include "inode/inode.h"
#if CONFIG_NFILE_DESCRIPTORS > 0
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: file_seek64
*
* Description:
* This is the internal implementation of lseek. See the comments in
* lseek() for further information.
*
* Input Parameters:
* file File structure instance
* offset Defines the offset to position to
* whence Defines how to use offset
*
* Returned Value:
* The resulting offset on success. A negated errno value is returned on
* any failure (see lseek comments).
*
****************************************************************************/
off64_t file_seek64(FAR struct file *filep, off64_t offset, int whence)
{
FAR struct inode *inode = NULL;
off64_t ret;
int err = OK;
DEBUGASSERT(filep);
inode = filep->f_inode;
if (inode == NULL)
{
err = EBADF;
goto errout;
}
/* Invoke the file seek method if available */
if (INODE_IS_MOUNTPT(inode) && inode->u.i_mops && inode->u.i_mops->seek64)
{
ret = inode->u.i_mops->seek64(filep, offset, whence);
if (ret < 0)
{
err = -(int)ret;
goto errout;
}
filep->f_pos = ret;
}
else
{
/* No... Just set the common file position value */
switch (whence)
{
case SEEK_CUR:
offset += filep->f_pos;
/* FALLTHROUGH */
case SEEK_SET:
if (offset >= 0)
{
filep->f_pos = offset; /* Might be beyond the end-of-file */
}
else
{
err = EINVAL;
goto errout;
}
break;
case SEEK_END:
err = ENOSYS;
goto errout;
default:
err = EINVAL;
goto errout;
}
}
return filep->f_pos;
errout:
set_errno(err);
return (off64_t)VFS_ERROR;
}
/****************************************************************************
* Name: lseek64
*
* Description:
* The lseek64() function repositions the offset of the open file associated
* with the file descriptor fd to the argument 'offset' according to the
* directive 'whence' as follows:
*
* SEEK_SET
* The offset is set to offset bytes.
* SEEK_CUR
* The offset is set to its current location plus offset bytes.
* SEEK_END
* The offset is set to the size of the file plus offset bytes.
*
* The lseek64() function allows the file offset to be set beyond the end of the
* file (but this does not change the size of the file). If data is later written
* at this point, subsequent reads of the data in the gap (a "hole") return null
* bytes ('\0') until data is actually written into the gap.
*
* Input Parameters:
* fd File descriptor of device
* offset Defines the offset to position to
* whence Defines how to use offset
*
* Returned Value:
* The resulting offset on success. -1 on failure withi errno set properly:
*
* EBADF fd is not an open file descriptor.
* EINVAL whence is not one of SEEK_SET, SEEK_CUR, SEEK_END; or the
* resulting file offset would be negative, or beyond the end of a
* seekable device.
* EOVERFLOW The resulting file offset cannot be represented in an off_t.
* ESPIPE fd is associated with a pipe, socket, or FIFO.
*
****************************************************************************/
off64_t lseek64(int fd, off64_t offset, int whence)
{
FAR struct file *filep;
/* Get the file structure corresponding to the file descriptor. */
int ret = fs_getfilep(fd, &filep);
if (ret < 0)
{
/* The errno value has already been set */
return (off64_t)VFS_ERROR;
}
/* Then let file_seek do the real work */
return file_seek64(filep, offset, whence);
}
#endif
+277
View File
@@ -0,0 +1,277 @@
/****************************************************************************
* fs/vfs/fs_mkdir.c
*
* Copyright (C) 2007, 2008, 2014, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "errno.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fs/fs.h"
#include "stdlib.h"
#include "inode/inode.h"
#include "string.h"
#include "fs_other.h"
#include "capability_api.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#undef FS_HAVE_WRITABLE_MOUNTPOINT
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_WRITABLE) && \
CONFIG_NFILE_STREAMS > 0
# define FS_HAVE_WRITABLE_MOUNTPOINT 1
#endif
#undef FS_HAVE_PSEUDOFS_OPERATIONS
#if !defined(CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && CONFIG_NFILE_STREAMS > 0
# define FS_HAVE_PSEUDOFS_OPERATIONS 1
#endif
#undef FS_HAVE_MKDIR
#if defined(FS_HAVE_WRITABLE_MOUNTPOINT) || defined(FS_HAVE_PSEUDOFS_OPERATIONS)
# define FS_HAVE_MKDIR 1
#endif
#ifdef FS_HAVE_MKDIR
/****************************************************************************
* Private Functions
****************************************************************************/
int do_mkdir(int dirfd, const char *pathname, mode_t mode)
{
FAR struct inode *inode;
FAR struct inode *pathnode;
const char *relpath = NULL;
int errcode;
int ret;
char *fullpath = NULL;
char *relativepath = NULL;
struct inode_search_s desc;
uint c_uid = OsCurrUserGet()->effUserID;
uint c_gid = OsCurrUserGet()->effGid;
mode &= ~GetUmask();
mode &= (S_IRWXU|S_IRWXG|S_IRWXO);
/* Get absolute path by dirfd*/
ret = get_path_from_fd(dirfd, &relativepath);
if (ret < 0)
{
errcode = -ret;
goto errout;
}
ret = vfs_normalize_path((const char *)relativepath, pathname, &fullpath);
if (relativepath)
{
free(relativepath);
}
if (ret < 0)
{
errcode = -ret;
goto errout;
}
/* Find the inode that includes this path */
SETUP_SEARCH(&desc, fullpath, false);
ret = inode_find(&desc);
inode = desc.node;
relpath = desc.relpath;
if ((ret >= 0) && (inode != NULL))
{
if (!strlen(relpath))
{
/* Find the inode that exactly match this path. */
errcode = EEXIST;
goto errout_with_inode;
}
/* If the path doesn't include the existed rootfs dirs,
* then make a pseudo dir.
*/
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
if (((inode == g_root_inode) && !IsInRootfs(relpath)) || (!INODE_IS_MOUNTPT(g_root_inode)))
{
if (VfsPermissionCheck(desc.parent->i_uid, desc.parent->i_gid, desc.parent->i_mode, EXEC_OP | WRITE_OP))
{
errcode = EACCES;
goto errout_with_inode;
}
/* Create a pseudo inode. */
inode_semtake();
ret = inode_reserve(fullpath, &pathnode);
if (ret < 0)
{
errcode = -ret;
inode_semgive();
goto errout_with_inode;
}
pathnode->i_mode = mode;
pathnode->i_uid = c_uid;
pathnode->i_gid = c_gid;
inode_semgive();
}
else
#endif
/* An inode was found that includes this path and possibly refers to a
* mountpoint.
*/
#ifndef CONFIG_DISABLE_MOUNTPOINT
/* Check if the inode is a valid mountpoint. */
if (!INODE_IS_MOUNTPT(inode) || !inode->u.i_mops)
{
/* The inode is not a mountpoint */
errcode = EEXIST;
goto errout_with_inode;
}
/* Perform the mkdir operation using the relative path
* at the mountpoint.
*/
else if (inode->u.i_mops->mkdir)
{
ret = inode->u.i_mops->mkdir(inode, relpath, mode);
if (ret < 0)
{
errcode = -ret;
goto errout_with_inode;
}
}
else
{
errcode = ENOSYS;
goto errout_with_inode;
}
/* Release our reference on the inode */
inode_release(inode);
#else
/* But mountpoints are not supported in this configuration */
errcode = EEXIST;
goto errout_with_inode;
#endif
}
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
/* No inode exists that contains this path. Create a new inode in the
* pseudo-filesystem at this location.
*/
else
{
/* Create an inode in the pseudo-filesystem at this path.
* NOTE that the new inode will be created with a reference
* count of zero.
*/
inode_semtake();
ret = inode_reserve(fullpath, &inode);
if (ret < 0)
{
errcode = -ret;
free(fullpath);
inode_semgive();
goto errout;
}
inode->i_mode = mode;
inode->i_uid = c_uid;
inode->i_gid = c_gid;
inode_semgive();
}
#else
else
{
errcode = ENXIO;
free(fullpath);
goto errout;
}
#endif
/* Directory successfully created */
free(fullpath);
return OK;
errout_with_inode:
inode_release(inode);
free(fullpath);
errout:
set_errno(errcode);
return VFS_ERROR;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: mkdir
*
* Description: Create a directory
*
****************************************************************************/
int mkdir(const char *pathname, mode_t mode)
{
return do_mkdir(AT_FDCWD, pathname, mode);
}
/****************************************************************************
* Name: mkdirat
*
* Description: Create a directory by dirfd
*
****************************************************************************/
int mkdirat(int dirfd, const char *pathname, mode_t mode)
{
return do_mkdir(dirfd, pathname, mode);
}
#endif /* FS_HAVE_MKDIR */
+362
View File
@@ -0,0 +1,362 @@
/****************************************************************************
* fs/vfs/fs_open.c
*
* Copyright (C) 2007-2009, 2011-2012, 2016-2018 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "errno.h"
#include "sys/types.h"
#include "fcntl.h"
#include "sched.h"
#include "assert.h"
#ifdef LOSCFG_FILE_MODE
#include "stdarg.h"
#endif
#include "stdlib.h"
#include "fs/fs.h"
#include "inode/inode.h"
#include "driver/blockproxy.h"
#include "fs_other.h"
/****************************************************************************
* Public Functions
****************************************************************************/
static int oflag_convert_mode(int oflags)
{
/* regular file operations */
int acc_mode = 0;
if ((oflags & O_ACCMODE) == O_RDONLY)
acc_mode |= READ_OP;
if (oflags & O_WRONLY)
acc_mode |= WRITE_OP;
if (oflags & O_RDWR)
acc_mode |= READ_OP | WRITE_OP;
/* Opens the file, if it is existing. If not, a new file is created. */
if (oflags & O_CREAT)
acc_mode |= WRITE_OP;
/* Creates a new file. If the file is existing, it is truncated and overwritten. */
if (oflags & O_TRUNC)
acc_mode |= WRITE_OP;
/* Creates a new file. The function fails if the file is already existing. */
if (oflags & O_EXCL)
acc_mode |= WRITE_OP;
if (oflags & O_APPEND)
acc_mode |= WRITE_OP;
/* mark for executing operation */
if (oflags & O_EXECVE)
acc_mode |= EXEC_OP;
return acc_mode;
}
int get_path_from_fd(int fd, char **path)
{
FAR struct file *file = NULL;
char *copypath = NULL;
if (fd == AT_FDCWD)
{
return OK;
}
int ret = fs_getfilep(fd, &file);
if (ret < 0)
{
return -ENOENT;
}
if ((file == NULL) || (file->f_inode == NULL) || (file->f_path == NULL))
{
return -EBADF;
}
copypath = strdup((const char*)file->f_path);
if (copypath == NULL)
{
return VFS_ERROR;
}
char *endptr = copypath + strlen(copypath)-1;//the ptr before '\0'
/* strip out the file name, for example:/usr/lib/xx.so, final get /usr/lib/ */
while (endptr > copypath)
{
if(*endptr == '/' && endptr > copypath)
{
*(endptr + 1) = '\0';
*path = copypath;
return OK;
}
endptr--;
}
free(copypath);
return -ENOENT;
}
int do_open(int dirfd, const char *path, int oflags, ...)
{
FAR struct file *filep = NULL;
FAR struct inode *inode = NULL;
FAR const char *relpath = NULL;
char *fullpath = NULL;
char *relativepath = NULL;
struct inode_search_s desc;
#if defined(LOSCFG_FILE_MODE) || !defined(CONFIG_DISABLE_MOUNTPOINT)
mode_t mode = DEFAULT_FILE_MODE;
#endif
int ret;
int fd;
int acc_mode;
#ifdef LOSCFG_FILE_MODE
/* 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, int);
va_end(ap);
mode &= ~GetUmask();
mode &= (S_IRWXU|S_IRWXG|S_IRWXO);
}
#endif
/* Get relative path by dirfd*/
ret = get_path_from_fd(dirfd, &relativepath);
if (ret < 0)
{
ret = -ret;
goto errout;
}
ret = vfs_normalize_path((const char *)relativepath, path, &fullpath);
if (relativepath)
{
free(relativepath);
}
if (ret < 0)
{
ret = -ret;
goto errout;
}
/* Get an inode for this file */
SETUP_SEARCH(&desc, fullpath, false);
ret = inode_find(&desc);
if (ret < 0)
{
ret = EACCES;
free(fullpath);
goto errout;
}
inode = desc.node;
relpath = desc.relpath;
#if !defined(CONFIG_DISABLE_MOUNTPOINT)
#ifdef LOSCFG_FS_VFS_BLOCK_DEVICE
if (INODE_IS_BLOCK(inode))
{
fd = block_proxy(path, oflags);
if (fd < 0)
{
ret = fd;
goto errout_with_inode;
}
inode_release(inode);
free(fullpath);
return fd;
}
#endif
#endif
/* Verify that the inode is valid and either a "normal" character driver or a
* mountpoint. We specifically exclude block drivers and and "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;
}
/* Associate the inode with a file structure */
fd = files_allocate(inode, oflags, 0, NULL, 3); /* 3: file start fd */
if (fd < 0)
{
ret = EMFILE;
goto errout_with_inode;
}
/* Get the file structure corresponding to the file descriptor. */
ret = fs_getfilep(fd, &filep);
if (ret < 0)
{
ret = EPERM;
/* The errno value has already been set */
goto errout_with_fd;
}
/* 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;
filep->f_path = fullpath; /* The mem will free in close(fd); */
filep->f_relpath = relpath;
acc_mode = oflag_convert_mode(oflags);
if (inode->u.i_ops->open)
{
#ifndef CONFIG_DISABLE_MOUNTPOINT
if (INODE_IS_MOUNTPT(inode))
{
if (VfsPermissionCheck(inode->i_uid, inode->i_gid, inode->i_mode, EXEC_OP))
{
ret = EACCES;
goto errout_with_fd;
}
ret = inode->u.i_mops->open(filep, relpath, oflags, mode);
}
else
#endif
{
if (VfsPermissionCheck(inode->i_uid, inode->i_gid, inode->i_mode, acc_mode))
{
ret = EACCES;
goto errout_with_fd;
}
ret = inode->u.i_ops->open(filep);
}
}
if (ret < 0)
{
ret = -ret;
goto errout_with_fd;
}
/* we do not bother to handle the NULL scenario, if so, page-cache feature will not be used
* when we do the file fault */
add_mapping(filep, fullpath);
return fd;
errout_with_fd:
files_release(fd);
errout_with_inode:
inode_release(inode);
free(fullpath);
errout:
set_errno(ret);
return VFS_ERROR;
}
/****************************************************************************
* Name: open
*
* Description: Standard 'open' interface
*
****************************************************************************/
int open(const char *path, int oflags, ...)
{
mode_t mode = 0666; /* File read-write properties. */
#ifdef LOSCFG_FILE_MODE
va_list ap;
va_start(ap, oflags);
mode = va_arg(ap, int);
va_end(ap);
#endif
return do_open(AT_FDCWD, path, oflags, mode);
}
int open64 (const char *__path, int __oflag, ...)
{
mode_t mode = 0666; /* File read-write properties. */
#ifdef LOSCFG_FILE_MODE
va_list ap;
va_start(ap, __oflag);
mode = va_arg(ap, int);
va_end(ap);
#endif
return open (__path, ((unsigned int)__oflag) | O_LARGEFILE, mode);
}
/****************************************************************************
* Name: openat
*
* Description: open by dirfd
*
****************************************************************************/
int openat(int dirfd, const char * path, int oflags, ...)
{
mode_t mode = 0666; /* File read-write properties. */
#ifdef LOSCFG_FILE_MODE
va_list ap;
va_start(ap, oflags);
mode = va_arg(ap, int);
va_end(ap);
#endif
return do_open(dirfd, path, oflags, mode);
}
+540
View File
@@ -0,0 +1,540 @@
/****************************************************************************
* fs/vfs/fs_poll.c
*
* Copyright (C) 2008-2009, 2012-2019 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "los_hwi.h"
#include "vfs_config.h"
#include "stdint.h"
#include "poll.h"
#include "assert.h"
#include "errno.h"
#include "debug.h"
#include "fs/fs.h"
#include "inode/inode.h"
#include "stdlib.h"
#include "stdio.h"
#include "console.h"
#include "unistd.h"
#include "linux/wait.h"
#ifdef LOSCFG_NET_LWIP_SACK
#include "lwip/sockets.h"
#endif
#ifndef CONFIG_DISABLE_POLL
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifndef MSEC_PER_SEC
#define MSEC_PER_SEC 1000L
#endif
#ifndef NSEC_PER_MSEC
#define NSEC_PER_MSEC 1000000L
#endif
#define N_POLL_ITEMS 5
#define poll_semgive(sem) sem_post(sem)
/****************************************************************************
* Data Structures & Macros
****************************************************************************/
typedef wait_queue_head_t * poll_wait_queue;
typedef struct tag_poll_wait_node
{
LOS_DL_LIST queue_node;
pollevent_t key;
struct tag_poll_wait_entry *entry;
poll_wait_queue wait_queue;
} poll_wait_node;
typedef struct tag_poll_wait_entry_table
{
struct tag_poll_wait_entry_table *next;
UINT32 index;
poll_wait_node items[N_POLL_ITEMS];
} poll_wait_entry_table;
typedef struct tag_poll_wait_entry
{
bool add_queue_flag;
sem_t sem;
UINT32 inline_index;
poll_wait_node inline_items[N_POLL_ITEMS];
poll_wait_entry_table *table;
} poll_wait_entry;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: poll_semtake
****************************************************************************/
static int poll_semtake(sem_t *sem)
{
/* Take the semaphore (perhaps waiting) */
if (sem_wait(sem) < 0)
{
int err = get_errno();
/* The only case that an error should occur here is if the wait were
* awakened by a signal.
*/
DEBUGASSERT(err == EINTR);
return -err;
}
return OK;
}
static void set_add_poll_wait_flag(poll_wait_head wait, bool add_queue_flag)
{
wait->add_queue_flag = add_queue_flag;
}
static int destroy_poll_wait(poll_wait_head wait)
{
unsigned int i;
unsigned long int_save;
poll_wait_node *wait_node = NULL;
poll_wait_entry_table *curr_table = NULL;
for (i = 0; i < wait->inline_index; ++i)
{
wait_node = &wait->inline_items[i];
spin_lock_irqsave(&wait_node->wait_queue->lock, int_save);
LOS_ListDelete(&wait_node->queue_node);
spin_unlock_irqrestore(&wait_node->wait_queue->lock, int_save);
}
while (wait->table)
{
curr_table = wait->table;
wait->table = curr_table->next;
for (i = 0; i < curr_table->index; ++i)
{
wait_node = &curr_table->items[i];
spin_lock_irqsave(&wait_node->wait_queue->lock, int_save);
LOS_ListDelete(&wait_node->queue_node);
spin_unlock_irqrestore(&wait_node->wait_queue->lock, int_save);
}
free(curr_table);
}
if (sem_destroy(&wait->sem) < 0)
{
PRINT_ERR("[%s] sem_destroy failed\n", __FUNCTION__);
return -1;
}
return 0;
}
static poll_wait_node *get_poll_item(poll_wait_head wait)
{
if (wait->inline_index < N_POLL_ITEMS)
{
return wait->inline_items + wait->inline_index++;
}
if (!wait->table || (wait->table && wait->table->index >= N_POLL_ITEMS))
{
poll_wait_entry_table *new_entry_table = NULL;
new_entry_table = (poll_wait_entry_table *)malloc(sizeof(poll_wait_entry_table));
if (new_entry_table == NULL)
{
return (poll_wait_node *)NULL;
}
new_entry_table->index = 0;
new_entry_table->next = wait->table;
wait->table = new_entry_table;
}
return wait->table->items + wait->table->index++;
}
static void add_pollwait_queue(poll_wait_queue queue, poll_table *p)
{
unsigned long int_save;
poll_wait_head wait = p->wait;
poll_wait_node *new_node = get_poll_item(wait);
if (new_node != NULL)
{
new_node->entry = wait;
new_node->key = p->key;
new_node->wait_queue = queue;
spin_lock_irqsave(&queue->lock, int_save);
LOS_ListAdd(&queue->poll_queue, &new_node->queue_node);
spin_unlock_irqrestore(&queue->lock, int_save);
}
}
static int wait_sem_time(poll_wait_head wait, const struct timespec *time_ptr)
{
if (time_ptr != NULL)
{
return sem_timedwait(&wait->sem, time_ptr);
}
else
{
return poll_semtake(&wait->sem);
}
}
static int file_poll(struct file *filep, poll_table *wait)
{
struct inode *inode = NULL;
int ret = -ENOSYS;
inode = filep->f_inode;
if (inode != NULL && inode->u.i_ops != NULL && inode->u.i_ops->poll != NULL)
{
ret = inode->u.i_ops->poll(filep, wait);
}
return ret;
}
static int fdesc_poll(int fd, poll_table *wait)
{
struct file *filep = NULL;
if (fd <= STDERR_FILENO && fd >= STDIN_FILENO) /* fd : [0,2] */
{
fd = ConsoleUpdateFd();
if (fd < 0)
{
set_errno(EBADF);
return VFS_ERROR;
}
}
/* Get the file pointer corresponding to this file descriptor */
int ret = fs_getfilep(fd, &filep);
if (ret < 0)
{
/* The errno value has already been set */
int errorcode = get_errno();
return -errorcode;
}
/* Let file_poll() do the rest */
return file_poll(filep, wait);
}
static int query_fd(int fd, poll_table *wait)
{
/* Check for a valid file descriptor */
if (fd >= CONFIG_NFILE_DESCRIPTORS)
{
/* Perform the socket ioctl */
#if defined(LOSCFG_NET_LWIP_SACK)
if (fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS))
{
return socks_poll(fd, wait);
}
else
#endif
{
return -EBADF;
}
}
return fdesc_poll(fd, wait);
}
static int query_fds(struct pollfd *fds, nfds_t nfds, poll_table *wait)
{
unsigned int i;
int ret;
int count = 0;
if ((nfds != 0 && fds == NULL) || wait == NULL || wait->wait == NULL)
{
set_errno(EINVAL);
return -1;
}
for (i = 0; i < nfds; ++i)
{
struct pollfd *p_fds = &fds[i];
if (p_fds->fd < 0)
{
set_errno(EBADF);
return -1;
}
wait->key = p_fds->events | POLLERR | POLLHUP;
ret = query_fd(p_fds->fd, wait);
if (ret < 0)
{
set_errno(-ret);
return -1;
}
p_fds->revents = (p_fds->events | POLLERR | POLLHUP) & (pollevent_t)ret;
if (p_fds->revents)
{
++count;
set_add_poll_wait_flag(wait->wait, false);
}
}
return count;
}
/****************************************************************************
* Public Functions
****************************************************************************/
void notify_poll_with_key(wait_queue_head_t *wait_address, pollevent_t key)
{
unsigned long int_save;
int failed_count = 0;
poll_wait_node *curr = NULL;
spin_lock_irqsave(&wait_address->lock, int_save);
LOS_DL_LIST_FOR_EACH_ENTRY(curr, &(wait_address->poll_queue), poll_wait_node, queue_node)
{
poll_wait_entry *curr_entry = curr->entry;
if (!key || (key & curr->key))
{
if (poll_semgive(&curr_entry->sem) < 0)
{
failed_count++;
}
}
}
spin_unlock_irqrestore(&wait_address->lock, int_save);
if (failed_count != 0)
{
PRINT_ERR("[%s] sem_post failed %d times\n", __FUNCTION__, failed_count);
}
}
/* just for compatible */
void notify_poll(wait_queue_head_t *wait_address)
{
notify_poll_with_key(wait_address, 0);
}
void poll_wait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p)
{
if (!wait_address || !p || !p->wait)
{
return;
}
if (p->wait->add_queue_flag)
{
add_pollwait_queue(wait_address, p);
}
}
/****************************************************************************
* Name: poll
*
* Description:
* poll() waits for one of a set of file descriptors to become ready to
* perform I/O. If none of the events requested (and no error) has
* occurred for any of the file descriptors, then poll() blocks until
* one of the events occurs.
*
* Input Parameters:
* fds - List of structures describing file descriptors to be monitored
* nfds - The number of entries in the list
* timeout - Specifies an upper limit on the time for which poll() will
* block in milliseconds. A negative value of timeout means an infinite
* timeout.
*
* Returned Value:
* On success, the number of structures that have non-zero revents fields.
* A value of 0 indicates that the call timed out and no file descriptors
* were ready. On error, -1 is returned, and errno is set appropriately:
*
* EBADF - An invalid file descriptor was given in one of the sets.
* EFAULT - The fds address is invalid
* EINTR - A signal occurred before any requested event.
* EINVAL - The nfds value exceeds a system limit.
* ENOMEM - There was no space to allocate internal data structures.
* ENOSYS - One or more of the drivers supporting the file descriptor
* does not support the poll method.
*
****************************************************************************/
int poll(struct pollfd *fds, nfds_t nfds, int timeout)
{
poll_table wait_table;
poll_wait_entry wait_entry;
size_t start_ticks = 0;
int millisecs_left;
int ret = OK;
int count = 0;
int err = 0;
int temp = 0;
wait_table.wait = &wait_entry;
wait_table.wait->table = NULL;
wait_table.wait->inline_index = 0;
if (sem_init(&wait_table.wait->sem, 0, 0) < 0)
{
set_errno(ENOMEM);
return -1;
}
/* set wait flag */
set_add_poll_wait_flag(wait_table.wait, ((timeout == 0) ? false : true));
count = query_fds(fds, nfds, &wait_table);
if (count > 0)
{
ret = OK;
goto out;
}
else if (count < 0)
{
goto out;
}
/* clear wait flag if no fd got on first query */
set_add_poll_wait_flag(wait_table.wait, false);
if (timeout > 0)
{
start_ticks = LOS_TickCountGet();
}
millisecs_left = timeout;
while (count == 0)
{
if (timeout < 0)
{
ret = wait_sem_time(wait_table.wait, (const struct timespec *)NULL);
}
else if (timeout == 0 || millisecs_left <= 0)
{
ret = OK;
goto out;
}
else if (millisecs_left > 0)
{
struct timespec wait_time;
UINT64 curr_ticks;
int millisecs_last;
curr_ticks = LOS_TickCountGet();
millisecs_last = (curr_ticks - start_ticks) * MSEC_PER_SEC / LOSCFG_BASE_CORE_TICK_PER_SECOND;
if (millisecs_last >= timeout)
{
ret = OK;
goto out;
}
else
{
millisecs_left = timeout - millisecs_last;
}
wait_time.tv_sec = millisecs_left / MSEC_PER_SEC;
wait_time.tv_nsec = (millisecs_left - MSEC_PER_SEC * wait_time.tv_sec) * NSEC_PER_MSEC;
ret = wait_sem_time(wait_table.wait, &wait_time);
if (ret < 0)
{
err = get_errno();
if (err == ETIMEDOUT)
{
ret = OK;
}
else
{
ret = -err;
}
}
}
if (ret < 0)
{
goto out;
}
count = query_fds(fds, nfds, &wait_table);
if (err == ETIMEDOUT)
{
break;
}
}
out:
temp = get_errno();
if (destroy_poll_wait(wait_table.wait) < 0)
{
temp = get_errno();
}
if (temp != 0)
{
set_errno(temp);
}
if (ret < 0)
{
set_errno(-ret);
return -1;
}
return count;
}
#endif /* CONFIG_DISABLE_POLL */
+167
View File
@@ -0,0 +1,167 @@
/****************************************************************************
* fs/vfs/fs_pread.c
*
* Copyright (C) 2014, 2016-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "sys/types.h"
#include "unistd.h"
#include "errno.h"
#include "fs/fs.h"
#include "fs/file.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: file_pread
*
* Description:
* Equivalent to the standard pread function except that is accepts a
* struct file instance instead of a file descriptor. Currently used
* only by aio_read();
*
****************************************************************************/
ssize_t file_pread(FAR struct file *filep, FAR void *buf, size_t nbytes,
off_t offset)
{
off_t savepos;
off_t pos;
ssize_t ret;
int errcode;
/* Perform the seek to the current position. This will not move the
* file pointer, but will return its current setting
*/
savepos = file_seek(filep, 0, SEEK_CUR);
if (savepos == (off_t)-1)
{
/* file_seek might fail if this if the media is not seekable */
return VFS_ERROR;
}
/* Then seek to the correct position in the file */
pos = file_seek(filep, offset, SEEK_SET);
if (pos == (off_t)-1)
{
/* This might fail is the offset is beyond the end of file */
return VFS_ERROR;
}
/* Then perform the read operation */
ret = file_read(filep, buf, nbytes);
errcode = get_errno();
/* Restore the file position */
pos = file_seek(filep, savepos, SEEK_SET);
if (pos == (off_t)-1 && ret >= 0)
{
/* This really should not fail */
return VFS_ERROR;
}
if (errcode != 0)
{
set_errno(errcode);
}
return ret;
}
/****************************************************************************
* Name: pread
*
* Description:
* The pread() function performs the same action as read(), except that it
* reads from a given position in the file without changing the file
* pointer. The first three arguments to pread() are the same as read()
* with the addition of a fourth argument offset for the desired position
* inside the file. An attempt to perform a pread() on a file that is
* incapable of seeking results in an error.
*
* NOTE: This function could have been wholly implemented within libc but
* it is not. Why? Because if pread were implemented in libc, it would
* require four system calls. If it is implemented within the kernel,
* only three.
*
* Input Parameters:
* file File structure instance
* buf User-provided to save the data
* nbytes The maximum size of the user-provided buffer
* offset The file offset
*
* Returned Value:
* The positive non-zero number of bytes read on success, 0 on if an
* end-of-file condition, or -1 on failure with errno set appropriately.
* See read() return values
*
****************************************************************************/
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. */
int ret = fs_getfilep(fd, &filep);
if (ret < 0)
{
/* The errno value has already been set */
set_errno(-ret);
return (ssize_t)VFS_ERROR;
}
if (filep->f_oflags & O_DIRECTORY)
{
set_errno(EBADF);
return (ssize_t)VFS_ERROR;
}
/* Let file_pread do the real work */
return file_pread(filep, buf, nbytes, offset);
}
+166
View File
@@ -0,0 +1,166 @@
/****************************************************************************
* fs/vfs/fs_pread.c
*
* Copyright (C) 2014, 2016-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "sys/types.h"
#include "unistd.h"
#include "errno.h"
#include "fs/fs.h"
#include "fs/file.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: file_pread64
*
* Description:
* Equivalent to the standard pread function except that is accepts a
* struct file instance instead of a file descriptor. Currently used
* only by aio_read();
*
****************************************************************************/
ssize_t file_pread64(FAR struct file *filep, FAR void *buf, size_t nbytes,
off64_t offset)
{
off64_t savepos;
off64_t pos;
ssize_t ret;
int errcode;
/* Perform the seek to the current position. This will not move the
* file pointer, but will return its current setting
*/
savepos = file_seek64(filep, 0, SEEK_CUR);
if (savepos == (off64_t)-1)
{
/* file_seek64 might fail if this if the media is not seekable */
return VFS_ERROR;
}
/* Then seek to the correct position in the file */
pos = file_seek64(filep, offset, SEEK_SET);
if (pos == (off64_t)-1)
{
/* This might fail is the offset is beyond the end of file */
return VFS_ERROR;
}
/* Then perform the read operation */
ret = file_read(filep, buf, nbytes);
errcode = get_errno();
/* Restore the file position */
pos = file_seek64(filep, savepos, SEEK_SET);
if (pos == (off64_t)-1 && ret >= 0)
{
/* This really should not fail */
return VFS_ERROR;
}
if (errcode != 0)
{
set_errno(errcode);
}
return ret;
}
/****************************************************************************
* Name: pread64
*
* Description:
* The pread() function performs the same action as read(), except that it
* reads from a given position in the file without changing the file
* pointer. The first three arguments to pread() are the same as read()
* with the addition of a fourth argument offset for the desired position
* inside the file. An attempt to perform a pread() on a file that is
* incapable of seeking results in an error.
*
* NOTE: This function could have been wholly implemented within libc but
* it is not. Why? Because if pread were implemented in libc, it would
* require four system calls. If it is implemented within the kernel,
* only three.
*
* Input Parameters:
* file File structure instance
* buf User-provided to save the data
* nbytes The maximum size of the user-provided buffer
* offset The file offset
*
* Returned Value:
* The positive non-zero number of bytes read on success, 0 on if an
* end-of-file condition, or -1 on failure with errno set appropriately.
* See read() return values
*
****************************************************************************/
ssize_t pread64(int fd, void *buf, size_t nbytes, off64_t offset)
{
FAR struct file *filep;
/* Get the file structure corresponding to the file descriptor. */
int ret = fs_getfilep(fd, &filep);
if (ret < 0)
{
/* The errno value has already been set */
return (ssize_t)VFS_ERROR;
}
if (filep->f_oflags & O_DIRECTORY)
{
set_errno(EBADF);
return VFS_ERROR;
}
/* Let file_pread do the real work */
return file_pread64(filep, buf, nbytes, offset);
}
+171
View File
@@ -0,0 +1,171 @@
/****************************************************************************
* fs/vfs/fs_pwrite.c
*
* Copyright (C) 2014, 2016-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "sys/types.h"
#include "unistd.h"
#include "errno.h"
#include "fs/fs.h"
#include "fs/file.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: file_pwrite
*
* Description:
* Equivalent to the standard pwrite function except that is accepts a
* struct file instance instead of a file descriptor. Currently used
* only by aio_write();
*
****************************************************************************/
ssize_t file_pwrite(FAR struct file *filep, FAR const void *buf,
size_t nbytes, off_t offset)
{
off_t savepos;
off_t pos;
ssize_t ret;
int errcode;
/* Perform the seek to the current position. This will not move the
* file pointer, but will return its current setting
*/
savepos = file_seek(filep, 0, SEEK_CUR);
if (savepos == (off_t)-1)
{
/* file_seek might fail if this if the media is not seekable */
return VFS_ERROR;
}
/* Then seek to the correct position in the file */
pos = file_seek(filep, offset, SEEK_SET);
if (pos == (off_t)-1)
{
/* This might fail is the offset is beyond the end of file */
return VFS_ERROR;
}
/* Then perform the write operation */
ret = file_write(filep, buf, nbytes);
errcode = get_errno();
/* Restore the file position */
pos = file_seek(filep, savepos, SEEK_SET);
if (pos == (off_t)-1 && ret >= 0)
{
/* This really should not fail */
return VFS_ERROR;
}
if (errcode != 0)
{
set_errno(errcode);
}
return ret;
}
/****************************************************************************
* Name: pwrite
*
* Description:
* The pwrite() function performs the same action as write(), except that
* it writes into a given position without changing the file pointer. The
* first three arguments to pwrite() are the same as write() with the
* addition of a fourth argument offset for the desired position inside
* the file.
*
* NOTE: This function could have been wholly implemented within libc but
* it is not. Why? Because if pwrite were implemented in libc, it would
* require four system calls. If it is implemented within the kernel,
* only three.
*
* Input Parameters:
* fd file descriptor (or socket descriptor) to write to
* buf Data to write
* nbytes Length of data to write
*
* Returned Value:
* The positive non-zero number of bytes read on success, 0 on if an
* end-of-file condition, or -1 on failure with errno set appropriately.
* See write() return values
*
* Assumptions/Limitations:
* POSIX requires that opening a file with the O_APPEND flag should have no
* effect on the location at which pwrite() writes data. However, on NuttX
* like on Linux, if a file is opened with O_APPEND, pwrite() appends data
* to the end of the file, regardless of the value of offset.
*
****************************************************************************/
ssize_t pwrite(int fd, FAR const void *buf, size_t nbytes, off_t offset)
{
FAR struct file *filep;
/* Get the file structure corresponding to the file descriptor. */
int ret = fs_getfilep(fd, &filep);
if (ret < 0)
{
/* The errno value has already been set */
set_errno(-ret);
return (ssize_t)VFS_ERROR;
}
if (filep->f_oflags & O_DIRECTORY)
{
set_errno(EBADF);
return (ssize_t)VFS_ERROR;
}
/* Let file_pread do the real work */
return file_pwrite(filep, buf, nbytes, offset);
}
+170
View File
@@ -0,0 +1,170 @@
/****************************************************************************
* fs/vfs/fs_pwrite.c
*
* Copyright (C) 2014, 2016-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "sys/types.h"
#include "unistd.h"
#include "errno.h"
#include "fs/fs.h"
#include "fs/file.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: file_pwrite
*
* Description:
* Equivalent to the standard pwrite function except that is accepts a
* struct file instance instead of a file descriptor. Currently used
* only by aio_write();
*
****************************************************************************/
static ssize_t file_pwrite64(FAR struct file *filep, FAR const void *buf,
size_t nbytes, off64_t offset)
{
off64_t savepos;
off64_t pos;
ssize_t ret;
int errcode;
/* Perform the seek to the current position. This will not move the
* file pointer, but will return its current setting
*/
savepos = file_seek64(filep, 0, SEEK_CUR);
if (savepos == (off64_t)-1)
{
/* file_seek64 might fail if this if the media is not seekable */
return VFS_ERROR;
}
/* Then seek to the correct position in the file */
pos = file_seek64(filep, offset, SEEK_SET);
if (pos == (off64_t)-1)
{
/* This might fail is the offset is beyond the end of file */
return VFS_ERROR;
}
/* Then perform the write operation */
ret = file_write(filep, buf, nbytes);
errcode = get_errno();
/* Restore the file position */
pos = file_seek64(filep, savepos, SEEK_SET);
if (pos == (off64_t)-1 && ret >= 0)
{
/* This really should not fail */
return VFS_ERROR;
}
if (errcode != 0)
{
set_errno(errcode);
}
return ret;
}
/****************************************************************************
* Name: pwrite64
*
* Description:
* The pwrite64() function performs the same action as write(), except that
* it writes into a given position without changing the file pointer. The
* first three arguments to pwrite() are the same as write() with the
* addition of a fourth argument offset for the desired position inside
* the file.
*
* NOTE: This function could have been wholly implemented within libc but
* it is not. Why? Because if pwrite were implemented in libc, it would
* require four system calls. If it is implemented within the kernel,
* only three.
*
* Input Parameters:
* fd file descriptor (or socket descriptor) to write to
* buf Data to write
* nbytes Length of data to write
*
* Returned Value:
* The positive non-zero number of bytes read on success, 0 on if an
* end-of-file condition, or -1 on failure with errno set appropriately.
* See write() return values
*
* Assumptions/Limitations:
* POSIX requires that opening a file with the O_APPEND flag should have no
* effect on the location at which pwrite() writes data. However, on NuttX
* like on Linux, if a file is opened with O_APPEND, pwrite() appends data
* to the end of the file, regardless of the value of offset.
*
****************************************************************************/
ssize_t pwrite64(int fd, FAR const void *buf, size_t nbytes, off64_t offset)
{
FAR struct file *filep;
/* Get the file structure corresponding to the file descriptor. */
int ret = fs_getfilep(fd, &filep);
if (ret < 0)
{
/* The errno value has already been set */
return (ssize_t)VFS_ERROR;
}
if (filep->f_oflags & O_DIRECTORY)
{
set_errno(EBADF);
return VFS_ERROR;
}
/* Let file_pread do the real work */
return file_pwrite64(filep, buf, nbytes, offset);
}
+234
View File
@@ -0,0 +1,234 @@
/****************************************************************************
* fs/vfs/fs_read.c
*
* Copyright (C) 2007-2009, 2012-2014, 2016-2017 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "sys/types.h"
#include "sys/socket.h"
#include "console.h"
#include "unistd.h"
#include "fcntl.h"
#include "sched.h"
#include "assert.h"
#include "errno.h"
#include "user_copy.h"
#include "inode/inode.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: file_read
*
* Description:
* file_read() is an interanl OS interface. It is functionally similar to
* the standard read() 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 - User-provided to save the data
* nbytes - The maximum size of the user-provided buffer
*
* Returned Value:
* The positive non-zero number of bytes read on success, 0 on if an
* end-of-file condition, or a negated errno value on any failure.
*
****************************************************************************/
ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes)
{
FAR struct inode *inode = NULL;
int ret = -EBADF;
DEBUGASSERT(filep);
inode = filep->f_inode;
if (buf == NULL)
{
ret = -EFAULT;
}
/* Was this file opened for read access? */
else if (((unsigned int)(filep->f_oflags) & O_ACCMODE) == O_WRONLY)
{
/* No.. File is not read-able */
ret = -EACCES;
}
/* Is a driver or mountpoint registered? If so, does it support the read
* method?
*/
else if (inode && inode->u.i_ops && inode->u.i_ops->read)
{
/* Yes.. then let it perform the read. NOTE that for the case of the
* mountpoint, we depend on the read methods being identical in
* signature and position in the operations vtable.
*/
ret = (int)inode->u.i_ops->read(filep, (char *)buf, (size_t)nbytes);
}
/* If an error occurred, set errno and return -1 (ERROR) */
if (ret < 0)
{
set_errno(-ret);
return VFS_ERROR;
}
/* Otherwise, return the number of bytes read */
return ret;
}
/****************************************************************************
* Name: read
*
* Description:
* The standard, POSIX read interface.
*
* Input Parameters:
* fd - File descriptor to read from
* buf - User-provided to save the data
* nbytes - The maximum size of the user-provided buffer
*
* Returned Value:
* The positive non-zero number of bytes read on success, 0 on if an
* end-of-file condition, or -1 on failure with errno set appropriately.
*
****************************************************************************/
ssize_t read(int fd, FAR void *buf, size_t nbytes)
{
/* Did we get a valid file descriptor? */
#if CONFIG_NFILE_DESCRIPTORS > 0
FAR struct file *filep = NULL;
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
#endif
{
/* No.. If networking is enabled, read() is the same as recv() with
* the flags parameter set to zero.
*/
#if defined(LOSCFG_NET_LWIP_SACK)
FAR void *bufbak = buf;
ssize_t ret;
if (LOS_IsUserAddress((VADDR_T)(uintptr_t)buf))
{
if (buf != NULL && nbytes > 0)
{
buf = malloc(nbytes);
if (buf == NULL)
{
set_errno(ENOMEM);
return VFS_ERROR;
}
}
}
ret = recv(fd, buf, nbytes, 0);
if (ret > 0 && buf != bufbak)
{
if (LOS_ArchCopyToUser(bufbak, buf, ret) != 0)
{
/* data lost here */
set_errno(EFAULT);
ret = VFS_ERROR;
}
}
if (buf != bufbak)
{
free(buf);
}
return ret;
#else
/* No networking... it is a bad descriptor in any event */
set_errno(EBADF);
return VFS_ERROR;
#endif
}
#if CONFIG_NFILE_DESCRIPTORS > 0
else
{
if (fd <= STDERR_FILENO && fd >= STDIN_FILENO) /* fd : [0,2] */
{
fd = ConsoleUpdateFd();
if (fd < 0)
{
set_errno(EBADF);
return VFS_ERROR;
}
}
/* The descriptor is in a valid range to file descriptor... do the
* read. First, get the file structure.
*/
int ret = fs_getfilep(fd, &filep);
if (ret < 0)
{
/* The errno value has already been set */
return VFS_ERROR;
}
if (filep->f_oflags & O_DIRECTORY)
{
set_errno(EBADF);
return VFS_ERROR;
}
/* Then let file_read do all of the work */
return file_read(filep, buf, nbytes);
}
#endif
}
+314
View File
@@ -0,0 +1,314 @@
/****************************************************************************
* fs/vfs/fs_rename.c
*
* Copyright (C) 2007-2009, 2014, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "stdio.h"
#include "errno.h"
#include "fs/fs.h"
#include "stdlib.h"
#include "inode/inode.h"
#include "fs_other.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#undef FS_HAVE_WRITABLE_MOUNTPOINT
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_WRITABLE) && \
CONFIG_NFILE_STREAMS > 0
# define FS_HAVE_WRITABLE_MOUNTPOINT 1
#endif
#undef FS_HAVE_PSEUDOFS_OPERATIONS
#if !defined(CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && CONFIG_NFILE_STREAMS > 0
# define FS_HAVE_PSEUDOFS_OPERATIONS 1
#endif
#undef FS_HAVE_RENAME
#if defined(FS_HAVE_WRITABLE_MOUNTPOINT) || defined(FS_HAVE_PSEUDOFS_OPERATIONS)
# define FS_HAVE_RENAME 1
#endif
#ifdef FS_HAVE_RENAME
/****************************************************************************
* Public Functions
****************************************************************************/
int do_rename(int oldfd, FAR const char *oldpath, int newfd, FAR const char *newpath)
{
FAR struct inode *oldinode;
FAR struct inode *newinode;
const char *oldrelpath = NULL;
char *fulloldpath = NULL;
char *fulloldpath_bak = NULL;
char *fullnewpath = NULL;
char *fullnewpath_bak = NULL;
#ifndef CONFIG_DISABLE_MOUNTPOINT
const char *newrelpath = NULL;
#endif
int errcode = ENOERR;
int ret;
struct inode_search_s old_desc, new_desc;
/* Ignore paths that are interpreted as the root directory which has no name
* and cannot be moved
*/
if (!oldpath || *oldpath == '\0' ||
!newpath || *newpath == '\0')
{
errcode = EINVAL;
goto errout;
}
ret = vfs_normalize_pathat(oldfd, oldpath, &fulloldpath);
if (ret < 0)
{
errcode = -ret;
goto errout;
}
fulloldpath_bak = fulloldpath;
ret = vfs_normalize_pathat(newfd, newpath, &fullnewpath);
if (ret < 0)
{
errcode = -ret;
goto errout_with_path;
}
fullnewpath_bak = fullnewpath;
/* Get an inode that includes the oldpath */
SETUP_SEARCH(&old_desc, fulloldpath, false);
ret = inode_find(&old_desc);
if (ret < 0)
{
errcode = EACCES;
free(fullnewpath_bak);
goto errout_with_path;
}
oldinode = old_desc.node;
oldrelpath = old_desc.relpath;
#ifndef CONFIG_DISABLE_MOUNTPOINT
/* Verify that the old inode is a valid mountpoint. */
if (INODE_IS_MOUNTPT(oldinode) && oldinode->u.i_mops)
{
/* Get an inode for the new relpath -- it should like on the same
* mountpoint
*/
SETUP_SEARCH(&new_desc, fullnewpath, false);
ret = inode_find(&new_desc);
if (ret < 0)
{
errcode = EACCES;
goto errout_with_oldinode;
}
newinode = new_desc.node;
newrelpath = new_desc.relpath;
/* Verify that the two paths lie on the same mountpoint inode */
if (oldinode != newinode)
{
errcode = EXDEV;
goto errout_with_newinode;
}
/* Perform the rename operation using the relative paths
* at the common mountpoint.
*/
if (oldinode->u.i_mops->rename)
{
ret = oldinode->u.i_mops->rename(oldinode, oldrelpath, newrelpath);
if (ret < 0)
{
errcode = -ret;
goto errout_with_newinode;
}
}
else
{
errcode = ENOSYS;
goto errout_with_newinode;
}
/* Successfully renamed */
inode_release(newinode);
}
else
#endif
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
{
/* Create a new, empty inode at the destination location */
if (VfsPermissionCheck(old_desc.parent->i_uid, old_desc.parent->i_gid,
old_desc.parent->i_mode, EXEC_OP | WRITE_OP))
{
ret = EACCES;
goto errout_with_oldinode;
}
SETUP_SEARCH(&new_desc, fullnewpath, false);
ret = inode_find(&new_desc);
if (ret < 0)
{
errcode = EACCES;
goto errout_with_oldinode;
}
newinode = new_desc.node;
newrelpath = new_desc.relpath;
if (VfsPermissionCheck(new_desc.parent->i_uid, new_desc.parent->i_gid,
new_desc.parent->i_mode, EXEC_OP | WRITE_OP))
{
ret = EACCES;
goto errout_with_oldinode;
}
inode_semtake();
ret = inode_reserve(fullnewpath, &newinode);
if (ret < 0)
{
/* It is an error if a node at newpath already exists in the tree
* OR if we fail to allocate memory for the new inode (and possibly
* any new intermediate path segments).
*/
inode_semgive();
errcode = EEXIST;
goto errout_with_oldinode;
}
/* Copy the inode state from the old inode to the newly allocated inode */
newinode->i_child = oldinode->i_child; /* Link to lower level inode */
newinode->i_flags = oldinode->i_flags; /* Flags for inode */
newinode->u.i_ops = oldinode->u.i_ops; /* Inode operations */
#ifdef LOSCFG_FILE_MODE
newinode->i_mode = oldinode->i_mode; /* Access mode flags */
#endif
newinode->i_private = oldinode->i_private; /* Per inode driver private data */
/* We now have two copies of the inode. One with a reference count of
* zero (the new one), and one that may have multiple references
* including one by this logic (the old one)
*
* 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() should return
* -EBUSY to indicate that the inode was not deleted now.
*/
ret = inode_remove(fulloldpath);
if (ret < 0 && ret != -EBUSY)
{
/* Remove the new node we just recreated */
(void)inode_remove(fullnewpath);
inode_semgive();
errcode = -ret;
goto errout_with_oldinode;
}
/* Remove all of the children from the unlinked inode */
oldinode->i_child = NULL;
inode_semgive();
}
#else
{
errcode = ENXIO;
goto errout_with_oldinode;
}
#endif
/* rename file page cache mapping if necessary */
rename_mapping(fulloldpath, fullnewpath);
/* Successfully renamed */
inode_release(oldinode);
free(fulloldpath_bak);
free(fullnewpath_bak);
return OK;
#ifndef CONFIG_DISABLE_MOUNTPOINT
errout_with_newinode:
inode_release(newinode);
#endif
errout_with_oldinode:
inode_release(oldinode);
free(fullnewpath_bak);
errout_with_path:
free(fulloldpath_bak);
errout:
set_errno(errcode);
return VFS_ERROR;
}
/****************************************************************************
* Name: rename
*
* Description: Rename a file managed a mountpoint
*
****************************************************************************/
int rename(FAR const char *oldpath, FAR const char *newpath)
{
return do_rename(AT_FDCWD, oldpath, AT_FDCWD, newpath);
}
/****************************************************************************
* Name: renameat
*
* Description: Rename a file managed a mountpoint with relatively fds.
*
****************************************************************************/
int renameat(int oldfd, FAR const char *oldpath, int newdfd, FAR const char *newpath)
{
return do_rename(oldfd, oldpath, newdfd, newpath);
}
#endif /* FS_HAVE_RENAME */
+235
View File
@@ -0,0 +1,235 @@
/****************************************************************************
* fs/vfs/fs_rmdir.c
*
* Copyright (C) 2007-2009, 2014, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "unistd.h"
#include "errno.h"
#include "fs/fs.h"
#include "stdlib.h"
#include "inode/inode.h"
#include "sys/stat.h"
#include "string.h"
#include "fs_other.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#undef FS_HAVE_WRITABLE_MOUNTPOINT
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_WRITABLE) && \
CONFIG_NFILE_STREAMS > 0
# define FS_HAVE_WRITABLE_MOUNTPOINT 1
#endif
#undef FS_HAVE_PSEUDOFS_OPERATIONS
#if !defined(CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && CONFIG_NFILE_STREAMS > 0
# define FS_HAVE_PSEUDOFS_OPERATIONS 1
#endif
#undef FS_HAVE_RMDIR
#if defined(FS_HAVE_WRITABLE_MOUNTPOINT) || defined(FS_HAVE_PSEUDOFS_OPERATIONS)
# define FS_HAVE_RMDIR 1
#endif
#ifdef FS_HAVE_RMDIR
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: do_rmdir
*
* Description: Remove a file managed a mountpoint
*
****************************************************************************/
int do_rmdir(int dirfd, FAR const char *pathname)
{
FAR struct inode *inode;
const char *relpath = NULL;
int errcode;
char *fullpath = NULL;
char *relativepath = NULL;
int ret;
struct inode_search_s desc;
/* Get relative path by dirfd*/
ret = get_path_from_fd(dirfd, &relativepath);
if (ret < 0)
{
errcode = ret;
goto errout;
}
ret = vfs_normalize_path((const char *)relativepath, pathname, &fullpath);
if (relativepath)
{
free(relativepath);
}
if (ret < 0)
{
errcode = -ret;
goto errout;
}
/* Get an inode for this file. inode_find() automatically increments the
* reference count on the inode if one is found.
*/
SETUP_SEARCH(&desc, fullpath, false);
ret = inode_find(&desc);
if (ret < 0)
{
free(fullpath);
errcode = EACCES;
goto errout;
}
inode = desc.node;
relpath = desc.relpath;
#ifndef CONFIG_DISABLE_MOUNTPOINT
/* Check if the inode is a valid mountpoint. */
if (INODE_IS_MOUNTPT(inode) && inode->u.i_mops)
{
/* Perform the rmdir operation using the relative path
* from the mountpoint.
*/
if (inode->u.i_mops->rmdir)
{
if (!strlen(relpath))
{
errcode = EPERM;
goto errout_with_inode;
}
ret = inode->u.i_mops->rmdir(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-directory node (i.e., it has no
* operations) then rmdir should remove the node.
*/
if (!inode->u.i_ops)
{
/* If the directory inode has children, however, then it cannot be
* removed.
*/
if (inode->i_child)
{
errcode = ENOTEMPTY;
goto errout_with_inode;
}
/* Remove the inode. NOTE: Because we hold a reference count on the
* inode, it will not be deleted now. But probably when inode_release()
* is called below. inode_remove should return -EBUSY to indicate that
* the inode was not deleted now.
*/
if (VfsPermissionCheck(desc.parent->i_uid, desc.parent->i_gid, desc.parent->i_mode, EXEC_OP | WRITE_OP))
{
errcode = EACCES;
goto errout_with_inode;
}
inode_semtake();
ret = inode_remove(fullpath);
inode_semgive();
if (ret < 0 && ret != -EBUSY)
{
errcode = -ret;
goto errout_with_inode;
}
}
else
{
errcode = ENOTDIR;
goto errout_with_inode;
}
#else
{
errcode = ENXIO;
goto errout_with_inode;
}
#endif
/* Successfully removed the directory */
inode_release(inode);
free(fullpath);
return OK;
errout_with_inode:
inode_release(inode);
free(fullpath);
errout:
set_errno(errcode);
return VFS_ERROR;
}
/****************************************************************************
* Name: rmdir
*
* Description: Remove a file managed a mountpoint
*
****************************************************************************/
int rmdir(FAR const char *pathname)
{
return do_rmdir(AT_FDCWD, pathname);
}
#endif /* FS_HAVE_RMDIR */
+340
View File
@@ -0,0 +1,340 @@
/****************************************************************************
* fs/vfs/fs_select.c
*
* Copyright (C) 2008-2009, 2012-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "sys/select.h"
#include "string.h"
#include "unistd.h"
#include "poll.h"
#include "assert.h"
#include "errno.h"
#include "debug.h"
#include "stdlib.h"
#include "fs/fs.h"
#include "los_syscall.h"
#include "inode/inode.h"
#ifndef CONFIG_DISABLE_POLL
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define POLL_IN_SET (POLLIN | POLLRDNORM | POLLRDBAND | POLLHUP | POLLERR)
#define POLL_OUT_SET (POLLOUT | POLLWRBAND | POLLWRNORM | POLLERR)
#define POLL_EX_SET (POLLPRI)
/* pollfd count in stack, optimization in order to avoid small memory allocation */
#define POLL_STACK_CNT 5
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
extern unsigned int sleep(unsigned int seconds);
/****************************************************************************
* Name: select
*
* Description:
* select() allows a program to monitor multiple file descriptors, waiting
* until one or more of the file descriptors become "ready" for some class
* of I/O operation (e.g., input possible). A file descriptor is
* considered ready if it is possible to perform the corresponding I/O
* operation (e.g., read(2)) without blocking.
*
* NOTE: poll() is the fundamental API for performing such monitoring
* operation under NuttX. select() is provided for compatibility and
* is simply a layer of added logic on top of poll(). As such, select()
* is more wasteful of resources and poll() is the recommended API to be
* used.
*
* Input Parameters:
* nfds - the maximum fd number (+1) of any descriptor in any of the
* three sets.
* readfds - the set of descriptions to monitor for read-ready events
* writefds - the set of descriptions to monitor for write-ready events
* exceptfds - the set of descriptions to monitor for error events
* timeout - Return at this time if none of these events of interest
* occur.
*
* Returned Value:
* 0: Timer expired
* >0: The number of bits set in the three sets of descriptors
* -1: An error occurred (errno will be set appropriately)
*
****************************************************************************/
int do_select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout, PollFun poll)
{
struct pollfd *pollset = NULL;
struct pollfd pfd[POLL_STACK_CNT];
int pfd_alloc_flag = 0;
int fd;
int npfds;
int msec;
int ndx;
int ret;
if (nfds < 0)
{
set_errno(EINVAL);
return VFS_ERROR;
}
/* How many pollfd structures do we need to allocate? */
/* Initialize the descriptor list for poll() */
for (fd = 0, npfds = 0; fd < nfds; fd++)
{
/* Check if any monitor operation is requested on this fd */
if ((readfds && FD_ISSET(fd, readfds)) ||
(writefds && FD_ISSET(fd, writefds)) ||
(exceptfds && FD_ISSET(fd, exceptfds)))
{
/* Yes.. increment the count of pollfds structures needed */
npfds++;
}
}
/* Allocate the descriptor list for poll() */
if (npfds != 0)
{
/* use stack variable in order to avoid small memory allocation. */
if (npfds <= POLL_STACK_CNT)
{
pollset = pfd;
(void)memset_s(pollset, npfds * sizeof(struct pollfd), 0, npfds * sizeof(struct pollfd));
}
else
{
pollset = (struct pollfd *)zalloc(npfds * sizeof(struct pollfd));
if (pollset == NULL)
{
set_errno(ENOMEM);
return VFS_ERROR;
}
pfd_alloc_flag = 1;
}
}
else
{
/* If the readfds, writefds, and exceptfds arguments are all null pointers and
* the timeout argument is not a null pointer, the select() function shall block for
* the time specified. If the readfds, writefds, and exceptfds arguments are all
* null pointers and the timeout argument is a null pointer, this is NOT permitted
* as LiteOS doesn't support Signal machanism, so select() can't come back anymore.
*/
if (timeout != NULL)
{
/* 1000000 : Convert seconds to microseconds. */
if ((long long)timeout->tv_sec * 1000000 > 0xffffffff)
{
(void)sleep(timeout->tv_sec);
}
else
{
(void)usleep(timeout->tv_sec * 1000000 + timeout->tv_usec);
}
return OK;
}
else
{
set_errno(EINVAL);
return VFS_ERROR;
}
}
/* Initialize the descriptor list for poll() */
for (fd = 0, ndx = 0; fd < nfds; fd++)
{
int incr = 0;
/* The readfs set holds the set of FDs that the caller can be assured
* of reading from without blocking. Note that POLLHUP is included as
* a read-able condition. POLLHUP will be reported at the end-of-file
* or when a connection is lost. In either case, the read() can then
* be performed without blocking.
*/
if (readfds && FD_ISSET(fd, readfds))
{
pollset[ndx].fd = fd;
pollset[ndx].events |= (POLLIN | POLLRDNORM);
incr = 1;
}
/* The writefds set holds the set of FDs that the caller can be assured
* of writing to without blocking.
*/
if (writefds && FD_ISSET(fd, writefds))
{
pollset[ndx].fd = fd;
pollset[ndx].events |= (POLLOUT | POLLWRNORM);
incr = 1;
}
/* The exceptfds set holds the set of FDs that are watched for exceptions */
if (exceptfds && FD_ISSET(fd, exceptfds))
{
pollset[ndx].fd = fd;
incr = 1;
}
ndx += incr;
}
DEBUGASSERT(ndx == npfds);
/* Convert the timeout to milliseconds */
if (timeout)
{
/* Calculate the timeout in milliseconds */
msec = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
}
else
{
/* Any negative value of msec means no timeout */
msec = -1;
}
/* Then let poll do all of the real work. */
ret = poll(pollset, npfds, msec);
/* Now set up the return values */
if (readfds)
{
(void)memset_s(readfds, sizeof(fd_set), 0, sizeof(fd_set));
}
if (writefds)
{
(void)memset_s(writefds, sizeof(fd_set), 0, sizeof(fd_set));
}
if (exceptfds)
{
(void)memset_s(exceptfds, sizeof(fd_set), 0, sizeof(fd_set));
}
/* Convert the poll descriptor list back into selects 3 bitsets */
if (ret > 0)
{
ret = 0;
for (ndx = 0; ndx < npfds; ndx++)
{
/* Check for read conditions. Note that POLLHUP is included as a
* read condition. POLLHUP will be reported when no more data will
* be available (such as when a connection is lost). In either
* case, the read() can then be performed without blocking.
*/
if (readfds)
{
if (pollset[ndx].revents & POLL_IN_SET)
{
FD_SET(pollset[ndx].fd, readfds);
ret++;
}
}
/* Check for write conditions */
if (writefds)
{
if (pollset[ndx].revents & POLL_OUT_SET)
{
FD_SET(pollset[ndx].fd, writefds);
ret++;
}
}
/* Check for exceptions */
if (exceptfds)
{
if (pollset[ndx].revents & POLL_EX_SET)
{
FD_SET(pollset[ndx].fd, exceptfds);
ret++;
}
}
}
}
if (pfd_alloc_flag)
{
free(pollset);
}
return ret;
}
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout)
{
return do_select(nfds, readfds, writefds, exceptfds, timeout, poll);
}
#endif /* CONFIG_DISABLE_POLL */
+290
View File
@@ -0,0 +1,290 @@
/****************************************************************************
* fs/vfs/fs_sendfile.c
*
* Copyright (C) 2007, 2009, 2011, 2013, 2017-2018 Gregory Nutt. All
* rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include <fs/file.h>
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fs/fs.h>
#ifndef CONFIG_LIB_SENDFILE_BUFSIZE
# define CONFIG_LIB_SENDFILE_BUFSIZE 512
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: sendfile
*
* Description:
* sendfile() copies data between one file descriptor and another.
* Used with file descriptors it basically just wraps a sequence of
* reads() and writes() to perform a copy.
*
* If the destination descriptor is a socket, it gives a better
* performance than simple reds() and writes(). The data is read directly
* into the net buffer and the whole tcp window is filled if possible.
*
* NOTE: This interface is *not* specified in POSIX.1-2001, or other
* standards. The implementation here is very similar to the Linux
* sendfile interface. Other UNIX systems implement sendfile() with
* different semantics and prototypes. sendfile() should not be used
* in portable programs.
*
* Input Parameters:
* infd - A file (or socket) descriptor opened for reading
* outfd - A descriptor opened for writing.
* offset - If 'offset' is not NULL, then it points to a variable
* holding the file offset from which sendfile() will start
* reading data from 'infd'. When sendfile() returns, this
* variable will be set to the offset of the byte following
* the last byte that was read. If 'offset' is not NULL,
* then sendfile() does not modify the current file offset of
* 'infd'; otherwise the current file offset is adjusted to
* reflect the number of bytes read from 'infd.'
*
* If 'offset' is NULL, then data will be read from 'infd'
* starting at the current file offset, and the file offset
* will be updated by the call.
* count - The number of bytes to copy between the file descriptors.
*
* Returned Value:
* If the transfer was successful, the number of bytes written to outfd is
* returned. On error, -1 is returned, and errno is set appropriately.
* There error values are those returned by read() or write() plus:
*
* EINVAL - Bad input parameters.
* ENOMEM - Could not allocated an I/O buffer
*
****************************************************************************/
ssize_t sendfile(int outfd, int infd, off_t *offset, size_t count)
{
FAR uint8_t *iobuffer;
FAR uint8_t *wrbuffer;
off_t startpos = 0;
ssize_t nbytesread;
ssize_t nbyteswritten;
size_t ntransferred;
bool endxfr;
/* Get the current file position. */
if (offset)
{
/* Use lseek to get the current file position */
startpos = lseek(infd, 0, SEEK_CUR);
if (startpos == (off_t)-1)
{
return VFS_ERROR;
}
/* Use lseek again to set the new file position */
if (lseek(infd, *offset, SEEK_SET) == (off_t)-1)
{
return VFS_ERROR;
}
}
/* Allocate an I/O buffer */
iobuffer = (FAR void *)malloc(CONFIG_LIB_SENDFILE_BUFSIZE);
if (!iobuffer)
{
set_errno(ENOMEM);
return VFS_ERROR;
}
/* Now transfer 'count' bytes from the infd to the outfd */
for (ntransferred = 0, endxfr = false; ntransferred < count && !endxfr; )
{
/* Loop until the read side of the transfer comes to some conclusion */
do
{
/* Read a buffer of data from the infd */
nbytesread = read(infd, iobuffer, CONFIG_LIB_SENDFILE_BUFSIZE);
/* Check for end of file */
if (nbytesread == 0)
{
/* End of file. Break out and return current number of bytes
* transferred.
*/
endxfr = true;
break;
}
/* Check for a read ERROR. EINTR is a special case. This function
* should break out and return an error if EINTR is returned and
* no data has been transferred. But what should it do if some
* data has been transferred? I suppose just continue?
*/
else if (nbytesread < 0)
{
int errcode = get_errno();
/* EINTR is not an error (but will still stop the copy) */
if (errcode != EINTR || ntransferred == 0)
{
/* Read error. Break out and return the error condition. */
set_errno(errcode);
ntransferred = VFS_ERROR;
endxfr = true;
break;
}
}
}
while (nbytesread < 0);
/* Was anything read? */
if (!endxfr)
{
/* Yes.. Loop until the read side of the transfer comes to some
* conclusion.
*/
wrbuffer = iobuffer;
do
{
/* Write the buffer of data to the outfd */
nbyteswritten = write(outfd, wrbuffer, nbytesread);
/* Check for a complete (or parial) write. write() should not
* return zero.
*/
if (nbyteswritten >= 0)
{
/* Advance the buffer pointer and decrement the number of bytes
* remaining in the iobuffer. Typically, nbytesread will now
* be zero.
*/
wrbuffer += nbyteswritten;
nbytesread -= nbyteswritten;
/* Increment the total number of bytes successfully transferred. */
ntransferred += nbyteswritten;
}
/* Otherwise an error occurred */
else
{
int errcode = get_errno();
/* Check for a read ERROR. EINTR is a special case. This
* function should break out and return an error if EINTR
* is returned and no data has been transferred. But what
* should it do if some data has been transferred? I
* suppose just continue?
*/
if (errcode != EINTR || ntransferred == 0)
{
/* Write error. Break out and return the error
* condition.
*/
set_errno(errcode);
ntransferred = VFS_ERROR;
endxfr = true;
break;
}
}
}
while (nbytesread > 0);
}
}
/* Release the I/O buffer */
free(iobuffer);
/* Return the current file position */
if (offset)
{
/* Use lseek to get the current file position */
off_t curpos = lseek(infd, 0, SEEK_CUR);
if (curpos == (off_t)-1)
{
return VFS_ERROR;
}
/* Return the current file position */
*offset = curpos;
/* Use lseek again to restore the original file position */
if (lseek(infd, startpos, SEEK_SET) == (off_t)-1)
{
return VFS_ERROR;
}
}
/* Finally return the number of bytes actually transferred (or VFS_ERROR
* if any failure occurred).
*/
return ntransferred;
}
+270
View File
@@ -0,0 +1,270 @@
/****************************************************************************
* fs/vfs/fs_stat.c
*
* Copyright (C) 2007-2009, 2012, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "errno.h"
#include "sys/stat.h"
#include "string.h"
#include "stdlib.h"
#include "inode/inode.h"
#include "fs_other.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: statpseudo
****************************************************************************/
static inline int statpseudo(FAR struct inode *inode, FAR struct stat *buf)
{
/* Most of the stat entries just do not apply */
(void)memset_s(buf, sizeof(struct stat), 0, sizeof(struct stat));
buf->st_mode |= inode->i_mode;
buf->st_uid = inode->i_uid;
buf->st_gid = inode->i_gid;
if (INODE_IS_SPECIAL(inode))
{
#if defined(CONFIG_FS_NAMED_SEMAPHORES)
if (INODE_IS_NAMEDSEM(inode))
{
buf->st_mode = S_IFSEM;
}
else
#endif
#if !defined(CONFIG_DISABLE_MQUEUE)
if (INODE_IS_MQUEUE(inode))
{
buf->st_mode = S_IFMQ;
}
else
#endif
#if defined(CONFIG_FS_SHM)
if (INODE_IS_SHM(inode))
{
buf->st_mode = S_IFSHM;
}
else
#endif
{
}
}
else if (inode->u.i_ops)
{
/* Determine the type of the inode */
if (INODE_IS_MOUNTPT(inode))
{
buf->st_mode |= S_IFDIR;
}
else if (INODE_IS_BLOCK(inode))
{
/* What is if also has child inodes? */
buf->st_mode |= S_IFBLK;
}
else /* if (INODE_IS_DRIVER(inode)) */
{
/* What is it if it also has child inodes? */
buf->st_mode |= S_IFCHR;
}
}
else
{
/* If it has no operations, then it must just be a intermediate
* node in the inode tree. It is something like a directory.
* We'll say that all pseudo-directories are read-able but not
* write-able.
*/
buf->st_mode |= S_IFDIR | inode->i_mode;
}
return OK;
}
/****************************************************************************
* Name: statroot
****************************************************************************/
static inline int statroot(FAR struct stat *buf)
{
/* There is no inode associated with the fake root directory */
(void)memset_s(buf, sizeof(struct stat), 0, sizeof(struct stat));
buf->st_mode = S_IFDIR | S_IROTH | S_IRGRP | S_IRUSR;
return OK;
}
/****************************************************************************
* Global Functions
****************************************************************************/
/****************************************************************************
* Name: stat
*
* Returned Value:
* Zero on success; -1 on failure with errno set:
*
* EACCES Search permission is denied for one of the directories in the
* path prefix of path.
* EFAULT Bad address.
* ENOENT A component of the path path does not exist, or the path is an
* empty string.
* ENOMEM Out of memory
* ENOTDIR A component of the path is not a directory.
*
****************************************************************************/
int stat(FAR const char *path, FAR struct stat *buf)
{
FAR struct inode *inode;
const char *relpath = NULL;
int ret = OK;
char *fullpath = NULL;
struct inode_search_s desc;
/* Sanity checks */
if (!path || !buf)
{
ret = EFAULT;
goto errout;
}
if (!path[0])
{
ret = ENOENT;
goto errout;
}
ret = vfs_normalize_path((const char *)NULL, path, &fullpath);
if (ret < 0)
{
ret = -ret;
goto errout;
}
/* Check for the fake root directory (which has no inode) */
if (strcmp(fullpath, "/") == 0)
{
free(fullpath);
return statroot(buf);
}
/* Get an inode for this file */
SETUP_SEARCH(&desc, fullpath, false);
ret = inode_find(&desc);
if (ret < 0)
{
ret = EACCES;
goto errout_with_path;
}
inode = desc.node;
relpath = desc.relpath;
/* 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 node is a file system mointpoint. Verify that the mountpoint
* supports the stat() method
*/
if (inode->u.i_mops && inode->u.i_mops->stat)
{
/* Perform the stat() operation */
ret = inode->u.i_mops->stat(inode, relpath, buf);
}
else
{
ret = ENOSYS;
}
}
else
#endif
{
/* The node is part of the root pseudo file system */
if (VfsPermissionCheck(desc.parent->i_uid, desc.parent->i_gid, desc.parent->i_mode, EXEC_OP))
{
ret = EACCES;
goto errout_with_inode;
}
ret = statpseudo(inode, buf);
}
/* Check if the stat operation was successful */
if (ret < 0)
{
ret = -ret;
goto errout_with_inode;
}
/* Successfully stat'ed the file */
inode_release(inode);
free(fullpath);
return OK;
/* Failure conditions always set the errno appropriately */
errout_with_inode:
inode_release(inode);
errout_with_path:
free(fullpath);
errout:
set_errno(ret);
return VFS_ERROR;
}
int isatty(int fd)
{
return 0;
}
+171
View File
@@ -0,0 +1,171 @@
/****************************************************************************
* fs/vfs/fs_statfs.c
*
* Copyright (C) 2007-2009, 2012, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "sys/statfs.h"
#include "string.h"
#include "sched.h"
#include "inode/inode.h"
#include "errno.h"
#include "stdlib.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: statpseudo
****************************************************************************/
static inline int statpseudofs(FAR struct inode *inode, FAR struct statfs *buf)
{
(void)memset_s(buf, sizeof(struct statfs), 0, sizeof(struct statfs));
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: statfs
*
* Returned Value:
* Zero on success; -1 on failure with errno set:
*
* EACCES Search permission is denied for one of the directories in the
* path prefix of path.
* EFAULT Bad address.
* ENOENT A component of the path path does not exist, or the path is an
* empty string.
* ENOMEM Out of memory
* ENOTDIR A component of the path is not a directory.
* ENOSYS The file system does not support this call.
*
****************************************************************************/
int statfs(FAR const char *path, FAR struct statfs *buf)
{
FAR struct inode *inode;
int ret = OK;
char *fullpath = NULL;
struct inode_search_s desc;
/* Sanity checks */
if (!path || !buf)
{
ret = EFAULT;
goto errout;
}
if (!path[0])
{
ret = ENOENT;
goto errout;
}
ret = vfs_normalize_path((const char *)NULL, path, &fullpath);
if (ret < 0)
{
ret = -ret;
goto errout;
}
/* Get an inode for this file */
SETUP_SEARCH(&desc, fullpath, false);
ret = inode_find(&desc);
if (ret < 0)
{
ret = EACCES;
free(fullpath);
goto errout;
}
inode = desc.node;
/* The way we handle the statfs depends on the type of inode that we
* are dealing with.
*/
#ifndef CONFIG_DISABLE_MOUNTPOINT
if (INODE_IS_MOUNTPT(inode))
{
/* The node is a file system mointpoint. Verify that the mountpoint
* supports the statfs() method
*/
if (inode->u.i_mops && inode->u.i_mops->statfs)
{
/* Perform the statfs() operation */
ret = inode->u.i_mops->statfs(inode, buf);
}
}
else
#endif
{
/* The node is part of the root pseudo file system */
ret = statpseudofs(inode, buf);
}
/* Check if the statfs operation was successful */
if (ret < 0)
{
ret = -ret;
goto errout_with_inode;
}
/* Successfully statfs'ed the file */
inode_release(inode);
free(fullpath);
return OK;
/* Failure conditions always set the errno appropriately */
errout_with_inode:
inode_release(inode);
free(fullpath);
errout:
set_errno(ret);
return VFS_ERROR;
}
+193
View File
@@ -0,0 +1,193 @@
/****************************************************************************
* fs/vfs/fs_truncate.c
*
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "sys/types.h"
#include "unistd.h"
#include "fcntl.h"
#include "sched.h"
#include "assert.h"
#include "errno.h"
#include "inode/inode.h"
/****************************************************************************
* Name: file_truncate
*
* Description:
* Equivalent to the standard ftruncate() function except that is accepts
* a struct file instance instead of a file descriptor and it does not set
* the errno variable.
*
****************************************************************************/
static int file_truncate(FAR struct file *filep, off_t length)
{
FAR struct inode *inode = NULL;
int ret;
int err;
/* Was this file opened for write access? */
if (((unsigned int)(filep->f_oflags) & O_ACCMODE) == O_RDONLY)
{
err = EACCES;
goto errout;
}
/* Is this inode a registered mountpoint? Does it support the
* truncate operations may be relevant to device drivers but only
* the mountpoint operations vtable contains a truncate method.
*/
inode = filep->f_inode;
if (!inode || !inode->u.i_mops || !inode->u.i_mops->truncate)
{
err = EBADF;
goto errout;
}
/* Does the file system support the truncate method? It should if it is
* a write-able file system.
*/
ret = inode->u.i_mops->truncate(filep, length);
if (ret < 0)
{
err = -ret;
goto errout;
}
return ret;
errout:
set_errno(err);
return VFS_ERROR;
}
/****************************************************************************
* Name: ftruncate
*
* Description:
* The ftruncate() function causes the regular file referenced by fd to
* have a size of length bytes.
*
* If the file previously was larger than length, the extra data is
* discarded. If it was previously shorter than length, it is unspecified
* whether the file is changed or its size increased. If the file is
* extended, the extended area appears as if it were zero-filled. If fd
* references a shared memory object, ftruncate() sets the size of the
* shared memory object to length. If the file is not a regular file or
* a shared memory object, the result is unspecified.
* With ftruncate(), the file must be open for writing; for truncate(),
* the process must have write permission for the file.
*
* ftruncate() does not modify the file offset for any open file
* descriptions associated with the file.
*
* Input Parameters:
* fd - A reference to an open, regular file or shared memory object
* to be truncated.
* length - The new length of the file or shared memory object.
*
* Returned Value:
* On success, 0.
* On error, -1 is returned, and errno is set appro-priately:
*
*
****************************************************************************/
int ftruncate(int fd, off_t length)
{
#if CONFIG_NFILE_DESCRIPTORS > 0
FAR struct file *filep = NULL;
#endif
/* Did we get a valid file descriptor? */
#if CONFIG_NFILE_DESCRIPTORS > 0
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
#endif
{
set_errno(EBADF);
return VFS_ERROR;
}
#if CONFIG_NFILE_DESCRIPTORS > 0
/* The descriptor is in the right range to be a file descriptor... write
* to the file.
*/
int ret = fs_getfilep(fd, &filep);
if (ret < 0)
{
/* The errno value has already been set */
return VFS_ERROR;
}
if (filep->f_oflags & O_DIRECTORY)
{
set_errno(EBADF);
return VFS_ERROR;
}
/* Perform the truncate operation using the file descriptor as an index */
return file_truncate(filep, length);
#endif
}
int truncate(const char *path, off_t length)
{
int fd;
int ret;
fd = open(path, O_RDWR);
if (fd == VFS_ERROR)
{
/* The errno value has already been set */
return VFS_ERROR;
}
ret = ftruncate(fd, length);
close(fd);
return ret;
}
+193
View File
@@ -0,0 +1,193 @@
/****************************************************************************
* fs/vfs/fs_truncate64.c
*
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "sys/types.h"
#include "unistd.h"
#include "fcntl.h"
#include "sched.h"
#include "assert.h"
#include "errno.h"
#include "inode/inode.h"
/****************************************************************************
* Name: file_truncate
*
* Description:
* Equivalent to the standard ftruncate() function except that is accepts
* a struct file instance instead of a file descriptor and it does not set
* the errno variable.
*
****************************************************************************/
static int file_truncate64(FAR struct file *filep, off64_t length)
{
FAR struct inode *inode = NULL;
int ret;
int err;
/* Was this file opened for write access? */
if (((unsigned int)(filep->f_oflags) & O_ACCMODE) == O_RDONLY)
{
err = EACCES;
goto errout;
}
/* Is this inode a registered mountpoint? Does it support the
* truncate operations may be relevant to device drivers but only
* the mountpoint operations vtable contains a truncate method.
*/
inode = filep->f_inode;
if (!inode || !inode->u.i_mops || !inode->u.i_mops->truncate64)
{
err = EBADF;
goto errout;
}
/* Does the file system support the truncate method? It should if it is
* a write-able file system.
*/
ret = inode->u.i_mops->truncate64(filep, length);
if (ret < 0)
{
err = -ret;
goto errout;
}
return ret;
errout:
set_errno(err);
return VFS_ERROR;
}
/****************************************************************************
* Name: ftruncate
*
* Description:
* The ftruncate() function causes the regular file referenced by fd to
* have a size of length bytes.
*
* If the file previously was larger than length, the extra data is
* discarded. If it was previously shorter than length, it is unspecified
* whether the file is changed or its size increased. If the file is
* extended, the extended area appears as if it were zero-filled. If fd
* references a shared memory object, ftruncate() sets the size of the
* shared memory object to length. If the file is not a regular file or
* a shared memory object, the result is unspecified.
* With ftruncate(), the file must be open for writing; for truncate(),
* the process must have write permission for the file.
*
* ftruncate() does not modify the file offset for any open file
* descriptions associated with the file.
*
* Input Parameters:
* fd - A reference to an open, regular file or shared memory object
* to be truncated.
* length - The new length of the file or shared memory object.
*
* Returned Value:
* On success, 0.
* On error, -1 is returned, and errno is set appro-priately:
*
*
****************************************************************************/
int ftruncate64(int fd, off64_t length)
{
#if CONFIG_NFILE_DESCRIPTORS > 0
FAR struct file *filep = NULL;
#endif
/* Did we get a valid file descriptor? */
#if CONFIG_NFILE_DESCRIPTORS > 0
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
#endif
{
set_errno(EBADF);
return VFS_ERROR;
}
#if CONFIG_NFILE_DESCRIPTORS > 0
/* The descriptor is in the right range to be a file descriptor... write
* to the file.
*/
int ret = fs_getfilep(fd, &filep);
if (ret < 0)
{
/* The errno value has already been set */
return VFS_ERROR;
}
if (filep->f_oflags & O_DIRECTORY)
{
set_errno(EBADF);
return VFS_ERROR;
}
/* Perform the truncate operation using the file descriptor as an index */
return file_truncate64(filep, length);
#endif
}
int truncate64(const char *path, off64_t length)
{
int fd;
int ret;
fd = open(path, O_RDWR);
if (fd == VFS_ERROR)
{
/* The errno value has already been set */
return VFS_ERROR;
}
ret = ftruncate64(fd, length);
close(fd);
return ret;
}
+290
View File
@@ -0,0 +1,290 @@
/****************************************************************************
* fs/vfs/fs_unlink.c
*
* Copyright (C) 2007-2009, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "unistd.h"
#include "errno.h"
#include "fs/fs.h"
#include "fcntl.h"
#include "inode/inode.h"
#include "stdlib.h"
#include "fs_other.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#undef FS_HAVE_WRITABLE_MOUNTPOINT
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_WRITABLE) && \
CONFIG_NFILE_STREAMS > 0
# define FS_HAVE_WRITABLE_MOUNTPOINT 1
#endif
#undef FS_HAVE_PSEUDOFS_OPERATIONS
#if !defined(CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && CONFIG_NFILE_STREAMS > 0
# define FS_HAVE_PSEUDOFS_OPERATIONS 1
#endif
#undef FS_HAVE_UNLINK
#if defined(FS_HAVE_WRITABLE_MOUNTPOINT) || defined(FS_HAVE_PSEUDOFS_OPERATIONS)
# define FS_HAVE_UNLINK 1
#endif
#ifdef FS_HAVE_UNLINK
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: do_unlink
*
* Description: Remove a file managed a mountpoint
*
****************************************************************************/
int do_unlink(int dirfd, FAR const char *pathname)
{
FAR struct inode *inode;
const char *relpath = NULL;
int errcode;
int ret;
char *fullpath = NULL;
char *relativepath = NULL;
struct inode_search_s desc;
/* Get relative path by dirfd*/
ret = get_path_from_fd(dirfd, &relativepath);
if (ret < 0)
{
errcode = ret;
goto errout;
}
errcode = vfs_normalize_path((const char *)relativepath, pathname, &fullpath);
if (relativepath)
{
free(relativepath);
}
if (errcode < 0)
{
errcode = -errcode;
goto errout;
}
/* Get an inode for this file */
SETUP_SEARCH(&desc, fullpath, false);
ret = inode_find(&desc);
if (ret < 0)
{
errcode = EACCES;
free(fullpath);
goto errout;
}
inode = desc.node;
relpath = desc.relpath;
#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 no operations)
* or a soft link, 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.
*/
inode_semtake();
if (VfsPermissionCheck(desc.parent->i_uid, desc.parent->i_gid, desc.parent->i_mode, EXEC_OP | WRITE_OP))
{
errcode = EACCES;
goto errout_with_inode;
}
/* 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;
inode_semgive();
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;
inode_semgive();
goto errout_with_inode;
}
}
#endif
else
{
inode_semgive();
errcode = EACCES;
goto errout_with_inode;
}
inode_semgive();
}
else if (!INODE_IS_SPECIAL(inode) && (inode->u.i_ops == NULL))
{
/* It is a "dangling" pseudo-file node with no operations */
errcode = EISDIR;
goto errout_with_inode;
}
else
#endif
{
errcode = ENXIO;
goto errout_with_inode;
}
/* Thie file is being deleted, page-caches of the file will no longer be used,
* so drop all the page-caches for the file at this moment, and then remove mapping
* between the file and pagecache.
*/
(void)remove_mapping(fullpath, NULL);
/* Successfully unlinked */
inode_release(inode);
free(fullpath);
return OK;
errout_with_inode:
inode_release(inode);
free(fullpath);
errout:
set_errno(errcode);
return VFS_ERROR;
}
/****************************************************************************
* Name: unlink
*
* Description: Remove a file managed a mountpoint
*
****************************************************************************/
int unlink(FAR const char *pathname)
{
return do_unlink(AT_FDCWD, pathname);
}
/****************************************************************************
* Name: unlinkat
*
* Description: Remove a file managed a mountpoint by dirfd
*
****************************************************************************/
extern int do_rmdir(int dirfd, FAR const char *pathname);
int unlinkat(int dirfd, FAR const char *pathname, int flag)
{
/* Now flag only support 0 && AT_REMOVEDIR */
if ((flag & ~AT_REMOVEDIR) != 0)
return VFS_ERROR;
if (flag & AT_REMOVEDIR)
return do_rmdir(dirfd, pathname);
return do_unlink(dirfd, pathname);
}
#endif /* FS_HAVE_UNLINK */
+263
View File
@@ -0,0 +1,263 @@
/****************************************************************************
* fs/vfs/fs_write.c
*
* Copyright (C) 2007-2009, 2012-2014, 2016-2017 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "sys/types.h"
#include "unistd.h"
#include "fcntl.h"
#include "sched.h"
#include "assert.h"
#include "errno.h"
#include "sys/socket.h"
#include "console.h"
#include "user_copy.h"
#include "inode/inode.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: file_write
*
* Description:
* Equivalent to the standard write() function except that is accepts a
* struct file instance instead of a file descriptor. It is functionally
* equivalent to write() except that in addition to the differences in
* input paramters:
*
* - It does not modify the errno variable,
* - It is not a cancellation point, and
* - It does not handle socket descriptors.
*
* Input Parameters:
* filep - Instance of struct file to use with the write
* buf - Data to write
* nbytes - Length of data to write
*
* Returned Value:
* On success, the number of bytes written are returned (zero indicates
* nothing was written). On any failure, a negated errno value is returned
* (see comments withwrite() for a description of the appropriate errno
* values).
*
****************************************************************************/
ssize_t file_write(FAR struct file *filep, FAR const void *buf, size_t nbytes)
{
FAR struct inode *inode;
int ret;
int err;
if (buf == NULL)
{
err = EFAULT;
goto errout;
}
/* Was this file opened for write access? */
if ((((unsigned int)(filep->f_oflags)) & O_ACCMODE) == O_RDONLY)
{
err = EACCES;
goto errout;
}
/* Is a driver registered? Does it support the write method? */
inode = filep->f_inode;
if (!inode || !inode->u.i_ops || !inode->u.i_ops->write)
{
err = EBADF;
goto errout;
}
/* Yes, then let the driver perform the write */
ret = inode->u.i_ops->write(filep, (const char *)buf, nbytes);
if (ret < 0)
{
err = -ret;
goto errout;
}
return ret;
errout:
set_errno(err);
return VFS_ERROR;
}
/****************************************************************************
* Name: write
*
* Description:
* write() writes up to nytes bytes to the file referenced by the file
* descriptor fd from the buffer starting at buf.
*
* Input Parameters:
* fd - file descriptor (or socket descriptor) to write to
* buf - Data to write
* nbytes - Length of data to write
*
* Returned Value:
* On success, the number of bytes written are returned (zero indicates
* nothing was written). On error, -1 is returned, and errno is set appro-
* priately:
*
* EAGAIN
* Non-blocking I/O has been selected using O_NONBLOCK and the write
* would block.
* EBADF
* fd is not a valid file descriptor or is not open for writing.
* EFAULT
* buf is outside your accessible address space.
* EFBIG
* An attempt was made to write a file that exceeds the implementation
* defined maximum file size or the process' file size limit, or
* to write at a position past the maximum allowed offset.
* EINTR
* The call was interrupted by a signal before any data was written.
* EINVAL
* fd is attached to an object which is unsuitable for writing; or
* the file was opened with the O_DIRECT flag, and either the address
* specified in buf, the value specified in count, or the current
* file offset is not suitably aligned.
* EIO
* A low-level I/O error occurred while modifying the inode.
* ENOSPC
* The device containing the file referred to by fd has no room for
* the data.
* EPIPE
* fd is connected to a pipe or socket whose reading end is closed.
* When this happens the writing process will also receive a SIGPIPE
* signal. (Thus, the write return value is seen only if the program
* catches, blocks or ignores this signal.)
*
****************************************************************************/
ssize_t write(int fd, FAR const void *buf, size_t nbytes)
{
#if CONFIG_NFILE_DESCRIPTORS > 0
FAR struct file *filep;
#endif
/* 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(LOSCFG_NET_LWIP_SACK)
FAR const void *bufbak = buf;
ssize_t ret;
if (LOS_IsUserAddress((VADDR_T)(uintptr_t)buf))
{
if (buf != NULL && nbytes > 0)
{
buf = malloc(nbytes);
if (buf == NULL)
{
set_errno(ENOMEM);
return VFS_ERROR;
}
if (LOS_ArchCopyFromUser((void*)buf, bufbak, nbytes) != 0)
{
free((void*)buf);
set_errno(EFAULT);
return VFS_ERROR;
}
}
}
ret = send(fd, buf, nbytes, 0);
if (buf != bufbak)
{
free((void*)buf);
}
return ret;
#else
set_errno(EBADF);
return VFS_ERROR;
#endif
}
#if CONFIG_NFILE_DESCRIPTORS > 0
/* The descriptor is in the right range to be a file descriptor... write
* to the file.
*/
if (fd <= STDERR_FILENO && fd >= STDIN_FILENO) /* fd : [0,2] */
{
fd = ConsoleUpdateFd();
if (fd < 0)
{
set_errno(EBADF);
return VFS_ERROR;
}
}
int ret = fs_getfilep(fd, &filep);
if (ret < 0)
{
/* The errno value has already been set */
return VFS_ERROR;
}
if (filep->f_oflags & O_DIRECTORY)
{
set_errno(EBADF);
return VFS_ERROR;
}
if (filep->f_oflags & O_APPEND)
{
if (file_seek64(filep, 0, SEEK_END) == -1)
{
return VFS_ERROR;
}
}
/* Perform the write operation using the file descriptor as an index */
return file_write(filep, buf, nbytes);
#endif
}
+179
View File
@@ -0,0 +1,179 @@
/****************************************************************************
* include/debug.h
*
* Copyright (C) 2007-2011, 2014, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __INCLUDE_DEBUG_H
#define __INCLUDE_DEBUG_H
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "compiler.h"
#include "syslog.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Debug macros to runtime filter the debug messages sent to the console. In
* general, there are four forms of the debug macros:
*
* [a-z]dbg() -- Outputs messages to the console similar to printf() except
* that the output is not buffered. The first character indicates the
* system system (e.g., n=network, f=filesystm, etc.). If the first
* character is missing (i.e., dbg()), then it is common. The common
* dbg() macro is enabled by CONFIG_DEBUG. Subsystem debug requires an
* additional configuration setting to enable it (e.g., CONFIG_DEBUG_NET
* for the network, CONFIG_DEBUG_FS for the file system, etc).
*
* In general, error messages and output of importance use [a-z]dbg().
* [a-z]dbg() is implementation dependent but usually uses file descriptors.
* (that is a problem only because the interrupt task may have re-
* directed stdout). Therefore [a-z]dbg() should not be used in interrupt
* handlers.
*
* [a-z]vdbg() -- Identical to [a-z]dbg() except that it also requires that
* CONFIG_DEBUG_VERBOSE be defined. This is intended for general debug
* output that you would normally want to suppress.
*
* [a-z]lldbg() -- Identical to [a-z]dbg() except this is uses special
* interfaces provided by architecture-specific logic to talk directly
* to the underlying console hardware. If the architecture provides such
* logic, it should define CONFIG_ARCH_LOWPUTC.
*
* [a-z]lldbg() should not be used in normal code because the implementation
* probably disables interrupts and does things that are not consistent with
* good real-time performance. However, [a-z]lldbg() is particularly useful
* in low-level code where it is inappropriate to use file descriptors. For
* example, only [a-z]lldbg() should be used in interrupt handlers.
*
* [a-z]llvdbg() -- Identical to [a-z]lldbg() except that it also requires that
* CONFIG_DEBUG_VERBOSE be defined. This is intended for general debug
* output that you would normally want to suppress.
*/
#ifdef CONFIG_HAVE_FUNCTIONNAME
# define EXTRA_FMT "%s: "
# define EXTRA_ARG ,__FUNCTION__
#else
# define EXTRA_FMT
# define EXTRA_ARG
#endif
/* Debug macros will differ depending upon if the toolchain supports
* macros with a variable number of arguments or not.
*/
#ifdef CONFIG_CPP_HAVE_VARARGS
/* C-99 style variadic macros are supported */
/* The actual logger function may be overridden in arch/debug.h if needed.
* (Currently only if the pre-processor supports variadic macros)
*/
#ifdef CONFIG_DEBUG
# define dbg(format, ...) \
syslog(LOG_ERR, EXTRA_FMT format EXTRA_ARG, ##__VA_ARGS__)
# ifdef CONFIG_ARCH_LOWPUTC
# define lldbg(format, ...) \
lowsyslog(LOG_ERR, EXTRA_FMT format EXTRA_ARG, ##__VA_ARGS__)
# else
# define lldbg(x...)
# endif
# ifdef CONFIG_DEBUG_VERBOSE
# define vdbg(format, ...) \
syslog(LOG_DEBUG, EXTRA_FMT format EXTRA_ARG, ##__VA_ARGS__)
# ifdef CONFIG_ARCH_LOWPUTC
# define llvdbg(format, ...) \
lowsyslog(LOG_DEBUG, EXTRA_FMT format EXTRA_ARG, ##__VA_ARGS__)
# else
# define llvdbg(x...)
# endif
# else
# define vdbg(x...)
# define llvdbg(x...)
# endif
#else /* CONFIG_DEBUG */
# define dbg(x...)
# define lldbg(x...)
# define vdbg(x...)
# define llvdbg(x...)
#endif /* CONFIG_DEBUG */
/* Subsystem specific debug */
#ifdef CONFIG_DEBUG_FS
# define fdbg(format, ...) dbg(format, ##__VA_ARGS__)
# define flldbg(format, ...) lldbg(format, ##__VA_ARGS__)
# define fvdbg(format, ...) vdbg(format, ##__VA_ARGS__)
# define fllvdbg(format, ...) llvdbg(format, ##__VA_ARGS__)
# define finfo(format, ...) vdbg(format, ##__VA_ARGS__)
# define ferr(format, ...) dbg(format, ##__VA_ARGS__)
# define fwarn(format, ...) dbg(format, ##__VA_ARGS__)
#else
# define fdbg(x...)
# define flldbg(x...)
# define fvdbg(x...)
# define fllvdbg(x...)
# define finfo(x...)
# define ferr(x...)
# define fwarn(x...)
#endif
#endif /* CONFIG_CPP_HAVE_VARARGS */
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __INCLUDE_DEBUG_H */
+696
View File
@@ -0,0 +1,696 @@
/****************************************************************************
* include/nuttx/compiler.h
*
* Copyright (C) 2007-2009, 2012-2013, 2015-2017 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_COMPILER_H
#define __INCLUDE_NUTTX_COMPILER_H
/****************************************************************************
* Included Files
****************************************************************************/
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* GCC-specific definitions *************************************************/
#ifdef __GNUC__
/* Pre-processor */
# define CONFIG_CPP_HAVE_VARARGS 1 /* Supports variable argument macros */
# define CONFIG_CPP_HAVE_WARNING 1 /* Supports #warning */
/* Intriniscs. GCC supports __func__ but provides __FUNCTION__ for backward
* compatibility with older versions of GCC.
*/
# define CONFIG_HAVE_FUNCTIONNAME 1 /* Has __FUNCTION__ */
# define CONFIG_HAVE_FILENAME 1 /* Has __FILE__ */
/* Indicate that a local variable is not used */
# define UNUSED(a) ((void)(a))
/* Built-in functions */
/* GCC 4.x have __builtin_ctz(|l|ll) and __builtin_clz(|l|ll). These count
* trailing/leading zeros of input number and typically will generate few
* fast bit-counting instructions. Inputting zero to these functions is
* undefined and needs to be taken care of by the caller. */
#if __GNUC__ >= 4
# define CONFIG_HAVE_BUILTIN_CTZ 1
# define CONFIG_HAVE_BUILTIN_CLZ 1
#endif
/* C++ support */
#if defined(__cplusplus) && __cplusplus >= 201402L
# define CONFIG_HAVE_CXX14 1
#else
# undef CONFIG_HAVE_CXX14
#endif
/* Attributes
*
* GCC supports weak symbols which can be used to reduce code size because
* unnecessary "weak" functions can be excluded from the link.
*/
# if !defined(__CYGWIN__) && !defined(CONFIG_ARCH_GNU_NO_WEAKFUNCTIONS)
# define CONFIG_HAVE_WEAKFUNCTIONS 1
# ifndef weak_alias
# define weak_alias(name, aliasname) \
extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
# endif
# define weak_function __attribute__ ((weak))
# define weak_const_function __attribute__ ((weak, __const__))
# else
# undef CONFIG_HAVE_WEAKFUNCTIONS
# define weak_alias(name, aliasname)
# define weak_function
# define weak_const_function
# endif
/* The noreturn attribute informs GCC that the function will not return.
* C11 adds _Noreturn keyword (see stdnoreturn.h)
*/
# define noreturn_function __attribute__ ((noreturn))
/* The farcall_function attribute informs GCC that is should use long calls
* (even though -mlong-calls does not appear in the compilation options)
*/
# define farcall_function __attribute__ ((long_call))
/* Data alignment */
# define aligned_data(n) __attribute__ ((aligned(n)))
/* The packed attribute informs GCC that the structure elements are packed,
* ignoring other alignment rules.
*/
# define begin_packed_struct
# define end_packed_struct __attribute__ ((packed))
/* GCC does not support the reentrant attribute */
# define reentrant_function
/* The naked attribute informs GCC that the programmer will take care of
* the function prolog and epilog.
*/
# define naked_function __attribute__ ((naked,no_instrument_function))
/* The inline_function attribute informs GCC that the function should always
* be inlined, regardless of the level of optimization. The noinline_function
* indicates that the function should never be inlined.
*/
# define inline_function __attribute__ ((always_inline,no_instrument_function))
# define noinline_function __attribute__ ((noinline))
/* GCC does not use storage classes to qualify addressing */
# define FAR
# define NEAR
# define DSEG
# define CODE
/* Handle cases where sizeof(int) is 16-bits, sizeof(long) is 32-bits, and
* pointers are 16-bits.
*/
#if defined(__m32c__)
/* No I-space access qualifiers */
# define IOBJ
# define IPTR
/* Select the small, 16-bit addressing model */
# define CONFIG_SMALL_MEMORY 1
/* Long and int are not the same size */
# define CONFIG_LONG_IS_NOT_INT 1
/* Pointers and int are the same size */
# undef CONFIG_PTR_IS_NOT_INT
#elif defined(__AVR__)
# if defined(CONFIG_AVR_HAS_MEMX_PTR)
/* I-space access qualifiers needed by Harvard architecture */
# define IOBJ __flash
# define IPTR __memx
# else
/* No I-space access qualifiers */
# define IOBJ
# define IPTR
# endif
/* Select the small, 16-bit addressing model (for D-Space) */
# define CONFIG_SMALL_MEMORY 1
/* Long and int are not the same size */
# define CONFIG_LONG_IS_NOT_INT 1
/* Pointers and int are the same size */
# undef CONFIG_PTR_IS_NOT_INT
/* Uses a 32-bit FAR pointer only from accessing data outside of the 16-bit
* data space.
*/
# define CONFIG_HAVE_FARPOINTER 1
#elif defined(__mc68hc1x__)
/* No I-space access qualifiers */
# define IOBJ
# define IPTR
/* Select the small, 16-bit addressing model */
# define CONFIG_SMALL_MEMORY 1
/* Normally, mc68hc1x code is compiled with the -mshort option
* which results in a 16-bit integer. If -mnoshort is defined
* then an integer is 32-bits. GCC will defined __INT__ accordingly:
*/
# if __INT__ == 16
/* int is 16-bits, long is 32-bits */
# define CONFIG_LONG_IS_NOT_INT 1
/* Pointers and int are the same size (16-bits) */
# undef CONFIG_PTR_IS_NOT_INT
# else
/* int and long are both 32-bits */
# undef CONFIG_LONG_IS_NOT_INT
/* Pointers and int are NOT the same size */
# define CONFIG_PTR_IS_NOT_INT 1
# endif
#else
/* No I-space access qualifiers */
# define IOBJ
# define IPTR
/* Select the large, 32-bit addressing model */
# undef CONFIG_SMALL_MEMORY
/* Long and int are (probably) the same size (32-bits) */
# undef CONFIG_LONG_IS_NOT_INT
/* Pointers and int are the same size (32-bits) */
# undef CONFIG_PTR_IS_NOT_INT
#endif
/* GCC supports inlined functions for C++ and for C version C99 and above */
# if defined(__cplusplus) || !defined(__STDC_VERSION__) || __STDC_VERSION__ >= 199901L
# define CONFIG_HAVE_INLINE 1
# else
# undef CONFIG_HAVE_INLINE
# define inline
# endif
/* ISO C11 supports anonymous (unnamed) structures and unions, added in
* GCC 4.6 (but might be suppressed with -std= option). ISO C++11 also
* adds un-named unions, but NOT unnamed structures (although compilers
* may support them).
*
* CAREFUL: This can cause issues for shared data structures shared between
* C and C++ if the two versions do not support the same features. Structures
* and unions can lose binary compatibility!
*
* NOTE: The NuttX coding standard forbids the use of unnamed structures and
* unions within the OS.
*/
# undef CONFIG_HAVE_ANONYMOUS_STRUCT
# undef CONFIG_HAVE_ANONYMOUS_UNION
# if (defined(__cplusplus) && __cplusplus >= 201103L) || \
(defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L)
# define CONFIG_HAVE_ANONYMOUS_STRUCT 1
# define CONFIG_HAVE_ANONYMOUS_UNION 1
# endif
/* GCC supports both types double and long long */
# ifndef __clang__
# define CONFIG_HAVE_LONG_LONG 1
# endif
# define CONFIG_HAVE_FLOAT 1
# define CONFIG_HAVE_DOUBLE 1
# define CONFIG_HAVE_LONG_DOUBLE 1
/* Structures and unions can be assigned and passed as values */
# define CONFIG_CAN_PASS_STRUCTS 1
/* Indicate that a local variable is not used */
# define UNUSED(a) ((void)(a))
/* SDCC-specific definitions ************************************************/
#elif defined(SDCC) || defined(__SDCC)
/* No I-space access qualifiers */
# define IOBJ
# define IPTR
/* Pre-processor */
# define CONFIG_CPP_HAVE_VARARGS 1 /* Supports variable argument macros */
# define CONFIG_CPP_HAVE_WARNING 1 /* Supports #warning */
/* Intriniscs */
# define CONFIG_HAVE_FUNCTIONNAME 1 /* Has __FUNCTION__ */
# define CONFIG_HAVE_FILENAME 1 /* Has __FILE__ */
# define __FUNCTION__ __func__ /* SDCC supports on __func__ */
/* Pragmas
*
* Disable warnings for unused function arguments */
# pragma disable_warning 85
/* C++ support */
# undef CONFIG_HAVE_CXX14
/* Attributes
*
* SDCC does not support weak symbols */
# undef CONFIG_HAVE_WEAKFUNCTIONS
# ifndef weak_alias
# define weak_alias(name, aliasname)
# endif
# define weak_function
# define weak_const_function
# define restrict /* REVISIT */
/* SDCC does not support the noreturn or packed attributes */
/* Current SDCC supports noreturn via C11 _Noreturn keyword (see
* stdnoreturn.h).
*/
# define noreturn_function
# define aligned_data(n)
# define begin_packed_struct
# define end_packed_struct
/* REVISIT: */
# define farcall_function
/* SDCC does support "naked" functions */
# define naked_function __naked
/* SDCC does not support forced inlining. */
# define inline_function
# define noinline_function
/* The reentrant attribute informs SDCC that the function
* must be reentrant. In this case, SDCC will store input
* arguments on the stack to support reentrancy.
*
* SDCC functions are always reentrant (except for the mcs51,
* ds390, hc08 and s08 backends)
*/
# define reentrant_function __reentrant
/* ISO C11 supports anonymous (unnamed) structures and unions. Does SDCC? */
# undef CONFIG_HAVE_ANONYMOUS_STRUCT
# undef CONFIG_HAVE_ANONYMOUS_UNION
/* Indicate that a local variable is not used */
# define UNUSED(a) ((void)(a))
/* It is assumed that the system is build using the small
* data model with storage defaulting to internal RAM.
* The NEAR storage class can also be used to address data
* in internal RAM; FAR can be used to address data in
* external RAM.
*/
#if defined(__SDCC_z80) || defined(__SDCC_z180) || defined(__SDCC_gbz80)
# define FAR
# define NEAR
# define CODE
# define DSEG
#else
# define FAR __xdata
# define NEAR __data
# define CODE __code
# if defined(SDCC_MODEL_SMALL)
# define DSEG __data
# else
# define DSEG __xdata
# endif
#endif
/* Select small, 16-bit address model */
# define CONFIG_SMALL_MEMORY 1
/* Long and int are not the same size */
# define CONFIG_LONG_IS_NOT_INT 1
/* The generic pointer and int are not the same size (for some SDCC
* architectures). REVISIT: SDCC now has more backends where pointers are
* the same size as int than just z80 and z180.
*/
#if !defined(__z80) && !defined(__gbz80)
# define CONFIG_PTR_IS_NOT_INT 1
#endif
/* New versions of SDCC supports inline function */
# define CONFIG_HAVE_INLINE 1
/* SDCC does types long long and float, but not types double and long
* double.
*/
# define CONFIG_HAVE_LONG_LONG 1
# define CONFIG_HAVE_FLOAT 1
# undef CONFIG_HAVE_DOUBLE
# undef CONFIG_HAVE_LONG_DOUBLE
/* Structures and unions cannot be passed as values or used
* in assignments.
*/
# undef CONFIG_CAN_PASS_STRUCTS
/* Indicate that a local variable is not used */
# define UNUSED(a) ((void)(a))
/* Zilog-specific definitions ***********************************************/
#elif defined(__ZILOG__)
/* At present, only the following Zilog compilers are recognized */
# if !defined(__ZNEO__) && !defined(__EZ8__) && !defined(__EZ80__)
# warning "Unrecognized Zilog compiler"
# endif
/* Pre-processor */
# undef CONFIG_CPP_HAVE_VARARGS /* No variable argument macros */
# undef CONFIG_CPP_HAVE_WARNING /* Does not support #warning */
/* Intrinsics */
# define CONFIG_HAVE_FUNCTIONNAME 1 /* Has __FUNCTION__ */
# define CONFIG_HAVE_FILENAME 1 /* Has __FILE__ */
/* No I-space access qualifiers */
# define IOBJ
# define IPTR
/* C++ support */
# undef CONFIG_HAVE_CXX14
/* Attributes
*
* The Zilog compiler does not support weak symbols
*/
# undef CONFIG_HAVE_WEAKFUNCTIONS
# ifndef weak_alias
# define weak_alias(name, aliasname)
# endif
# define weak_function
# define weak_const_function
# define restrict
/* The Zilog compiler does not support the noreturn, packed, naked
* attributes.
*/
# define noreturn_function
# define aligned_data(n)
# define begin_packed_struct
# define end_packed_struct
# define naked_function
# define inline_function
# define noinline_function
/* REVISIT: */
# define farcall_function
/* The Zilog compiler does not support the reentrant attribute */
# define reentrant_function
/* Addressing.
*
* Z16F ZNEO: Far is 24-bits; near is 16-bits of address.
* The supported model is (1) all code on ROM, and (2) all data
* and stacks in external (far) RAM.
* Z8Encore!: Far is 16-bits; near is 8-bits of address.
* The supported model is (1) all code on ROM, and (2) all data
* and stacks in internal (far) RAM.
* Z8Acclaim: In Z80 mode, all pointers are 16-bits. In ADL mode, all pointers
* are 24 bits.
*/
# if defined(__ZNEO__)
# define FAR _Far
# define NEAR _Near
# define DSEG _Far
# define CODE _Erom
# undef CONFIG_SMALL_MEMORY /* Select the large, 32-bit addressing model */
# undef CONFIG_LONG_IS_NOT_INT /* Long and int are the same size */
# undef CONFIG_PTR_IS_NOT_INT /* FAR pointers and int are the same size */
# elif defined(__EZ8__)
# define FAR far
# define NEAR near
# define DSEG far
# define CODE rom
# define CONFIG_SMALL_MEMORY 1 /* Select small, 16-bit address model */
# define CONFIG_LONG_IS_NOT_INT 1 /* Long and int are not the same size */
# undef CONFIG_PTR_IS_NOT_INT /* FAR pointers and int are the same size */
# elif defined(__EZ80__)
# define FAR
# define NEAR
# define DSEG
# define CODE
# undef CONFIG_SMALL_MEMORY /* Select the large, 32-bit addressing model */
# define CONFIG_LONG_IS_NOT_INT 1 /* Long and int are not the same size */
# ifdef CONFIG_EZ80_Z80MODE
# define CONFIG_PTR_IS_NOT_INT 1 /* Pointers and int are not the same size */
# else
# undef CONFIG_PTR_IS_NOT_INT /* Pointers and int are the same size */
# endif
# endif
/* The Zilog compiler does not support inline functions */
# undef CONFIG_HAVE_INLINE
# define inline
/* ISO C11 supports anonymous (unnamed) structures and unions. Zilog does
* not support C11
*/
# undef CONFIG_HAVE_ANONYMOUS_STRUCT
# undef CONFIG_HAVE_ANONYMOUS_UNION
/* Older Zilog compilers support both types double and long long, but the size
* is 32-bits (same as long and single precision) so it is safer to say that
* they are not supported. Later versions are more ANSII compliant and
* simply do not support long long or double.
*/
# undef CONFIG_HAVE_LONG_LONG
# define CONFIG_HAVE_FLOAT 1
# undef CONFIG_HAVE_DOUBLE
# undef CONFIG_HAVE_LONG_DOUBLE
/* Structures and unions can be assigned and passed as values */
# define CONFIG_CAN_PASS_STRUCTS 1
/* Indicate that a local variable is not used */
# define UNUSED(a) ((void)(a))
/* ICCARM-specific definitions ***********************************************/
#elif defined(__ICCARM__)
# define CONFIG_CPP_HAVE_VARARGS 1 /* Supports variable argument macros */
# define CONFIG_HAVE_FILENAME 1 /* Has __FILE__ */
# define CONFIG_HAVE_FLOAT 1
/* Indicate that a local variable is not used */
# define UNUSED(a) ((void)(a))
# ifndef weak_alias
# define weak_alias(name, aliasname)
# endif
# define weak_function __weak
# define weak_const_function
# define noreturn_function
# define farcall_function
# define aligned_data(n)
# define begin_packed_struct __packed
# define end_packed_struct
# define reentrant_function
# define naked_function
# define inline_function
# define noinline_function
# define FAR
# define NEAR
# define DSEG
# define CODE
# define IOBJ
# define IPTR
# define __asm__ asm
# define __volatile__ volatile
/* For operatots __sfb() and __sfe() */
# pragma section = ".bss"
# pragma section = ".data"
# pragma section = ".data_init"
# pragma section = ".text"
/* C++ support */
# undef CONFIG_HAVE_CXX14
/* ISO C11 supports anonymous (unnamed) structures and unions. Does ICCARM? */
# undef CONFIG_HAVE_ANONYMOUS_STRUCT
# undef CONFIG_HAVE_ANONYMOUS_UNION
/* Unknown compiler *********************************************************/
#else
# undef CONFIG_CPP_HAVE_VARARGS
# undef CONFIG_CPP_HAVE_WARNING
# undef CONFIG_HAVE_FUNCTIONNAME
# undef CONFIG_HAVE_FILENAME
# undef CONFIG_HAVE_WEAKFUNCTIONS
# undef CONFIG_HAVE_CXX14
# ifndef weak_alias
# define weak_alias(name, aliasname)
# endif
# define weak_function
# define weak_const_function
# define restrict
# define noreturn_function
# define farcall_function
# define aligned_data(n)
# define begin_packed_struct
# define end_packed_struct
# define reentrant_function
# define naked_function
# define inline_function
# define noinline_function
# define FAR
# define NEAR
# define DSEG
# define CODE
# undef CONFIG_SMALL_MEMORY
# undef CONFIG_LONG_IS_NOT_INT
# undef CONFIG_PTR_IS_NOT_INT
# undef CONFIG_HAVE_INLINE
# define inline
# undef CONFIG_HAVE_LONG_LONG
# define CONFIG_HAVE_FLOAT 1
# undef CONFIG_HAVE_DOUBLE
# undef CONFIG_HAVE_LONG_DOUBLE
# undef CONFIG_CAN_PASS_STRUCTS
# undef CONFIG_HAVE_ANONYMOUS_STRUCT
# undef CONFIG_HAVE_ANONYMOUS_UNION
# define UNUSED(a) ((void)(a))
#endif
#endif /* __INCLUDE_NUTTX_COMPILER_H */
+200
View File
@@ -0,0 +1,200 @@
/****************************************************************************
* include/nuttx/audio/automount.h
*
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_AUDIO_AUTOMOUNT_H
#define __INCLUDE_NUTTX_AUDIO_AUTOMOUNT_H
/****************************************************************************
* Included Files
****************************************************************************/
#include "stdint.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Configuration ************************************************************
* Automounter configuration
* CONFIG_FS_AUTOMOUNTER - Enables automount support
*
* Prequisites:
* CONFIG_SCHED_WORKQUEUE - Work queue support is required
* And others that would only matter if you are working in a very minimal
* configuration.
*/
/* Helper macros ************************************************************/
#define AUTOMOUNT_ATTACH(s,isr,arg) ((s)->attach(s,isr,arg))
#define AUTOMOUNT_DETACH(s) ((s)->attach(s,NULL,NULL))
#define AUTOMOUNT_ENABLE(s) ((s)->enable(s,true))
#define AUTOMOUNT_DISABLE(s) ((s)->enable(s,false))
#define AUTOMOUNT_INSERTED(s) ((s)->inserted(s))
/****************************************************************************
* Public Types
****************************************************************************/
/* This is the type of the automount media change handler. The lower level
* code will intercept the interrupt and provide the upper level with the
* private data that was provided when the interrupt was attached and will
* also provide an indication if the media was inserted or removed.
*/
struct automount_lower_s; /* Forward reference. Defined below */
typedef CODE int
(*automount_handler_t)(FAR const struct automount_lower_s *lower,
FAR void *arg, bool inserted);
/* A reference to a structure of this type must be passed to the FS
* automounter. This structure provides information about the volume to be
* mounted and provides board-specific hooks.
*
* Memory for this structure is provided by the caller. It is not copied
* by the automounter and is presumed to persist while the automounter
* is active.
*/
struct automount_lower_s
{
/* Volume characterization */
FAR const char *fstype; /* Type of file system */
FAR const char *blockdev; /* Path to the block device */
FAR const char *mountpoint; /* Location to mount the volume */
/* Debounce delay in system clock ticks. Automount operation will not
* be performed until the insertion/removal state has been unchanges
* for this duration.
*/
uint32_t ddelay;
/* Unmount delay time in system clock ticks. If a volume has open
* references at the time that the media is removed, then we will be
* unable to unmount it. In that case, hopefully, the clients of the
* mount will eventually fail with file access errors and eventually close
* their references. So, at some time later, it should be possible to
* unmount the volume. This delay specifies the time between umount
* retries.
*/
uint32_t udelay;
/* Interrupt related operations all hidden behind callbacks to isolate the
* automounter from differences in interrupt handling by varying boards
* and MCUs. Board interrupts should be configured both insertion and
* removal of the media can be detected.
*
* attach - Attach or detach the media change interrupt handler to the
* board level interrupt
* enable - Enable or disable the media change interrupt
*/
CODE int (*attach)(FAR const struct automount_lower_s *lower,
automount_handler_t isr, FAR void *arg);
CODE void (*enable)(FAR const struct automount_lower_s *lower,
bool enable);
CODE bool (*inserted)(FAR const struct automount_lower_s *lower);
};
/****************************************************************************
* Public Data
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: automount_initialize
*
* Description:
* Configure the automounter.
*
* Input Parameters:
* lower - Persistent board configuration data
*
* Returned Value:
* A void* handle. The only use for this handle is with automount_uninitialize().
* NULL is returned on any failure.
*
****************************************************************************/
FAR void *automount_initialize(FAR const struct automount_lower_s *lower);
/****************************************************************************
* Name: automount_uninitialize
*
* Description:
* Stop the automounter and free resources that it used. NOTE that the
* mount is left in its last state mounted/unmounted state.
*
* Input Parameters:
* handle - The value previously returned by automount_initialize();
*
* Returned Value:
* None
*
****************************************************************************/
void automount_uninitialize(FAR void *handle);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __INCLUDE_NUTTX_AUDIO_AUTOMOUNT_H */
+331
View File
@@ -0,0 +1,331 @@
/****************************************************************************
* include/nuttx/fs/dirent_fs.h
*
* Copyright (C) 2007, 2009, 2011-2013, 2015, 2018 Gregory Nutt. All
* rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_FS_DIRENT_FS_H
#define __INCLUDE_NUTTX_FS_DIRENT_FS_H
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "sys/types.h"
#include "stdint.h"
#include "dirent.h"
#include "fs/fs.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define kmm_malloc(s) malloc(s)
#define kmm_free(mem) free(mem)
#define kmm_zalloc(s) zalloc(s)
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_NFS
# define DIRENT_NFS_MAXHANDLE 64 /* Maximum length of an NFSv3 file handle */
# define DIRENT_NFS_VERFLEN 8 /* Length of the copy verifier */
#endif
/****************************************************************************
* Public Types
****************************************************************************/
/* The internal representation of type DIR is just a container for an inode
* reference, a position, a dirent structure, and file-system-specific
* information.
*
* For the root pseudo-file system, we need retain only the 'next' inode
* need for the next readdir() operation. We hold a reference on this
* inode so we know that it will persist until closedir is called.
*/
struct fs_pseudodir_s
{
struct inode *fd_next; /* The inode for the next call to readdir() */
};
typedef void *fs_dir_s;
#define DIRENT_MAGIC 0x11CBA828 /* Magic number to express the status of a dirent */
#ifdef CONFIG_FS_FAT
/* For fat, we need to return the start cluster, current cluster, current
* sector and current directory index.
*/
struct fs_fatdir_s
{
off_t fd_startcluster; /* Start cluster number of the directory */
off_t fd_currcluster; /* Current cluster number being read */
off_t fd_currsector; /* Current sector being read */
unsigned int fd_index; /* Current index of the directory entry to read */
};
#endif /* CONFIG_FS_FAT */
#ifdef CONFIG_FS_ROMFS
/* For ROMFS, we need to return the offset to the current and start positions
* of the directory entry being read
*/
struct fs_romfsdir_s
{
off_t fr_firstoffset; /* Offset to the first entry in the directory */
off_t fr_curroffset; /* Current offset into the directory contents */
};
#endif /* CONFIG_FS_ROMFS */
#ifdef CONFIG_FS_CROMFS
/* For CROMFS, we need to return the next compressed node to be examined. */
struct fs_cromfsdir_s
{
uint32_t cr_firstoffset; /* Offset to the first entry in the directory */
uint32_t cr_curroffset; /* Current offset into the directory contents */
};
#endif /* CONFIG_FS_CROMFS */
/* For TMPFS, we need the directory object and an index into the directory
* entries.
*/
struct tmpfs_directory_s; /* Forward reference */
struct fs_tmpfsdir_s
{
FAR struct tmpfs_directory_s *tf_tdo; /* Directory being enumerated */
unsigned int tf_index; /* Directory index */
};
#ifdef CONFIG_FS_BINFS
/* The apps/ pseudo bin/ directory. The state value is simply an index */
struct fs_binfsdir_s
{
unsigned int fb_index; /* Index to the next named entry point */
};
#endif
#ifdef CONFIG_FS_NXFFS
/* NXFFS is the tiny NuttX wear-leveling FLASH file system. The state value is
* the offset in FLASH memory to the next inode entry.
*/
struct fs_nxffsdir_s
{
off_t nx_offset; /* Offset to the next inode */
};
#endif
#ifdef CONFIG_NFS
/* The NFS client file system */
struct nfsdir_s
{
uint8_t nfs_fhsize; /* Length of the file handle */
uint8_t nfs_fhandle[DIRENT_NFS_MAXHANDLE]; /* File handle (max size allocated) */
uint8_t nfs_verifier[DIRENT_NFS_VERFLEN]; /* Cookie verifier */
uint32_t nfs_cookie[2]; /* Cookie */
};
#endif
#ifdef CONFIG_FS_SMARTFS
/* SMARTFS is the Sector Mapped Allocation for Really Tiny FLASH filesystem.
* it is designed to use small sectors on small serial FLASH devices, using
* minimal RAM footprint.
*/
struct fs_smartfsdir_s
{
uint16_t fs_firstsector; /* First sector of directory list */
uint16_t fs_currsector; /* Current sector of directory list */
uint16_t fs_curroffset; /* Current offset within current sector */
};
#endif
#ifdef CONFIG_FS_SPIFFS
/* SPIFFS is an SPI-oriented FLASH file system originally by Peter Andersson */
struct fs_spiffsdir_s
{
int16_t block; /* Current block */
int entry; /* Current entry */
};
#endif
#ifdef CONFIG_FS_UNIONFS
/* The Union File System can be used to merge to different mountpoints so
* that they appear as a single merged directory.
*/
struct fs_dirent_s; /* Forward reference */
struct fs_unionfsdir_s
{
uint8_t fu_ndx; /* Index of file system being enumerated */
bool fu_eod; /* True: At end of directory */
bool fu_prefix[2]; /* True: Fake directory in prefix */
FAR char *fu_relpath; /* Path being enumerated */
FAR struct fs_dirent_s *fu_lower[2]; /* dirent struct used by contained file system */
};
#endif
#ifdef CONFIG_FS_USERFS
/* The UserFS uses an opaque representation since the actual userspace representation
* of the directory state structure is unknowable.
*/
struct fs_userfsdir_s
{
FAR void *fs_dir; /* Opaque pointer to UserFS DIR */
};
#endif
#ifdef CONFIG_FS_HOSTFS
/* HOSTFS provides mapping to directories on the host machine in the
* sim environment.
*/
struct fs_hostfsdir_s
{
FAR void *fs_dir; /* Opaque pointer to host DIR */
};
#endif
struct fs_dirent_s
{
/* This is the node that was opened by opendir. The type of the inode
* determines the way that the readdir() operations are performed. For the
* pseudo root pseudo-file system, it is also used to support rewind.
*
* We hold a reference on this inode so we know that it will persist until
* closedir() is called (although inodes linked to this inode may change).
*/
struct inode *fd_root;
/* At present, only mountpoints require special handling flags */
#ifndef CONFIG_DISABLE_MOUNTPOINT
unsigned int fd_flags;
#endif
/* This keeps track of the current directory position for telldir */
off_t fd_position;
/* Retained control information depends on the type of file system that
* provides is provides the mountpoint. Ideally this information should
* be hidden behind an opaque, file-system-dependent void *, but we put
* the private definitions in line here for now to reduce allocations.
*/
struct
{
/* Private data used by the built-in pseudo-file system */
struct fs_pseudodir_s pseudo;
/* Private data used by other file systems */
fs_dir_s fs_dir;
#ifdef CONFIG_FS_FAT
struct fs_fatdir_s fat;
#endif
#ifdef CONFIG_FS_ROMFS
struct fs_romfsdir_s romfs;
#endif
#ifdef CONFIG_FS_CROMFS
struct fs_cromfsdir_s cromfs;
#endif
#ifdef CONFIG_FS_TMPFS
struct fs_tmpfsdir_s tmpfs;
#endif
#ifdef CONFIG_FS_BINFS
struct fs_binfsdir_s binfs;
#endif
#ifdef CONFIG_FS_PROCFS
FAR void *procfs;
#endif
#ifdef CONFIG_FS_NXFFS
struct fs_nxffsdir_s nxffs;
#endif
#ifdef CONFIG_NFS
struct nfsdir_s nfs;
#endif
#ifdef CONFIG_FS_SMARTFS
struct fs_smartfsdir_s smartfs;
#endif
#ifdef CONFIG_FS_SPIFFS
struct fs_spiffsdir_s spiffs;
#endif
#ifdef CONFIG_FS_LITTLEFS
FAR void *littlefs;
#endif
#ifdef CONFIG_FS_UNIONFS
struct fs_unionfsdir_s unionfs;
#endif
#ifdef CONFIG_FS_USERFS
struct fs_userfsdir_s userfs;
#endif
#ifdef CONFIG_FS_HOSTFS
struct fs_hostfsdir_s hostfs;
#endif
} u;
/* In any event, this the actual struct dirent that is returned by readdir */
struct dirent fd_dir; /* Populated when readdir is called */
int fd_status; /* Express the dirent is been opened or no */
};
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __INCLUDE_NUTTX_FS_DIRENT_FS_H */
+179
View File
@@ -0,0 +1,179 @@
/****************************************************************************
* include/fs/file.h
*
* Copyright (C) 2007-2009, 2011-2013, 2015-2018 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __INCLUDE_FS_FILE_H
#define __INCLUDE_FS_FILE_H
/****************************************************************************
* Included Files
****************************************************************************/
#include "vfs_config.h"
#include "compiler.h"
#include "sys/types.h"
#include "stdarg.h"
#include "stdint.h"
#include "fs/fs.h"
#include "semaphore.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/****************************************************************************
* Global Function Prototypes
****************************************************************************/
/* Callback used by foreach_mountpoints to traverse all mountpoints in the
* pseudo-file system.
*/
#ifndef CONFIG_DISABLE_MOUNTPOINT
struct statfs; /* Forward reference */
typedef int (*foreach_mountpoint_t)(FAR const char *mountpoint,
FAR struct statfs *statbuf,
FAR void *arg);
#endif
struct filelist *sched_getfiles(void);
/* fs/fs_sendfile.c *************************************************/
/****************************************************************************
* Name: sendfile
*
* Description:
* Copy data between one file descriptor and another.
*
****************************************************************************/
ssize_t sendfile(int outfd, int infd, off_t *offset, size_t count);
/**
* @ingroup fs
* @brief get the path by a given file fd.
*
* @par Description:
* The function is used for getting the path by a given file fd.
*
* @attention
* <ul>
* <li>Only support file fd, not any dir fd.</li>
* </ul>
*
* @param fd [IN] Type #int file fd.
* @param path [IN] Type #char ** address of the location to return the path reference.
*
* @retval #0 get path success
* @retval #~0 get path failed
*
* @par Dependency:
* <ul><li>fs.h: the header file that contains the API declaration.</li></ul>
* @see
*
* @since 2020-1-8
*/
extern int get_path_from_fd(int fd, char **path);
/****************************************************************************
* Name: foreach_mountpoint
*
* Description:
* Visit each mountpoint in the pseudo-file system. The traversal is
* terminated when the callback 'handler' returns a non-zero value, or when
* all of the mountpoints have been visited.
*
* This is just a front end "filter" to foreach_inode() that forwards only
* mountpoint inodes. It is intended to support the mount() command to
* when the mount command is used to enumerate mounts.
*
* NOTE 1: Use with caution... The pseudo-file system is locked throughout
* the traversal.
* NOTE 2: The search algorithm is recursive and could, in principle, use
* an indeterminant amount of stack space. This will not usually be a
* real work issue.
*
* Input Parameters:
* handler - Operation function when find a mount point.
* arg - Private data.
*
****************************************************************************/
#ifndef CONFIG_DISABLE_MOUNTPOINT
int foreach_mountpoint(foreach_mountpoint_t handler, FAR void *arg);
#endif
/****************************************************************************
* Name: find_blockdriver
*
* Description:
* Return the inode of the block driver specified by 'pathname'
*
* Input Parameters:
* pathname - The full path to the block driver to be located
* mountflags - If MS_RDONLY is not set, then driver must support write
* operations (see include/sys/mount.h)
* ppinode - Address of the location to return the inode reference
*
* Returned Value:
* Returns zero on success or a negated errno on failure:
*
* EINVAL - Pathname or pinode is NULL.
* ENOENT - No block driver of this name is registered
* ENOTBLK - The inode associated with the pathname is not a block driver
* EACCESS - The MS_RDONLY option was not set but this driver does not
* support write access
*
* Attention:
* The parameter pathname is a full path, which begin with '/'.
* The parameter ppinode must point a valid memory, which size must be enough for storing struct inode.
*
****************************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
int find_blockdriver(FAR const char *pathname, int mountflags,
FAR struct inode **ppinode);
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* __INCLUDE_FS_FILE_H */
+1058
View File
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More