update OpenHarmony 2.0 Canary

This commit is contained in:
mamingshuai 2021-06-02 00:05:52 +08:00
parent 975373c2c2
commit 58a3bc7363
39 changed files with 4451 additions and 63 deletions

15
.gitattributes vendored Normal file
View File

@ -0,0 +1,15 @@
*.tgz filter=lfs diff=lfs merge=lfs -text
*.trp filter=lfs diff=lfs merge=lfs -text
*.apk filter=lfs diff=lfs merge=lfs -text
*.jar filter=lfs diff=lfs merge=lfs -text
*.mp4 filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.asm filter=lfs diff=lfs merge=lfs -text
*.8svn filter=lfs diff=lfs merge=lfs -text
*.9svn filter=lfs diff=lfs merge=lfs -text
*.dylib filter=lfs diff=lfs merge=lfs -text
*.exe filter=lfs diff=lfs merge=lfs -text
*.a filter=lfs diff=lfs merge=lfs -text
*.so filter=lfs diff=lfs merge=lfs -text
*.bin filter=lfs diff=lfs merge=lfs -text
*.dll filter=lfs diff=lfs merge=lfs -text

177
LICENSE Normal file
View File

@ -0,0 +1,177 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

View File

@ -1,36 +0,0 @@
# distributeddatamgr_file
#### Description
Providing JavaScript APIs for file management | 提供适用于文件管理的 JS 接口
#### Software Architecture
Software architecture description
#### Installation
1. xxxx
2. xxxx
3. xxxx
#### Instructions
1. xxxx
2. xxxx
3. xxxx
#### Contribution
1. Fork the repository
2. Create Feat_xxx branch
3. Commit your code
4. Create Pull Request
#### Gitee Feature
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
4. The most valuable open source project [GVP](https://gitee.com/gvp)
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

297
README.md
View File

@ -1,37 +1,280 @@
# distributeddatamgr_file
# Distributed File<a name="EN-US_TOPIC_0000001101541814"></a>
#### 介绍
Providing JavaScript APIs for file management | 提供适用于文件管理的 JS 接口
- [Introduction](#section104mcpsimp)
- [Architecture](#section110mcpsimp)
#### 软件架构
软件架构说明
- [Directory Structure](#section113mcpsimp)
- [Constraints](#section117mcpsimp)
- [Usage](#section125mcpsimp)
- [Available APIs](#section127mcpsimp)
- [Usage Guidelines](#section149mcpsimp)
- [Repositories Involved](#section178mcpsimp)
## Introduction<a name="section104mcpsimp"></a>
Currently, the Distributed File subsystem provides apps with JavaScript APIs for I/O capabilities, including APIs for managing files and directories, obtaining file information, reading and writing data streams of files, and receiving URIs rather than absolute paths.
### Architecture<a name="section110mcpsimp"></a>
Currently, the Distributed File subsystem provides only local JavaScript file APIs for apps through the FileIO and File modules. The Distributed File subsystem uses LibN to abstract APIs at the NAPI layer, providing basic capabilities such as the basic type system, memory management, and general programming models for the subsystem. This subsystem depends on the engine layer of the JS application development framework to provide the capability of converting JavaScript APIs into C++ code, depends on the application framework to provide app-related directories, and depends on the GLIBC runtimes to provide I/O capabilities.
**Figure 1** Distributed File subsystem architecture<a name="fig174088216114"></a>
![](figures/distributed-file-subsystem-architecture.png "distributed-file-subsystem-architecture")
## Directory Structure<a name="section113mcpsimp"></a>
```
foundation/distributeddatamgr/distributedfile
└── interfaces # APIs
└── kits # APIs exposed externally
```
## Constraints<a name="section117mcpsimp"></a>
Constraints on local I/O APIs:
- Only UTF-8/16 encoding is supported.
- The URIs cannot include external storage directories.
## Usage<a name="section125mcpsimp"></a>
### Available APIs<a name="section127mcpsimp"></a>
Currently, the Distributed File subsystem provides APIs for accessing local files and directories. The following table describes the API types classified by function.
**Table 1** API types
<a name="table99228171027"></a>
<table><thead align="left"><tr id="row2092221715211"><th class="cellrowborder" valign="top" width="15.02%" id="mcps1.2.5.1.1"><p id="p79225171524"><a name="p79225171524"></a><a name="p79225171524"></a>API Type</p>
</th>
<th class="cellrowborder" valign="top" width="32.25%" id="mcps1.2.5.1.2"><p id="p992271711216"><a name="p992271711216"></a><a name="p992271711216"></a>Function</p>
</th>
<th class="cellrowborder" valign="top" width="25.840000000000003%" id="mcps1.2.5.1.3"><p id="p29225175213"><a name="p29225175213"></a><a name="p29225175213"></a>Related Module</p>
</th>
<th class="cellrowborder" valign="top" width="26.889999999999997%" id="mcps1.2.5.1.4"><p id="p129221017720"><a name="p129221017720"></a><a name="p129221017720"></a>Example API (<em id="i15670628145315"><a name="i15670628145315"></a><a name="i15670628145315"></a>Class Name</em>.<em id="i6859230125316"><a name="i6859230125316"></a><a name="i6859230125316"></a>Method Name</em>)</p>
</th>
</tr>
</thead>
<tbody><tr id="row149231717327"><td class="cellrowborder" valign="top" width="15.02%" headers="mcps1.2.5.1.1 "><p id="p3923417629"><a name="p3923417629"></a><a name="p3923417629"></a>Basic file API</p>
</td>
<td class="cellrowborder" valign="top" width="32.25%" headers="mcps1.2.5.1.2 "><p id="p89236171124"><a name="p89236171124"></a><a name="p89236171124"></a>Creates, modifies, and accesses files, and changes file permissions based on the specified absolute paths or file descriptors.</p>
</td>
<td class="cellrowborder" valign="top" width="25.840000000000003%" headers="mcps1.2.5.1.3 "><p id="p22011844349"><a name="p22011844349"></a><a name="p22011844349"></a>@OHOS.distributedfile.fileio</p>
</td>
<td class="cellrowborder" valign="top" width="26.889999999999997%" headers="mcps1.2.5.1.4 "><p id="p1784383174320"><a name="p1784383174320"></a><a name="p1784383174320"></a>accessSync</p>
<p id="p184313310437"><a name="p184313310437"></a><a name="p184313310437"></a>chownSync</p>
<p id="p1684318315436"><a name="p1684318315436"></a><a name="p1684318315436"></a>chmodSync</p>
</td>
</tr>
<tr id="row1692320171825"><td class="cellrowborder" valign="top" width="15.02%" headers="mcps1.2.5.1.1 "><p id="p392391710219"><a name="p392391710219"></a><a name="p392391710219"></a>Basic directory API</p>
</td>
<td class="cellrowborder" valign="top" width="32.25%" headers="mcps1.2.5.1.2 "><p id="p109232176211"><a name="p109232176211"></a><a name="p109232176211"></a>Reads directories and determines file types based on the specified absolute paths.</p>
</td>
<td class="cellrowborder" valign="top" width="25.840000000000003%" headers="mcps1.2.5.1.3 "><p id="p271274219410"><a name="p271274219410"></a><a name="p271274219410"></a>@OHOS.distributedfile.fileio</p>
</td>
<td class="cellrowborder" valign="top" width="26.889999999999997%" headers="mcps1.2.5.1.4 "><p id="p29233177216"><a name="p29233177216"></a><a name="p29233177216"></a>Dir.openDirSync</p>
</td>
</tr>
<tr id="row14923171716217"><td class="cellrowborder" valign="top" width="15.02%" headers="mcps1.2.5.1.1 "><p id="p159234176215"><a name="p159234176215"></a><a name="p159234176215"></a>Basic statistical API</p>
</td>
<td class="cellrowborder" valign="top" width="32.25%" headers="mcps1.2.5.1.2 "><p id="p1992314179215"><a name="p1992314179215"></a><a name="p1992314179215"></a>Collects basic statistics including the file size, access permission, and modification time based on the specified absolute paths.</p>
</td>
<td class="cellrowborder" valign="top" width="25.840000000000003%" headers="mcps1.2.5.1.3 "><p id="p325774111413"><a name="p325774111413"></a><a name="p325774111413"></a>@OHOS.distributedfile.fileio</p>
</td>
<td class="cellrowborder" valign="top" width="26.889999999999997%" headers="mcps1.2.5.1.4 "><p id="p59231317420"><a name="p59231317420"></a><a name="p59231317420"></a>Stat.statSync</p>
</td>
</tr>
<tr id="row692319171228"><td class="cellrowborder" valign="top" width="15.02%" headers="mcps1.2.5.1.1 "><p id="p1592318171526"><a name="p1592318171526"></a><a name="p1592318171526"></a>Streaming file API</p>
</td>
<td class="cellrowborder" valign="top" width="32.25%" headers="mcps1.2.5.1.2 "><p id="p992311171421"><a name="p992311171421"></a><a name="p992311171421"></a>Reads and writes data streams of files based on the specified absolute paths or file descriptors.</p>
</td>
<td class="cellrowborder" valign="top" width="25.840000000000003%" headers="mcps1.2.5.1.3 "><p id="p1692321716217"><a name="p1692321716217"></a><a name="p1692321716217"></a>@OHOS.distributedfile.fileio</p>
</td>
<td class="cellrowborder" valign="top" width="26.889999999999997%" headers="mcps1.2.5.1.4 "><p id="p10923141711215"><a name="p10923141711215"></a><a name="p10923141711215"></a>Stream.createStreamSync</p>
<p id="p88031126184311"><a name="p88031126184311"></a><a name="p88031126184311"></a>Stream.fdopenStreamSync</p>
</td>
</tr>
<tr id="row82479241516"><td class="cellrowborder" valign="top" width="15.02%" headers="mcps1.2.5.1.1 "><p id="p12923111711216"><a name="p12923111711216"></a><a name="p12923111711216"></a>Sandbox file API</p>
</td>
<td class="cellrowborder" valign="top" width="32.25%" headers="mcps1.2.5.1.2 "><p id="p49237171020"><a name="p49237171020"></a><a name="p49237171020"></a>Provides a subset or a combination of the capabilities provided by the basic file, directory, and statistical APIs based on the specified URIs.</p>
</td>
<td class="cellrowborder" valign="top" width="25.840000000000003%" headers="mcps1.2.5.1.3 "><p id="p724852418510"><a name="p724852418510"></a><a name="p724852418510"></a>@system.file</p>
</td>
<td class="cellrowborder" valign="top" width="26.889999999999997%" headers="mcps1.2.5.1.4 "><p id="p0390135216324"><a name="p0390135216324"></a><a name="p0390135216324"></a>move</p>
<p id="p202016525456"><a name="p202016525456"></a><a name="p202016525456"></a>copy</p>
<p id="p8142558194520"><a name="p8142558194520"></a><a name="p8142558194520"></a>list</p>
</td>
</tr>
</tbody>
</table>
The URIs used in sandbox file APIs are classified into three types, as described in the following table.
**Table 2** URI types
<a name="table947391523311"></a>
<table><thead align="left"><tr id="row84733151332"><th class="cellrowborder" valign="top" width="13.969999999999999%" id="mcps1.2.5.1.1"><p id="p32271219113313"><a name="p32271219113313"></a><a name="p32271219113313"></a>Directory Type</p>
</th>
<th class="cellrowborder" valign="top" width="16.41%" id="mcps1.2.5.1.2"><p id="p3227191993310"><a name="p3227191993310"></a><a name="p3227191993310"></a>Prefix</p>
</th>
<th class="cellrowborder" valign="top" width="22%" id="mcps1.2.5.1.3"><p id="p192277196333"><a name="p192277196333"></a><a name="p192277196333"></a>Access Visibility</p>
</th>
<th class="cellrowborder" valign="top" width="47.620000000000005%" id="mcps1.2.5.1.4"><p id="p18227719103313"><a name="p18227719103313"></a><a name="p18227719103313"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row1474161514330"><td class="cellrowborder" valign="top" width="13.969999999999999%" headers="mcps1.2.5.1.1 "><p id="p9896152614335"><a name="p9896152614335"></a><a name="p9896152614335"></a>Temporary directory</p>
</td>
<td class="cellrowborder" valign="top" width="16.41%" headers="mcps1.2.5.1.2 "><p id="p389632610335"><a name="p389632610335"></a><a name="p389632610335"></a>internal://cache/</p>
</td>
<td class="cellrowborder" valign="top" width="22%" headers="mcps1.2.5.1.3 "><p id="p989610267332"><a name="p989610267332"></a><a name="p989610267332"></a>Current app only</p>
</td>
<td class="cellrowborder" valign="top" width="47.620000000000005%" headers="mcps1.2.5.1.4 "><p id="p16896726173311"><a name="p16896726173311"></a><a name="p16896726173311"></a>Readable and writable, and can be cleared at any time. This directory is usually used for temporary downloads or caches.</p>
</td>
</tr>
<tr id="row194741315193312"><td class="cellrowborder" valign="top" width="13.969999999999999%" headers="mcps1.2.5.1.1 "><p id="p12896142620339"><a name="p12896142620339"></a><a name="p12896142620339"></a>Private directory of an app</p>
</td>
<td class="cellrowborder" valign="top" width="16.41%" headers="mcps1.2.5.1.2 "><p id="p118969269332"><a name="p118969269332"></a><a name="p118969269332"></a>internal://app/</p>
</td>
<td class="cellrowborder" valign="top" width="22%" headers="mcps1.2.5.1.3 "><p id="p189612263333"><a name="p189612263333"></a><a name="p189612263333"></a>Current app only</p>
</td>
<td class="cellrowborder" valign="top" width="47.620000000000005%" headers="mcps1.2.5.1.4 "><p id="p1089682623314"><a name="p1089682623314"></a><a name="p1089682623314"></a>Deleted when the app is uninstalled.</p>
</td>
</tr>
<tr id="row204743152331"><td class="cellrowborder" valign="top" width="13.969999999999999%" headers="mcps1.2.5.1.1 "><p id="p3896152673319"><a name="p3896152673319"></a><a name="p3896152673319"></a>External storage</p>
</td>
<td class="cellrowborder" valign="top" width="16.41%" headers="mcps1.2.5.1.2 "><p id="p158961526113310"><a name="p158961526113310"></a><a name="p158961526113310"></a>internal://share/</p>
</td>
<td class="cellrowborder" valign="top" width="22%" headers="mcps1.2.5.1.3 "><p id="p16896326133310"><a name="p16896326133310"></a><a name="p16896326133310"></a>All apps</p>
</td>
<td class="cellrowborder" valign="top" width="47.620000000000005%" headers="mcps1.2.5.1.4 "><p id="p5897126113313"><a name="p5897126113313"></a><a name="p5897126113313"></a>Deleted when the app is uninstalled. Other apps with granted permissions can read and write files in this directory.</p>
</td>
</tr>
</tbody>
</table>
### Usage Guidelines<a name="section149mcpsimp"></a>
The I/O APIs provided by the Distributed File subsystem can be classified into the following types based on the programming model:
- Synchronous programming model
APIs whose names contain **Sync** are implemented as a synchronous model. When a synchronous API is called, the calling process waits until a value is returned.
The following example opens a file stream in read-only mode, attempts to read the first 4096 bytes, converts them into a UTF-8-encoded string, and then closes the file stream:
```
import fileio from '@OHOS.distributedfile.fileio';
try {
var ss = fileio.Stream.createStreamSync("tmp", "r")
buf = new ArrayBuffer(4096)
ss.readSync(buf)
console.log(String.fromCharCode.apply(null, new Uint8Array(buf)))
ss.closeSync()
}
catch (e) {
console.log(e);
}
```
#### 安装教程
- Asynchronous programming model: Promise
1. xxxx
2. xxxx
3. xxxx
In the **@OHOS.distributedfile.fileio** module, the APIs whose names do not contain **Sync** and to which a callback is not passed as their input parameter are implemented as the Promise asynchronous model. The Promise asynchronous model is one of the OHOS standard asynchronous models. When an asynchronous API using the Promise model is called, the API returns a Promise object while executing the concerned task asynchronously. The Promise object represents the asynchronous operation result. When there is more than one result, the results are returned as properties of the Promise object.
#### 使用说明
In the following example, a Promise chain is used to open a file stream in read-only mode, attempt to read the first 4096 bytes of the file, display the length of the content read, and then close the file:
1. xxxx
2. xxxx
3. xxxx
#### 参与贡献
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
```
import fileio from '@OHOS.distributedfile.fileio';
try {
let openedStream
fileio.Stream.createStream("test.txt", "r")
.then(function (ss) {
openedStream = ss;
return ss.read(new ArrayBuffer(4096))
})
.then(function (res) {
console.log(res.bytesRead);
console.log(String.fromCharCode.apply(null, new Uint8Array(res.buffer)))
return openedStream.close()
})
.then(function (undefined) {
console.log("Stream is closed")
})
.catch(function (e) {
console.log(e)
})
} catch (e) {
console.log(e)
}
```
#### 特技
- Asynchronous programming model: Callback
In the **@OHOS.distributedfile.fileio** module, the APIs whose names do not contain **Sync** and to which a callback is directly passed as their input parameter are implemented as the callback asynchronous model. The callback asynchronous model is also one of the OHOS standard asynchronous models. When an asynchronous API with a callback passed is called, the API executes the concerned task asynchronously and returns the execution result as the input parameters of the registered callback. The first parameter is of the **undefined** or **Error** type, indicating that the execution succeeds or fails, respectively.
The following example creates a file stream asynchronously, reads the first 4096 bytes of the file asynchronously in the callback invoked when the file stream is created, and then closes the file asynchronously in the callback invoked when the file is read:
```
import fileio from '@OHOS.distributedfile.fileio';
try {
fileio.Stream.createStream("./testdir/test_stream.txt", "r", function (err, ss) {
if (!err) {
ss.read(new ArrayBuffer(4096), {}, function (err, buf, readLen) {
if (!err) {
console.log('readLen: ' + readLen)
console.log('data: ' + String.fromCharCode.apply(null, new Uint8Array(buf)))
} else {
console.log('Cannot read from the stream ' + err)
}
ss.close(function (err) {
console.log(`Stream is ${err ? 'not' : ''}closed`)
});
})
} else {
console.log('Cannot open the stream ' + err)
}
})
} catch (e) {
console.log(e)
}
```
- Asynchronous programming model: Legacy
All APIs in the **@system.file** module are implemented as the legacy asynchronous model. When calling such an API, you need to implement three callbacks \(including **success**, **fail**, and **complete**\) to be invoked when the execution is successful, fails, or is complete, respectively. If the input parameters are correct, the API calls the **success** or **fail** callback based on whether the asynchronous task is successful after the task execution is complete, and finally calls the **complete** callback.
The following example asynchronously checks whether the file pointed to by the specified URI exists and provides three callbacks to print the check result:
```
import file from '@system.file'
file.access({
uri: 'internal://app/test.txt',
success: function() {
console.log('call access success.');
},
fail: function(data, code) {
console.error('call fail callback fail, code: ' + code + ', data: ' + data);
},
complete: function () {
console.log('call access finally.');
}
});
console.log("file access tested done")
```
## Repositories Involved<a name="section178mcpsimp"></a>
**Distributed File subsystem**
distributeddatamgr_distributedfile
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

281
README_zh.md Normal file
View File

@ -0,0 +1,281 @@
# 分布式文件子系统<a name="ZH-CN_TOPIC_0000001101541814"></a>
- [简介](#section104mcpsimp)
- [系统架构](#section110mcpsimp)
- [目录结构](#section113mcpsimp)
- [约束](#section117mcpsimp)
- [说明](#section125mcpsimp)
- [接口说明](#section127mcpsimp)
- [使用说明](#section149mcpsimp)
- [相关仓](#section178mcpsimp)
## 简介<a name="section104mcpsimp"></a>
分布式文件子系统当前向应用程序提供用于的 IO 的 JS 接口。其具体包括用于管理文件的基本文件接口,用于管理目录的基本目录接口,用于获取文件信息的统计接口,用于流式读写文件的流式接口,以及接收 URI 而非绝对路径的沙盒接口。
### 系统架构<a name="section110mcpsimp"></a>
当前分布式文件子系统仅面向应用提供本地 JS 文件接口,这些接口分别通过 FileIO 模块以及 File 模块提供。架构上,分布式文件子系统实现了自研的 LibN其抽象了 NAPI 层接口,向分布式文件子系统提供包括基本类型系统、内存管理、通用编程模型在内的基本能力。本系统对外依赖 JS 开发框架提供将 JS 接口转换为 C++ 代码的能力,依赖用户程序框架提供应用相关目录,依赖 GLIBC Runtimes 提供 IO 能力。
**图 1** 分布式文件子系统架构图<a name="fig174088216114"></a>
![](figures/分布式文件子系统架构图.png "分布式文件子系统架构图")
## 目录结构<a name="section113mcpsimp"></a>
```
foundation/distributeddatamgr/distributedfile
├── figures # 仓库图床
└── interfaces # 接口代码
└── kits # 对外接口代码
```
## 约束<a name="section117mcpsimp"></a>
本地 IO 接口
- 目前仅支持 UTF-8/16 编码;
- 目前 URI 暂不支持外部存储目录;
## 说明<a name="section125mcpsimp"></a>
### 接口说明<a name="section127mcpsimp"></a>
当前分布式文件子系统开放本地文件目录访问接口,按照功能,其可划分为如下几种类型:
**表 1** 接口类型表
<a name="table99228171027"></a>
<table><thead align="left"><tr id="row2092221715211"><th class="cellrowborder" valign="top" width="15.02%" id="mcps1.2.5.1.1"><p id="p79225171524"><a name="p79225171524"></a><a name="p79225171524"></a>接口类型</p>
</th>
<th class="cellrowborder" valign="top" width="32.25%" id="mcps1.2.5.1.2"><p id="p992271711216"><a name="p992271711216"></a><a name="p992271711216"></a>接口用途</p>
</th>
<th class="cellrowborder" valign="top" width="25.840000000000003%" id="mcps1.2.5.1.3"><p id="p29225175213"><a name="p29225175213"></a><a name="p29225175213"></a>相关模块</p>
</th>
<th class="cellrowborder" valign="top" width="26.889999999999997%" id="mcps1.2.5.1.4"><p id="p129221017720"><a name="p129221017720"></a><a name="p129221017720"></a>接口示例(类名.方法名)</p>
</th>
</tr>
</thead>
<tbody><tr id="row149231717327"><td class="cellrowborder" valign="top" width="15.02%" headers="mcps1.2.5.1.1 "><p id="p3923417629"><a name="p3923417629"></a><a name="p3923417629"></a>基本文件接口</p>
</td>
<td class="cellrowborder" valign="top" width="32.25%" headers="mcps1.2.5.1.2 "><p id="p89236171124"><a name="p89236171124"></a><a name="p89236171124"></a>需要用户提供绝对路径或文件描述符fd提供创建、修改及访问文件或修改文件权限的能力</p>
</td>
<td class="cellrowborder" valign="top" width="25.840000000000003%" headers="mcps1.2.5.1.3 "><p id="p22011844349"><a name="p22011844349"></a><a name="p22011844349"></a>@OHOS.distributedfile.fileio</p>
</td>
<td class="cellrowborder" valign="top" width="26.889999999999997%" headers="mcps1.2.5.1.4 "><p id="p1784383174320"><a name="p1784383174320"></a><a name="p1784383174320"></a>accessSync</p>
<p id="p184313310437"><a name="p184313310437"></a><a name="p184313310437"></a>chownSync</p>
<p id="p1684318315436"><a name="p1684318315436"></a><a name="p1684318315436"></a>chmodSync</p>
</td>
</tr>
<tr id="row1692320171825"><td class="cellrowborder" valign="top" width="15.02%" headers="mcps1.2.5.1.1 "><p id="p392391710219"><a name="p392391710219"></a><a name="p392391710219"></a>基本目录接口</p>
</td>
<td class="cellrowborder" valign="top" width="32.25%" headers="mcps1.2.5.1.2 "><p id="p109232176211"><a name="p109232176211"></a><a name="p109232176211"></a>需要用户提供绝对路径,提供读取目录及判断文件类型的能力</p>
</td>
<td class="cellrowborder" valign="top" width="25.840000000000003%" headers="mcps1.2.5.1.3 "><p id="p271274219410"><a name="p271274219410"></a><a name="p271274219410"></a>@OHOS.distributedfile.fileio</p>
</td>
<td class="cellrowborder" valign="top" width="26.889999999999997%" headers="mcps1.2.5.1.4 "><p id="p29233177216"><a name="p29233177216"></a><a name="p29233177216"></a>Dir.openDirSync</p>
</td>
</tr>
<tr id="row14923171716217"><td class="cellrowborder" valign="top" width="15.02%" headers="mcps1.2.5.1.1 "><p id="p159234176215"><a name="p159234176215"></a><a name="p159234176215"></a>基本Stat接口</p>
</td>
<td class="cellrowborder" valign="top" width="32.25%" headers="mcps1.2.5.1.2 "><p id="p1992314179215"><a name="p1992314179215"></a><a name="p1992314179215"></a>需要用户提供绝对路径,提供包括文件大小、访问权限、修改时间在内的基本统计信息</p>
</td>
<td class="cellrowborder" valign="top" width="25.840000000000003%" headers="mcps1.2.5.1.3 "><p id="p325774111413"><a name="p325774111413"></a><a name="p325774111413"></a>@OHOS.distributedfile.fileio</p>
</td>
<td class="cellrowborder" valign="top" width="26.889999999999997%" headers="mcps1.2.5.1.4 "><p id="p59231317420"><a name="p59231317420"></a><a name="p59231317420"></a>Stat.statSync</p>
</td>
</tr>
<tr id="row692319171228"><td class="cellrowborder" valign="top" width="15.02%" headers="mcps1.2.5.1.1 "><p id="p1592318171526"><a name="p1592318171526"></a><a name="p1592318171526"></a>流式文件接口</p>
</td>
<td class="cellrowborder" valign="top" width="32.25%" headers="mcps1.2.5.1.2 "><p id="p992311171421"><a name="p992311171421"></a><a name="p992311171421"></a>需要用户提供绝对路径或文件描述符,提供流式读写文件的能力</p>
</td>
<td class="cellrowborder" valign="top" width="25.840000000000003%" headers="mcps1.2.5.1.3 "><p id="p1692321716217"><a name="p1692321716217"></a><a name="p1692321716217"></a>@OHOS.distributedfile.fileio</p>
</td>
<td class="cellrowborder" valign="top" width="26.889999999999997%" headers="mcps1.2.5.1.4 "><p id="p10923141711215"><a name="p10923141711215"></a><a name="p10923141711215"></a>Stream.createStreamSync</p>
<p id="p88031126184311"><a name="p88031126184311"></a><a name="p88031126184311"></a>Stream.fdopenStreamSync</p>
</td>
</tr>
<tr id="row82479241516"><td class="cellrowborder" valign="top" width="15.02%" headers="mcps1.2.5.1.1 "><p id="p12923111711216"><a name="p12923111711216"></a><a name="p12923111711216"></a>沙盒文件接口</p>
</td>
<td class="cellrowborder" valign="top" width="32.25%" headers="mcps1.2.5.1.2 "><p id="p49237171020"><a name="p49237171020"></a><a name="p49237171020"></a>需要用户提供 URI提供基本文件接口、基本目录接口及基本统计接口能力的子集能力或这些能力的组合能力</p>
</td>
<td class="cellrowborder" valign="top" width="25.840000000000003%" headers="mcps1.2.5.1.3 "><p id="p724852418510"><a name="p724852418510"></a><a name="p724852418510"></a>@system.file</p>
</td>
<td class="cellrowborder" valign="top" width="26.889999999999997%" headers="mcps1.2.5.1.4 "><p id="p0390135216324"><a name="p0390135216324"></a><a name="p0390135216324"></a>move</p>
<p id="p202016525456"><a name="p202016525456"></a><a name="p202016525456"></a>copy</p>
<p id="p8142558194520"><a name="p8142558194520"></a><a name="p8142558194520"></a>list</p>
</td>
</tr>
</tbody>
</table>
其中,沙盒文件接口所使用的 URI 具体可划分为三种类型:
**表 2** URI类型表
<a name="table947391523311"></a>
<table><thead align="left"><tr id="row84733151332"><th class="cellrowborder" valign="top" width="13.969999999999999%" id="mcps1.2.5.1.1"><p id="p32271219113313"><a name="p32271219113313"></a><a name="p32271219113313"></a>目录类型</p>
</th>
<th class="cellrowborder" valign="top" width="16.41%" id="mcps1.2.5.1.2"><p id="p3227191993310"><a name="p3227191993310"></a><a name="p3227191993310"></a>路径前缀</p>
</th>
<th class="cellrowborder" valign="top" width="22%" id="mcps1.2.5.1.3"><p id="p192277196333"><a name="p192277196333"></a><a name="p192277196333"></a>访问可见性</p>
</th>
<th class="cellrowborder" valign="top" width="47.620000000000005%" id="mcps1.2.5.1.4"><p id="p18227719103313"><a name="p18227719103313"></a><a name="p18227719103313"></a>说明</p>
</th>
</tr>
</thead>
<tbody><tr id="row1474161514330"><td class="cellrowborder" valign="top" width="13.969999999999999%" headers="mcps1.2.5.1.1 "><p id="p9896152614335"><a name="p9896152614335"></a><a name="p9896152614335"></a>临时目录</p>
</td>
<td class="cellrowborder" valign="top" width="16.41%" headers="mcps1.2.5.1.2 "><p id="p389632610335"><a name="p389632610335"></a><a name="p389632610335"></a>internal://cache/</p>
</td>
<td class="cellrowborder" valign="top" width="22%" headers="mcps1.2.5.1.3 "><p id="p989610267332"><a name="p989610267332"></a><a name="p989610267332"></a>仅本应用可见</p>
</td>
<td class="cellrowborder" valign="top" width="47.620000000000005%" headers="mcps1.2.5.1.4 "><p id="p16896726173311"><a name="p16896726173311"></a><a name="p16896726173311"></a>可读写,随时可能清除,不保证持久性。一般用作下载临时目录或缓存目录。</p>
</td>
</tr>
<tr id="row194741315193312"><td class="cellrowborder" valign="top" width="13.969999999999999%" headers="mcps1.2.5.1.1 "><p id="p12896142620339"><a name="p12896142620339"></a><a name="p12896142620339"></a>应用私有目录</p>
</td>
<td class="cellrowborder" valign="top" width="16.41%" headers="mcps1.2.5.1.2 "><p id="p118969269332"><a name="p118969269332"></a><a name="p118969269332"></a>internal://app/</p>
</td>
<td class="cellrowborder" valign="top" width="22%" headers="mcps1.2.5.1.3 "><p id="p189612263333"><a name="p189612263333"></a><a name="p189612263333"></a>仅本应用可见</p>
</td>
<td class="cellrowborder" valign="top" width="47.620000000000005%" headers="mcps1.2.5.1.4 "><p id="p1089682623314"><a name="p1089682623314"></a><a name="p1089682623314"></a>随应用卸载删除。</p>
</td>
</tr>
<tr id="row204743152331"><td class="cellrowborder" valign="top" width="13.969999999999999%" headers="mcps1.2.5.1.1 "><p id="p3896152673319"><a name="p3896152673319"></a><a name="p3896152673319"></a>外部存储</p>
</td>
<td class="cellrowborder" valign="top" width="16.41%" headers="mcps1.2.5.1.2 "><p id="p158961526113310"><a name="p158961526113310"></a><a name="p158961526113310"></a>internal://share/</p>
</td>
<td class="cellrowborder" valign="top" width="22%" headers="mcps1.2.5.1.3 "><p id="p16896326133310"><a name="p16896326133310"></a><a name="p16896326133310"></a>所有应用可见</p>
</td>
<td class="cellrowborder" valign="top" width="47.620000000000005%" headers="mcps1.2.5.1.4 "><p id="p5897126113313"><a name="p5897126113313"></a><a name="p5897126113313"></a>随应用卸载删除。其他应用在有相应权限的情况下可读写此目录下的文件。</p>
</td>
</tr>
</tbody>
</table>
### 使用说明<a name="section149mcpsimp"></a>
当前分布式文件子系统所提供的 IO 接口,按照编程模型,可划分为如下几种类型:
- 同步编程模型
名称包含 Sync 的接口实现为同步模型。用户在调用这些接口的时候,将同步等待,直至执行完成,执行结果以函数返回值的形式返回。
下例以只读的方式打开一个文件流,接着试图读取其中前 4096 个字节并将之转换为 UTF-8 编码的字符串,最后关闭该文件流。
```
import fileio from '@OHOS.distributedfile.fileio';
try {
var ss = fileio.Stream.createStreamSync("tmp", "r")
buf = new ArrayBuffer(4096)
ss.readSync(buf)
console.log(String.fromCharCode.apply(null, new Uint8Array(buf)))
ss.closeSync()
}
catch (e) {
console.log(e);
}
```
- 异步编程模型Promise
@OHOS.distributedfile.fileio 模块中,名称不含 Sync 的接口,在不提供最后一个函数型参数 callback 的时候,即实现为 Promsie 异步模型。Promise 异步模型是 OHOS 标准异步模型之一。用户在调用这些接口的时候,接口实现将异步执行任务,同时返回一个 promise 对象,其代表异步操作的结果。在返回的结果的个数超过一个时,其以对象属性的形式返回。
下例通过 Promise 链依次完成:以只读方式打开文件流、尝试读取文件前 4096 个字节、显示读取内容的长度,最后关闭文件。
```
import fileio from '@OHOS.distributedfile.fileio';
try {
let openedStream
fileio.Stream.createStream("test.txt", "r")
.then(function (ss) {
openedStream = ss;
return ss.read(new ArrayBuffer(4096))
})
.then(function (res) {
console.log(res.bytesRead);
console.log(String.fromCharCode.apply(null, new Uint8Array(res.buffer)))
return openedStream.close()
})
.then(function (undefined) {
console.log("Stream is closed")
})
.catch(function (e) {
console.log(e)
})
} catch (e) {
console.log(e)
}
```
- 异步编程模型Callback
@OHOS.distributedfile.fileio 模块中,名字不含 Sync 的接口,在提供最后一个函数性参数 callback 的时候,即实现为 Callback 异步模型。Callback 异步模型是 OHOS 标准异步模型之一。用户在调用这些接口的时候,接口实现将异步执行任务。任务执行结果以参数的形式提供给用户注册的回调函数。这些参数的第一个是 Error 或 undefined 类型,分别表示执行出错与正常。
下例异步创建文件流,并在文件流的回调函数中异步读取文件的前 4096 字节,接着在读取文件的回调函数中异步关闭文件。
```
import fileio from '@OHOS.distributedfile.fileio';
try {
fileio.Stream.createStream("./testdir/test_stream.txt", "r", function (err, ss) {
if (!err) {
ss.read(new ArrayBuffer(4096), {}, function (err, buf, readLen) {
if (!err) {
console.log('readLen: ' + readLen)
console.log('data: ' + String.fromCharCode.apply(null, new Uint8Array(buf)))
} else {
console.log('Cannot read from the stream ' + err)
}
ss.close(function (err) {
console.log(`Stream is ${err ? 'not' : ''}closed`)
});
})
} else {
console.log('Cannot open the stream ' + err)
}
})
} catch (e) {
console.log(e)
}
```
- 异步编程模型Legacy
@system.file 模块中的所有接口都实现为 Legacy 异步模型。用户在调用这些接口的时候,需要提供 success、fail 及 complete 三个回调。在正确提供参数的情况下,当异步任务完成后,接口会根据是否成功,分别调用 success 回调或 fail 回调,并最终调用 complete 回调。
下例异步判断 URI 所指向的文件是否存在,并相应提供三个回调用于打印判断结果。
```
import file from '@system.file'
file.access({
uri: 'internal://app/test.txt',
success: function() {
console.log('call access success.');
},
fail: function(data, code) {
console.error('call fail callback fail, code: ' + code + ', data: ' + data);
},
complete: function () {
console.log('call access finally.');
}
});
console.log("file access tested done")
```
## 相关仓<a name="section178mcpsimp"></a>
**分布式文件**
distributeddatamgr_distributedfile

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -0,0 +1,57 @@
# Copyright (c) 2021 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/ohos.gni")
ohos_shared_library("fileio") {
subsystem_name = "distributeddatamgr"
part_name = "distributedfilejs"
relative_install_dir = "module"
include_dirs = [
"//third_party/node/src",
"//foundation/ace/napi/interfaces/kits",
"//utils/native/base/include",
]
sources = [
"src/common/fd_guard.cpp",
"src/common/napi/n_class.cpp",
"src/common/napi/n_func_arg.cpp",
"src/common/napi/n_val.cpp",
"src/common/uni_error.cpp",
"src/mod_fileio/class_dir/dir_n_exporter.cpp",
"src/mod_fileio/class_dirent/dirent_n_exporter.cpp",
"src/mod_fileio/class_stat/stat_n_exporter.cpp",
"src/mod_fileio/class_stream/stream_n_exporter.cpp",
"src/mod_fileio/common_func.cpp",
"src/mod_fileio/module.cpp",
"src/mod_fileio/properties/prop_n_exporter.cpp",
]
deps = [
"//foundation/ace/napi:ace_napi",
"//utils/native/base:utilsecurec",
]
external_deps = [
"hiviewdfx_hilog_native:libhilog",
]
}
group("build_kits_js") {
deps = [
":fileio",
]
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "fd_guard.h"
#include <unistd.h>
namespace OHOS {
namespace DistributedFS {
FDGuard::FDGuard(int fd) : fd_(fd) {}
FDGuard::~FDGuard()
{
if (fd_ > 0) {
close(fd_);
}
}
int FDGuard::GetFD() const
{
return fd_;
}
void FDGuard::SetFD(int fd)
{
fd_ = fd;
}
void FDGuard::ClearFD()
{
fd_ = -1;
}
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
namespace OHOS {
namespace DistributedFS {
class FDGuard {
public:
FDGuard() = default;
explicit FDGuard(int fd);
~FDGuard();
int GetFD() const;
void SetFD(int fd);
void ClearFD();
private:
int fd_ = -1;
};
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <cstdio>
#include <string>
#include <vector>
#ifndef FILE_SUBSYSTEM_DEV_ON_PC
#include "hilog/log.h"
#endif
namespace OHOS {
namespace DistributedFS {
#ifndef FILE_SUBSYSTEM_DEV_ON_PC
static constexpr int FILEIO_DOMAIN_ID = 0;
static constexpr OHOS::HiviewDFX::HiLogLabel FILEIO_LABEL = { LOG_CORE, FILEIO_DOMAIN_ID, "distributedfilejs" };
#ifdef HILOGD
#undef HILOGD
#endif
#ifdef HILOGF
#undef HILOGF
#endif
#ifdef HILOGE
#undef HILOGE
#endif
#ifdef HILOGW
#undef HILOGW
#endif
#ifdef HILOGI
#undef HILOGI
#endif
#define HILOGD(fmt, ...) \
(void)OHOS::HiviewDFX::HiLog::Debug(OHOS::DistributedFS::FILEIO_LABEL, "%{public}s: " fmt, __func__, ##__VA_ARGS__)
#define HILOGI(fmt, ...) \
(void)OHOS::HiviewDFX::HiLog::Info(OHOS::DistributedFS::FILEIO_LABEL, "%{public}s: " fmt, __func__, ##__VA_ARGS__)
#define HILOGW(fmt, ...) \
(void)OHOS::HiviewDFX::HiLog::Warn(OHOS::DistributedFS::FILEIO_LABEL, "%{public}s: " fmt, __func__, ##__VA_ARGS__)
#define HILOGE(fmt, ...) \
(void)OHOS::HiviewDFX::HiLog::Error(OHOS::DistributedFS::FILEIO_LABEL, "%{public}s: " fmt, __func__, ##__VA_ARGS__)
#define HILOGF(fmt, ...) \
(void)OHOS::HiviewDFX::HiLog::Fatal(OHOS::DistributedFS::FILEIO_LABEL, "%{public}s: " fmt, __func__, ##__VA_ARGS__)
#else
#define PCLOG(fmt, ...) \
do { \
const std::vector<std::string> filter = { \
"{public}", \
"{private}", \
}; \
std::string str____(fmt); \
for (auto &&pattern : filter) { \
size_t pos = 0; \
while (std::string::npos != (pos = str____.find(pattern))) { \
str____.erase(pos, pattern.length()); \
} \
} \
str____ += "\n"; \
printf(str____.c_str(), ##__VA_ARGS__); \
} while (0);
#define HILOGD(fmt, ...) PCLOG("%{public}s: " fmt, __func__, ##__VA_ARGS__)
#define HILOGI(fmt, ...) PCLOG("%{public}s: " fmt, __func__, ##__VA_ARGS__)
#define HILOGW(fmt, ...) PCLOG("%{public}s: " fmt, __func__, ##__VA_ARGS__)
#define HILOGE(fmt, ...) PCLOG("%{public}s: " fmt, __func__, ##__VA_ARGS__)
#define HILOGF(fmt, ...) PCLOG("%{public}s: " fmt, __func__, ##__VA_ARGS__)
#endif
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,99 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "n_class.h"
#include <iostream>
#include <sstream>
#include "../log.h"
namespace OHOS {
namespace DistributedFS {
using namespace std;
NClass &NClass::GetInstance()
{
static NClass nClass;
return nClass;
}
tuple<bool, napi_value> NClass::DefineClass(napi_env env,
string className,
napi_callback constructor,
vector<napi_property_descriptor> &&properties)
{
napi_value classVal = nullptr;
napi_status stat = napi_define_class(env,
className.c_str(),
className.length(),
constructor,
nullptr,
properties.size(),
properties.data(),
&classVal);
if (stat != napi_ok) {
HILOGE("INNER BUG. Cannot define class %{public}s because of %{public}d", className.c_str(), stat);
}
return { stat == napi_ok, classVal };
}
bool NClass::SaveClass(napi_env env, string className, napi_value exClass)
{
NClass &nClass = NClass::GetInstance();
lock_guard(nClass.exClassMapLock);
if (nClass.exClassMap.find(className) != nClass.exClassMap.end()) {
return true;
}
napi_ref constructor;
napi_status res = napi_create_reference(env, exClass, 1, &constructor);
if (res == napi_ok) {
nClass.exClassMap.insert({ className, constructor });
HILOGI("Class %{public}s has been saved", className.c_str());
} else {
HILOGE("INNER BUG. Cannot ref class constructor %{public}s because of %{public}d", className.c_str(), res);
}
return res == napi_ok;
}
napi_value NClass::InstantiateClass(napi_env env, string className, vector<napi_value> args)
{
NClass &nClass = NClass::GetInstance();
lock_guard(nClass.exClassMapLock);
auto it = nClass.exClassMap.find(className);
if (it == nClass.exClassMap.end()) {
HILOGE("Class %{public}s hasn't been saved yet", className.c_str());
return nullptr;
}
napi_value cons = nullptr;
napi_status status = napi_get_reference_value(env, it->second, &cons);
if (status != napi_ok) {
HILOGE("INNER BUG. Cannot deref class %{public}s because of %{public}d", className.c_str(), status);
return nullptr;
}
napi_value instance = nullptr;
status = napi_new_instance(env, cons, args.size(), args.data(), &instance);
if (status != napi_ok) {
HILOGE("INNER BUG. Cannot instantiate the class %{public}s because of %{public}d", className.c_str(), status);
return nullptr;
}
return instance;
}
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,82 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "uni_header.h"
#include <map>
#include <memory>
#include <mutex>
#include <string>
#include <tuple>
#include <vector>
#include "../log.h"
namespace OHOS {
namespace DistributedFS {
class NClass final {
public:
NClass(const NClass &) = delete;
NClass &operator = (const NClass &) = delete;
static NClass &GetInstance();
static std::tuple<bool, napi_value> DefineClass(napi_env env,
std::string className,
napi_callback constructor,
std::vector<napi_property_descriptor> &&properties);
static bool SaveClass(napi_env env, std::string className, napi_value exClass);
static napi_value InstantiateClass(napi_env env, std::string className, std::vector<napi_value> args);
template <class T> static T *GetEntityOf(napi_env env, napi_value objStat)
{
if (!env || !objStat) {
HILOGE("Empty input: env %d, obj %d", env == nullptr, objStat == nullptr);
return nullptr;
}
T *t = nullptr;
napi_status status = napi_unwrap(env, objStat, (void **)&t);
if (status != napi_ok) {
HILOGE("Cannot umwarp for pointer: %d", status);
return nullptr;
}
return t;
}
template <class T> static bool SetEntityFor(napi_env env, napi_value obj, std::unique_ptr<T> entity)
{
napi_status status = napi_wrap(
env,
obj,
entity.get(),
[](napi_env env, void *data, void *hint) {
auto entity = static_cast<T *>(data);
delete entity;
},
nullptr,
nullptr);
entity.release();
return status == napi_ok;
}
private:
NClass() = default;
~NClass() = default;
std::map<std::string, napi_ref> exClassMap;
std::mutex exClassMapLock;
};
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "uni_header.h"
#include <functional>
#include <string>
#include "n_val.h"
namespace OHOS {
namespace DistributedFS {
class NExporter {
public:
NExporter(napi_env env, napi_value exports) : exports_(env, exports) {};
virtual ~NExporter() = default;
virtual bool Export() = 0;
virtual std::string GetClassName() = 0;
protected:
NVal exports_;
};
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,111 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "n_func_arg.h"
#include <iostream>
#include <sstream>
#include "../log.h"
#include "../uni_error.h"
namespace OHOS {
namespace DistributedFS {
using namespace std;
NFuncArg::NFuncArg(napi_env env, napi_callback_info info) : env_(env), info_(info) {}
NFuncArg::~NFuncArg() {}
void NFuncArg::SetArgc(size_t argc)
{
argc_ = argc;
}
void NFuncArg::SetThisVar(napi_value thisVar)
{
thisVar_ = thisVar;
}
size_t NFuncArg::GetArgc(void) const
{
return argc_;
}
napi_value NFuncArg::GetThisVar(void) const
{
return thisVar_;
}
napi_value NFuncArg::GetArg(size_t argPos) const
{
return (argPos < GetArgc()) ? argv_[argPos] : nullptr;
}
napi_value NFuncArg::operator[](size_t argPos) const
{
return GetArg(argPos);
}
bool NFuncArg::InitArgs(std::function<bool()> argcChecker)
{
SetArgc(0);
argv_.reset();
size_t argc;
napi_value thisVar;
napi_status status = napi_get_cb_info(env_, info_, &argc, nullptr, &thisVar, nullptr);
if (status != napi_ok) {
HILOGE("Cannot get num of func args for %{public}d", status);
return false;
}
if (argc) {
argv_ = make_unique<napi_value[]>(argc);
status = napi_get_cb_info(env_, info_, &argc, argv_.get(), &thisVar, nullptr);
if (status != napi_ok) {
HILOGE("Cannot get func args for %{public}d", status);
return false;
}
}
SetArgc(argc);
SetThisVar(thisVar);
return argcChecker();
}
bool NFuncArg::InitArgs(size_t argc)
{
return InitArgs([argc, this]() {
size_t realArgc = GetArgc();
if (argc != realArgc) {
HILOGE("Num of args recved eq %zu while expecting %{public}zu", realArgc, argc);
return false;
}
return true;
});
}
bool NFuncArg::InitArgs(size_t minArgc, size_t maxArgc)
{
return InitArgs([minArgc, maxArgc, this]() {
size_t realArgc = GetArgc();
if (minArgc > realArgc || maxArgc < realArgc) {
HILOGE("Num of args recved eq %zu while expecting %{public}zu ~ %{public}zu", realArgc, minArgc, maxArgc);
return false;
}
return true;
});
}
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <functional>
#include <map>
#include <memory>
#include <vector>
#include "n_val.h"
#include "uni_header.h"
namespace OHOS {
namespace DistributedFS {
enum NARG_CNT {
ZERO = 0,
ONE = 1,
TWO = 2,
THREE = 3,
FOUR = 4,
};
enum NARG_POS {
FIRST = 0,
SECOND = 1,
THIRD = 2,
FOURTH = 3,
};
class NFuncArg final {
public:
NFuncArg(napi_env env, napi_callback_info info);
virtual ~NFuncArg();
bool InitArgs(size_t argc);
bool InitArgs(size_t minArgc, size_t maxArgc);
size_t GetArgc() const;
napi_value GetThisVar() const;
napi_value operator[](size_t idx) const;
napi_value GetArg(size_t argPos) const;
private:
napi_env env_ = nullptr;
napi_callback_info info_ = nullptr;
size_t argc_ = 0;
std::unique_ptr<napi_value[]> argv_ = { nullptr };
napi_value thisVar_ = nullptr;
bool InitArgs(std::function<bool()> argcChecker);
void SetArgc(size_t argc);
void SetThisVar(napi_value thisVar);
};
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,272 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "n_val.h"
#include <sstream>
#include <string>
#include "../log.h"
#include "../uni_error.h"
namespace OHOS {
namespace DistributedFS {
using namespace std;
NVal::NVal(napi_env nEnv, napi_value nVal = nullptr) : env_(nEnv), val_(nVal) {}
NVal::operator bool() const
{
return env_ && val_;
}
bool NVal::TypeIs(napi_valuetype expType) const
{
if (!*this)
return false;
napi_valuetype valueType;
napi_typeof(env_, val_, &valueType);
if (expType != valueType) {
return false;
}
return true;
}
tuple<bool, unique_ptr<char[]>, size_t> NVal::ToUTF8String() const
{
size_t strLen = 0;
napi_status status = napi_get_value_string_utf8(env_, val_, nullptr, -1, &strLen);
if (status != napi_ok) {
return { false, nullptr, 0 };
}
size_t bufLen = strLen + 1;
unique_ptr<char[]> str = make_unique<char[]>(bufLen);
status = napi_get_value_string_utf8(env_, val_, str.get(), bufLen, &strLen);
return make_tuple(status == napi_ok, move(str), strLen);
}
tuple<bool, unique_ptr<char[]>, size_t> NVal::ToUTF16String() const
{
#ifdef FILE_SUBSYSTEM_DEV_ON_PC
size_t strLen = 0;
napi_status status = napi_get_value_string_utf16(env_, val_, nullptr, -1, &strLen);
if (status != napi_ok) {
return { false, nullptr, 0 };
}
auto str = make_unique<char16_t[]>(++strLen);
status = napi_get_value_string_utf16(env_, val_, str.get(), strLen, nullptr);
if (status != napi_ok) {
return { false, nullptr, 0 };
}
strLen = reinterpret_cast<char *>(str.get() + strLen) - reinterpret_cast<char *>(str.get());
auto strRet = unique_ptr<char[]>(reinterpret_cast<char *>(str.release()));
return { true, move(strRet), strLen };
#else
// Note that quickjs doesn't support utf16
return ToUTF8String();
#endif
}
tuple<bool, void *> NVal::ToPointer() const
{
void *res = nullptr;
napi_status status = napi_get_value_external(env_, val_, &res);
return make_tuple(status == napi_ok, res);
}
tuple<bool, bool> NVal::ToBool() const
{
bool flag = false;
napi_status status = napi_get_value_bool(env_, val_, &flag);
return make_tuple(status == napi_ok, flag);
}
tuple<bool, int32_t> NVal::ToInt32() const
{
int32_t res = 0;
napi_status status = napi_get_value_int32(env_, val_, &res);
return make_tuple(status == napi_ok, res);
}
tuple<bool, int64_t> NVal::ToInt64() const
{
int64_t res = 0;
napi_status status = napi_get_value_int64(env_, val_, &res);
return make_tuple(status == napi_ok, res);
}
tuple<bool, void *, size_t> NVal::ToArraybuffer() const
{
void *buf = nullptr;
size_t bufLen = 0;
bool status = napi_get_arraybuffer_info(env_, val_, &buf, &bufLen);
return make_tuple(status == napi_ok, buf, bufLen);
}
tuple<bool, void *, size_t> NVal::ToTypedArray() const
{
napi_typedarray_type type;
napi_value in_array_buffer = nullptr;
size_t byte_offset;
size_t length;
void *data = nullptr;
napi_status status =
napi_get_typedarray_info(env_, val_, &type, &length, (void **)&data, &in_array_buffer, &byte_offset);
return make_tuple(status == napi_ok, data, length);
}
bool NVal::HasProp(string propName) const
{
bool res = false;
if (!env_ || !val_ || !TypeIs(napi_object))
return false;
napi_status status = napi_has_named_property(env_, val_, propName.c_str(), &res);
return (status == napi_ok) && res;
}
NVal NVal::GetProp(string propName) const
{
if (!HasProp(propName)) {
return { env_, nullptr };
}
napi_value prop = nullptr;
napi_status status = napi_get_named_property(env_, val_, propName.c_str(), &prop);
if (status != napi_ok) {
return { env_, nullptr };
}
return NVal(env_, prop);
}
bool NVal::AddProp(vector<napi_property_descriptor> &&propVec) const
{
if (!TypeIs(napi_valuetype::napi_object)) {
HILOGE("INNER BUG. Prop should only be added to objects");
return false;
}
napi_status status = napi_define_properties(env_, val_, propVec.size(), propVec.data());
if (status != napi_ok) {
HILOGE("INNER BUG. Cannot define properties because of %{public}d", status);
return false;
}
return true;
}
bool NVal::AddProp(string propName, napi_value val) const
{
if (!TypeIs(napi_valuetype::napi_object) || HasProp(propName)) {
HILOGE("INNER BUG. Prop should only be added to objects");
return false;
}
napi_status status = napi_set_named_property(env_, val_, propName.c_str(), val);
if (status != napi_ok) {
HILOGE("INNER BUG. Cannot set named property because of %{public}d", status);
return false;
}
return true;
}
NVal NVal::CreateUndefined(napi_env env)
{
napi_value res = nullptr;
napi_get_undefined(env, &res);
return { env, res };
}
NVal NVal::CreateInt64(napi_env env, int64_t val)
{
napi_value res = nullptr;
napi_create_int64(env, val, &res);
return { env, res };
}
NVal NVal::CreateObject(napi_env env)
{
napi_value res = nullptr;
napi_create_object(env, &res);
return { env, res };
}
NVal NVal::CreateBool(napi_env env, bool val)
{
napi_value res = nullptr;
napi_get_boolean(env, val, &res);
return { env, res };
}
NVal NVal::CreateUTF8String(napi_env env, std::string str)
{
napi_value res = nullptr;
napi_create_string_utf8(env, str.c_str(), str.length(), &res);
return { env, res };
}
NVal NVal::CreateUint8Array(napi_env env, void *buf, size_t bufLen)
{
napi_value output_buffer = nullptr;
napi_create_external_arraybuffer(
env,
buf,
bufLen,
[](napi_env env, void *finalize_data, void *finalize_hint) { free(finalize_data); },
NULL,
&output_buffer);
napi_value output_array = nullptr;
napi_create_typedarray(env, napi_uint8_array, bufLen, output_buffer, 0, &output_array);
return { env, output_array };
}
napi_property_descriptor NVal::DeclareNapiProperty(const char *name, napi_value val)
{
return { (name), nullptr, nullptr, nullptr, nullptr, val, napi_default, nullptr };
}
napi_property_descriptor NVal::DeclareNapiStaticProperty(const char *name, napi_value val)
{
return { (name), nullptr, nullptr, nullptr, nullptr, val, napi_static, nullptr };
}
napi_property_descriptor NVal::DeclareNapiFunction(const char *name, napi_callback func)
{
return { (name), nullptr, (func), nullptr, nullptr, nullptr, napi_default, nullptr };
}
napi_property_descriptor NVal::DeclareNapiStaticFunction(const char *name, napi_callback func)
{
return { (name), nullptr, (func), nullptr, nullptr, nullptr, napi_static, nullptr };
}
napi_property_descriptor NVal::DeclareNapiGetter(const char *name, napi_callback getter)
{
return { (name), nullptr, nullptr, (getter), nullptr, nullptr, napi_default, nullptr };
}
napi_property_descriptor NVal::DeclareNapiSetter(const char *name, napi_callback setter)
{
return { (name), nullptr, nullptr, nullptr, (setter), nullptr, napi_default, nullptr };
}
napi_property_descriptor NVal::DeclareNapiGetterSetter(const char *name, napi_callback getter, napi_callback setter)
{
return { (name), nullptr, nullptr, (getter), (setter), nullptr, napi_default, nullptr };
}
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <memory>
#include <tuple>
#include <vector>
#include "uni_header.h"
namespace OHOS {
namespace DistributedFS {
class NVal final {
public:
NVal() = default;
NVal(napi_env nEnv, napi_value nVal);
NVal &operator = (const NVal &) = default;
virtual ~NVal() = default;
// NOTE! env_ and val_ is LIKELY to be null
napi_env env_ = nullptr;
napi_value val_ = nullptr;
explicit operator bool() const;
bool TypeIs(napi_valuetype expType) const;
/* SHOULD ONLY BE USED FOR EXPECTED TYPE */
std::tuple<bool, std::unique_ptr<char[]>, size_t> ToUTF8String() const;
std::tuple<bool, std::unique_ptr<char[]>, size_t> ToUTF16String() const;
std::tuple<bool, void *> ToPointer() const;
std::tuple<bool, bool> ToBool() const;
std::tuple<bool, int32_t> ToInt32() const;
std::tuple<bool, int64_t> ToInt64() const;
std::tuple<bool, void *, size_t> ToArraybuffer() const;
std::tuple<bool, void *, size_t> ToTypedArray() const;
/* Static helpers to create js objects */
static NVal CreateUndefined(napi_env env);
static NVal CreateInt64(napi_env env, int64_t val);
static NVal CreateObject(napi_env env);
static NVal CreateBool(napi_env env, bool val);
static NVal CreateUTF8String(napi_env env, std::string str);
static NVal CreateUint8Array(napi_env env, void *buf, size_t bufLen);
/* SHOULD ONLY BE USED FOR OBJECT */
bool HasProp(std::string propName) const;
NVal GetProp(std::string propName) const;
bool AddProp(std::vector<napi_property_descriptor> &&propVec) const;
bool AddProp(std::string propName, napi_value nVal) const;
/* Static helpers to create prop of js objects */
static napi_property_descriptor DeclareNapiProperty(const char *name, napi_value val);
static napi_property_descriptor DeclareNapiStaticProperty(const char *name, napi_value val);
static napi_property_descriptor DeclareNapiFunction(const char *name, napi_callback func);
static napi_property_descriptor DeclareNapiStaticFunction(const char *name, napi_callback func);
static napi_property_descriptor DeclareNapiGetter(const char *name, napi_callback getter);
static napi_property_descriptor DeclareNapiSetter(const char *name, napi_callback setter);
static inline napi_property_descriptor DeclareNapiGetterSetter(const char *name,
napi_callback getter,
napi_callback setter);
};
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,23 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#ifdef FILE_SUBSYSTEM_DEV_ON_PC
#include <node_api.h>
#else
#include "napi/native_api.h"
#include "napi/native_node_api.h"
#endif

View File

@ -0,0 +1,118 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "uni_error.h"
#include <cstring>
#include <string>
#include "log.h"
#include "napi/n_val.h"
namespace OHOS {
namespace DistributedFS {
using namespace std;
UniError::UniError() {}
UniError::UniError(ELegacy eLegacy) : errno_(eLegacy), codingSystem_(ERR_CODE_SYSTEM_LEGACY) {}
UniError::UniError(int ePosix) : errno_(ePosix), codingSystem_(ERR_CODE_SYSTEM_POSIX) {}
UniError::operator bool() const
{
return errno_ != ERRNO_NOERR;
}
int UniError::GetErrno(ErrCodeSystem cs)
{
if (errno_ == ERRNO_NOERR) {
return ERRNO_NOERR;
}
if (cs == codingSystem_) {
return errno_;
}
if (cs == ERR_CODE_SYSTEM_POSIX) {
// Note that we should support more codes here
return EINVAL;
}
// Note that this shall be done properly
return ELEGACY_INVAL;
}
void UniError::SetErrno(ELegacy eLegacy)
{
errno_ = eLegacy;
codingSystem_ = ERR_CODE_SYSTEM_LEGACY;
}
void UniError::SetErrno(int ePosix)
{
errno_ = ePosix;
codingSystem_ = ERR_CODE_SYSTEM_POSIX;
}
std::string UniError::GetDefaultErrstr()
{
if (codingSystem_ != ERR_CODE_SYSTEM_POSIX && codingSystem_ != ERR_CODE_SYSTEM_LEGACY) {
return "BUG: Curious coding system";
}
return strerror(GetErrno(ERR_CODE_SYSTEM_POSIX));
}
napi_value UniError::GetNapiErr(napi_env env)
{
return GetNapiErr(env, GetDefaultErrstr());
}
napi_value UniError::GetNapiErr(napi_env env, string errMsg)
{
napi_value code = NVal::CreateUTF8String(env, to_string(GetErrno(codingSystem_))).val_;
napi_value msg = NVal::CreateUTF8String(env, errMsg).val_;
napi_value res = nullptr;
napi_status createRes = napi_create_error(env, code, msg, &res);
if (createRes) {
HILOGE("Failed to create an exception, msg = %{public}s", errMsg.c_str());
}
return res;
}
void UniError::ThrowErr(napi_env env)
{
string msg = GetDefaultErrstr();
napi_value tmp = nullptr;
napi_get_and_clear_last_exception(env, &tmp);
// Note that ace engine cannot thow errors created by napi_create_error so far
napi_status throwStatus = napi_throw_error(env, nullptr, msg.c_str());
if (throwStatus != napi_ok) {
HILOGE("Failed to throw an exception, %{public}d, code = %{public}s", throwStatus, msg.c_str());
}
}
void UniError::ThrowErr(napi_env env, string errMsg)
{
napi_value tmp = nullptr;
napi_get_and_clear_last_exception(env, &tmp);
// Note that ace engine cannot thow errors created by napi_create_error so far
napi_status throwStatus = napi_throw_error(env, nullptr, errMsg.c_str());
if (throwStatus != napi_ok) {
HILOGE("Failed to throw an exception, %{public}d, code = %{public}s", throwStatus, errMsg.c_str());
}
}
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <cerrno>
#include <string>
#include "napi/uni_header.h"
namespace OHOS {
namespace DistributedFS {
constexpr int ERRNO_NOERR = 0;
enum ELegacy {
ELEGACY_INVAL = 202,
ELEGACY_IO = 300,
ELEGACY_NOENT = 301,
};
enum ErrCodeSystem {
ERR_CODE_SYSTEM_LEGACY,
ERR_CODE_SYSTEM_POSIX,
};
class UniError {
public:
UniError();
explicit UniError(ELegacy eLegacy);
explicit UniError(int ePosix);
~UniError() = default;
UniError &operator = (const UniError &) = default;
explicit operator bool() const;
void SetErrno(ELegacy eLegacy);
void SetErrno(int ePosix);
int GetErrno(ErrCodeSystem cs);
std::string GetDefaultErrstr();
napi_value GetNapiErr(napi_env env);
napi_value GetNapiErr(napi_env env, std::string errMsg);
void ThrowErr(napi_env env);
void ThrowErr(napi_env env, std::string errMsg);
private:
int errno_ = ERRNO_NOERR;
ErrCodeSystem codingSystem_ = ERR_CODE_SYSTEM_POSIX;
};
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <cstdio>
#include <dirent.h>
#include <functional>
#include <memory>
#include <mutex>
namespace OHOS {
namespace DistributedFS {
namespace ModuleFileIO {
struct DirEntity {
std::mutex lock_;
std::unique_ptr<DIR, std::function<void(DIR *)> > dir_ = { nullptr, closedir };
};
} // namespace ModuleFileIO
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,208 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "dir_n_exporter.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <dirent.h>
#include <iostream>
#include <memory>
#include <mutex>
#include <sstream>
#include <sys/stat.h>
#include <unistd.h>
#include "securec.h"
#include "../../common/log.h"
#include "../../common/napi/n_class.h"
#include "../../common/napi/n_func_arg.h"
#include "../../common/uni_error.h"
#include "../class_dirent/dirent_entity.h"
#include "../class_dirent/dirent_n_exporter.h"
#include "../common_func.h"
#include "dir_entity.h"
namespace OHOS {
namespace DistributedFS {
namespace ModuleFileIO {
using namespace std;
static DirEntity *GetDirEntity(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
auto dirEntity = NClass::GetEntityOf<DirEntity>(env, funcArg.GetThisVar());
if (!dirEntity) {
UniError(EIO).ThrowErr(env, "Cannot get entity of Dir");
return nullptr;
}
return dirEntity;
}
napi_value DirNExporter::OpenDirSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ONE)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
bool succ = false;
unique_ptr<char[]> path;
tie(succ, path, ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid path");
return nullptr;
}
std::unique_ptr<DIR, std::function<void(DIR *)>> dir = { opendir(path.get()), closedir };
if (!dir) {
UniError(errno).ThrowErr(env);
return nullptr;
}
napi_value objDir = NClass::InstantiateClass(env, DirNExporter::className_, {});
if (!objDir) {
UniError(EINVAL).ThrowErr(env, "Cannot instantiate class DirSync");
return nullptr;
}
auto dirEntity = NClass::GetEntityOf<DirEntity>(env, objDir);
if (!dirEntity) {
UniError(EINVAL).ThrowErr(env, "Cannot get the entity of objDir");
return nullptr;
}
dirEntity->dir_.swap(dir);
return objDir;
}
napi_value DirNExporter::CloseSync(napi_env env, napi_callback_info info)
{
DirEntity *dirEntity = GetDirEntity(env, info);
if (!dirEntity || !dirEntity->dir_) {
UniError(EBADF).ThrowErr(env, "Dir has been closed yet");
return nullptr;
}
dirEntity->dir_.reset();
return nullptr;
}
napi_value DirNExporter::ReadSync(napi_env env, napi_callback_info info)
{
DirEntity *dirEntity = GetDirEntity(env, info);
if (!dirEntity || !dirEntity->dir_) {
UniError(EBADF).ThrowErr(env, "Dir has been closed yet");
return nullptr;
}
struct dirent tmpDirent;
{
lock_guard(dirEntity->lock_);
errno = 0;
dirent *res = nullptr;
do {
res = readdir(dirEntity->dir_.get());
if (res == nullptr && errno) {
UniError(errno).ThrowErr(env);
return nullptr;
} else if (res == nullptr) {
return NVal::CreateUndefined(env).val_;
} else if (string(res->d_name) == "." || string(res->d_name) == "..") {
continue;
} else {
tmpDirent = *res;
break;
}
} while (true);
}
napi_value objDirent = NClass::InstantiateClass(env, DirentNExporter::className_, {});
if (!objDirent) {
return nullptr;
}
auto direntEntity = NClass::GetEntityOf<DirentEntity>(env, objDirent);
if (!direntEntity) {
return nullptr;
}
direntEntity->dirent_ = tmpDirent;
return objDirent;
}
napi_value DirNExporter::Constructor(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
auto dirEntity = make_unique<DirEntity>();
if (!NClass::SetEntityFor<DirEntity>(env, funcArg.GetThisVar(), move(dirEntity))) {
stringstream ss;
ss << "INNER BUG. Failed to wrap entity for obj dir";
UniError(EIO).ThrowErr(env, ss.str());
return nullptr;
}
return funcArg.GetThisVar();
}
bool DirNExporter::Export()
{
vector<napi_property_descriptor> props = {
NVal::DeclareNapiStaticFunction("opendirSync", OpenDirSync),
NVal::DeclareNapiFunction("readSync", ReadSync),
NVal::DeclareNapiFunction("closeSync", CloseSync),
};
string className = GetClassName();
bool succ = false;
napi_value clas = nullptr;
tie(succ, clas) = NClass::DefineClass(exports_.env_, className, DirNExporter::Constructor, std::move(props));
if (!succ) {
UniError(EIO).ThrowErr(exports_.env_, "INNER BUG. Failed to define class Dirent");
return false;
}
succ = NClass::SaveClass(exports_.env_, className, clas);
if (!succ) {
UniError(EIO).ThrowErr(exports_.env_, "INNER BUG. Failed to save class Dirent");
return false;
}
return exports_.AddProp(className, clas);
}
string DirNExporter::GetClassName()
{
return DirNExporter::className_;
}
DirNExporter::DirNExporter(napi_env env, napi_value exports) : NExporter(env, exports) {}
DirNExporter::~DirNExporter() {}
} // namespace ModuleFileIO
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <memory>
#include <string>
#include "../../common/napi/n_exporter.h"
namespace OHOS {
namespace DistributedFS {
namespace ModuleFileIO {
class DirNExporter final : public NExporter {
public:
inline static const std::string className_ = "Dir";
bool Export() override;
std::string GetClassName() override;
static napi_value Constructor(napi_env env, napi_callback_info info);
static napi_value OpenDirSync(napi_env env, napi_callback_info info);
static napi_value CloseSync(napi_env env, napi_callback_info info);
static napi_value ReadSync(napi_env env, napi_callback_info info);
DirNExporter(napi_env env, napi_value exports);
~DirNExporter() override;
};
} // namespace ModuleFileIO
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <dirent.h>
namespace OHOS {
namespace DistributedFS {
namespace ModuleFileIO {
struct DirentEntity {
struct dirent dirent_;
};
} // namespace ModuleFileIO
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,169 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "dirent_n_exporter.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <memory>
#include <sstream>
#include "securec.h"
#include "../../common/log.h"
#include "../../common/napi/n_class.h"
#include "../../common/napi/n_func_arg.h"
#include "../../common/uni_error.h"
#include "../common_func.h"
#include "dirent_entity.h"
namespace OHOS {
namespace DistributedFS {
namespace ModuleFileIO {
using namespace std;
static DirentEntity *GetDirentEntity(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
auto direntEntity = NClass::GetEntityOf<DirentEntity>(env, funcArg.GetThisVar());
if (!direntEntity) {
UniError(EIO).ThrowErr(env, "Cannot get entity of Dirent");
return nullptr;
}
return direntEntity;
}
static napi_value CheckDirentDType(napi_env env, napi_callback_info info, __mode_t dType)
{
DirentEntity *direntEntity = GetDirentEntity(env, info);
if (!direntEntity) {
return nullptr;
}
return NVal::CreateBool(env, direntEntity->dirent_.d_type == dType).val_;
}
napi_value DirentNExporter::isBlockDevice(napi_env env, napi_callback_info info)
{
return CheckDirentDType(env, info, DT_BLK);
}
napi_value DirentNExporter::isCharacterDevice(napi_env env, napi_callback_info info)
{
return CheckDirentDType(env, info, DT_CHR);
}
napi_value DirentNExporter::isDirectory(napi_env env, napi_callback_info info)
{
return CheckDirentDType(env, info, DT_DIR);
}
napi_value DirentNExporter::isFIFO(napi_env env, napi_callback_info info)
{
return CheckDirentDType(env, info, DT_FIFO);
}
napi_value DirentNExporter::isFile(napi_env env, napi_callback_info info)
{
return CheckDirentDType(env, info, DT_REG);
}
napi_value DirentNExporter::isSocket(napi_env env, napi_callback_info info)
{
return CheckDirentDType(env, info, DT_SOCK);
}
napi_value DirentNExporter::isSymbolicLink(napi_env env, napi_callback_info info)
{
return CheckDirentDType(env, info, DT_LNK);
}
napi_value DirentNExporter::GetName(napi_env env, napi_callback_info info)
{
DirentEntity *direntEntity = GetDirentEntity(env, info);
if (!direntEntity) {
return nullptr;
}
return NVal::CreateUTF8String(env, direntEntity->dirent_.d_name).val_;
}
napi_value DirentNExporter::Constructor(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
auto direntEntity = make_unique<DirentEntity>();
if (!NClass::SetEntityFor<DirentEntity>(env, funcArg.GetThisVar(), move(direntEntity))) {
stringstream ss;
ss << "INNER BUG. Failed to wrap entity for obj dirent";
UniError(EIO).ThrowErr(env, ss.str());
return nullptr;
}
return funcArg.GetThisVar();
}
bool DirentNExporter::Export()
{
vector<napi_property_descriptor> props = {
NVal::DeclareNapiFunction("isBlockDevice", isBlockDevice),
NVal::DeclareNapiFunction("isCharacterDevice", isCharacterDevice),
NVal::DeclareNapiFunction("isDirectory", isDirectory),
NVal::DeclareNapiFunction("isFIFO", isFIFO),
NVal::DeclareNapiFunction("isFile", isFile),
NVal::DeclareNapiFunction("isSocket", isSocket),
NVal::DeclareNapiFunction("isSymbolicLink", isSymbolicLink),
NVal::DeclareNapiGetter("name", GetName),
};
string className = GetClassName();
bool succ = false;
napi_value clas = nullptr;
tie(succ, clas) = NClass::DefineClass(exports_.env_, className, DirentNExporter::Constructor, std::move(props));
if (!succ) {
UniError(EIO).ThrowErr(exports_.env_, "INNER BUG. Failed to define class Dirent");
return false;
}
succ = NClass::SaveClass(exports_.env_, className, clas);
if (!succ) {
UniError(EIO).ThrowErr(exports_.env_, "INNER BUG. Failed to save class Dirent");
return false;
}
return exports_.AddProp(className, clas);
}
string DirentNExporter::GetClassName()
{
return DirentNExporter::className_;
}
DirentNExporter::DirentNExporter(napi_env env, napi_value exports) : NExporter(env, exports) {}
DirentNExporter::~DirentNExporter() {}
} // namespace ModuleFileIO
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "../../common/napi/n_exporter.h"
namespace OHOS {
namespace DistributedFS {
namespace ModuleFileIO {
class DirentNExporter final : public NExporter {
public:
inline static const std::string className_ = "Dirent";
bool Export() override;
std::string GetClassName() override;
static napi_value Constructor(napi_env env, napi_callback_info cbinfo);
static napi_value isBlockDevice(napi_env env, napi_callback_info cbinfo);
static napi_value isCharacterDevice(napi_env env, napi_callback_info cbinfo);
static napi_value isDirectory(napi_env env, napi_callback_info cbinfo);
static napi_value isFIFO(napi_env env, napi_callback_info cbinfo);
static napi_value isFile(napi_env env, napi_callback_info cbinfo);
static napi_value isSocket(napi_env env, napi_callback_info cbinfo);
static napi_value isSymbolicLink(napi_env env, napi_callback_info cbinfo);
static napi_value GetName(napi_env env, napi_callback_info cbinfo);
DirentNExporter(napi_env env, napi_value exports);
~DirentNExporter() override;
};
} // namespace ModuleFileIO
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <cstdio>
#include <memory>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "../../common/napi/uni_header.h"
namespace OHOS {
namespace DistributedFS {
namespace ModuleFileIO {
struct StatEntity {
struct stat stat_;
};
} // namespace ModuleFileIO
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,407 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "stat_n_exporter.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <memory>
#include <sstream>
#include "securec.h"
#include "../../common/log.h"
#include "../../common/napi/n_class.h"
#include "../../common/napi/n_func_arg.h"
#include "../../common/uni_error.h"
#include "stat_entity.h"
namespace OHOS {
namespace DistributedFS {
namespace ModuleFileIO {
using namespace std;
napi_value StatNExporter::StatSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ONE)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
bool succ = false;
unique_ptr<char[]> pathPtr;
tie(succ, pathPtr, ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "The first argument requires type string");
return nullptr;
}
struct stat buf;
int ret = stat(pathPtr.get(), &buf);
if (ret == -1) {
UniError(errno).ThrowErr(env);
return nullptr;
}
napi_value objStat = NClass::InstantiateClass(env, StatNExporter::className_, {});
if (!objStat) {
return nullptr;
}
auto statEntity = NClass::GetEntityOf<StatEntity>(env, objStat);
if (!statEntity) {
return nullptr;
}
statEntity->stat_ = buf;
return objStat;
}
static napi_value CheckStatMode(napi_env env, napi_callback_info info, mode_t mode)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
if (!statEntity) {
return nullptr;
}
bool check = (statEntity->stat_.st_mode & S_IFMT) == mode;
return NVal::CreateBool(env, check).val_;
}
napi_value StatNExporter::IsBlockDevice(napi_env env, napi_callback_info info)
{
return CheckStatMode(env, info, S_IFBLK);
}
napi_value StatNExporter::IsCharacterDevice(napi_env env, napi_callback_info info)
{
return CheckStatMode(env, info, S_IFCHR);
}
napi_value StatNExporter::IsDirectory(napi_env env, napi_callback_info info)
{
return CheckStatMode(env, info, S_IFDIR);
}
napi_value StatNExporter::IsFIFO(napi_env env, napi_callback_info info)
{
return CheckStatMode(env, info, S_IFIFO);
}
napi_value StatNExporter::IsFile(napi_env env, napi_callback_info info)
{
return CheckStatMode(env, info, S_IFREG);
}
napi_value StatNExporter::IsSocket(napi_env env, napi_callback_info info)
{
return CheckStatMode(env, info, S_IFSOCK);
}
napi_value StatNExporter::IsSymbolicLink(napi_env env, napi_callback_info info)
{
return CheckStatMode(env, info, S_IFLNK);
}
napi_value StatNExporter::GetDev(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
if (!statEntity) {
return nullptr;
}
return NVal::CreateInt64(env, statEntity->stat_.st_dev).val_;
}
napi_value StatNExporter::GetIno(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
if (!statEntity) {
return nullptr;
}
return NVal::CreateInt64(env, statEntity->stat_.st_ino).val_;
}
napi_value StatNExporter::GetMode(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
if (!statEntity) {
return nullptr;
}
return NVal::CreateInt64(env, statEntity->stat_.st_mode).val_;
}
napi_value StatNExporter::GetNlink(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
if (!statEntity) {
return nullptr;
}
return NVal::CreateInt64(env, statEntity->stat_.st_nlink).val_;
}
napi_value StatNExporter::GetUid(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
if (!statEntity) {
return nullptr;
}
return NVal::CreateInt64(env, statEntity->stat_.st_uid).val_;
}
napi_value StatNExporter::GetGid(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
if (!statEntity) {
return nullptr;
}
return NVal::CreateInt64(env, statEntity->stat_.st_gid).val_;
}
napi_value StatNExporter::GetRdev(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
if (!statEntity) {
return nullptr;
}
return NVal::CreateInt64(env, statEntity->stat_.st_rdev).val_;
}
napi_value StatNExporter::GetSize(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
if (!statEntity) {
return nullptr;
}
return NVal::CreateInt64(env, statEntity->stat_.st_size).val_;
}
napi_value StatNExporter::GetBlksize(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
if (!statEntity) {
return nullptr;
}
return NVal::CreateInt64(env, statEntity->stat_.st_blksize).val_;
}
napi_value StatNExporter::GetBlocks(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
if (!statEntity) {
return nullptr;
}
return NVal::CreateInt64(env, statEntity->stat_.st_blocks).val_;
}
napi_value StatNExporter::GetAtime(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
if (!statEntity) {
return nullptr;
}
return NVal::CreateInt64(env, statEntity->stat_.st_atim.tv_sec).val_;
}
napi_value StatNExporter::GetMtime(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
if (!statEntity) {
return nullptr;
}
return NVal::CreateInt64(env, statEntity->stat_.st_mtim.tv_sec).val_;
}
napi_value StatNExporter::GetCtime(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
if (!statEntity) {
return nullptr;
}
return NVal::CreateInt64(env, statEntity->stat_.st_ctim.tv_sec).val_;
}
napi_value StatNExporter::Constructor(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
unique_ptr<StatEntity> statEntity = make_unique<StatEntity>();
if (!NClass::SetEntityFor<StatEntity>(env, funcArg.GetThisVar(), move(statEntity))) {
stringstream ss;
ss << "INNER BUG. Failed to wrap entity for obj stat";
UniError(EIO).ThrowErr(env, ss.str());
return nullptr;
}
return funcArg.GetThisVar();
}
bool StatNExporter::Export()
{
vector<napi_property_descriptor> props = {
NVal::DeclareNapiStaticFunction("statSync", StatSync),
NVal::DeclareNapiFunction("isBlockDevice", IsBlockDevice),
NVal::DeclareNapiFunction("isCharacterDevice", IsCharacterDevice),
NVal::DeclareNapiFunction("isDirectory", IsDirectory),
NVal::DeclareNapiFunction("isFIFO", IsFIFO),
NVal::DeclareNapiFunction("isFile", IsFile),
NVal::DeclareNapiFunction("isSocket", IsSocket),
NVal::DeclareNapiFunction("isSymbolicLink", IsSymbolicLink),
NVal::DeclareNapiGetter("dev", GetDev),
NVal::DeclareNapiGetter("ino", GetIno),
NVal::DeclareNapiGetter("mode", GetMode),
NVal::DeclareNapiGetter("nlink", GetNlink),
NVal::DeclareNapiGetter("uid", GetUid),
NVal::DeclareNapiGetter("gid", GetGid),
NVal::DeclareNapiGetter("rdev", GetRdev),
NVal::DeclareNapiGetter("size", GetSize),
NVal::DeclareNapiGetter("blksize", GetBlksize),
NVal::DeclareNapiGetter("blocks", GetBlocks),
NVal::DeclareNapiGetter("atime", GetAtime),
NVal::DeclareNapiGetter("mtime", GetMtime),
NVal::DeclareNapiGetter("ctime", GetCtime),
};
string className = GetClassName();
bool succ = false;
napi_value clas = nullptr;
tie(succ, clas) = NClass::DefineClass(exports_.env_, className, StatNExporter::Constructor, std::move(props));
if (!succ) {
UniError(EIO).ThrowErr(exports_.env_, "INNER BUG. Failed to define class");
return false;
}
succ = NClass::SaveClass(exports_.env_, className, clas);
if (!succ) {
UniError(EIO).ThrowErr(exports_.env_, "INNER BUG. Failed to save class");
return false;
}
return exports_.AddProp(className, clas);
}
string StatNExporter::GetClassName()
{
return StatNExporter::className_;
}
StatNExporter::StatNExporter(napi_env env, napi_value exports) : NExporter(env, exports) {}
StatNExporter::~StatNExporter() {}
} // namespace ModuleFileIO
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <memory>
#include <string>
#include "../../common/napi/n_exporter.h"
namespace OHOS {
namespace DistributedFS {
namespace ModuleFileIO {
class StatNExporter final : public NExporter {
public:
inline static const std::string className_ = "Stat";
bool Export() override;
std::string GetClassName() override;
static napi_value Constructor(napi_env env, napi_callback_info cbinfo);
static napi_value StatSync(napi_env env, napi_callback_info info);
static napi_value IsBlockDevice(napi_env env, napi_callback_info cbinfo);
static napi_value IsCharacterDevice(napi_env env, napi_callback_info cbinfo);
static napi_value IsDirectory(napi_env env, napi_callback_info cbinfo);
static napi_value IsFIFO(napi_env env, napi_callback_info cbinfo);
static napi_value IsFile(napi_env env, napi_callback_info cbinfo);
static napi_value IsSocket(napi_env env, napi_callback_info cbinfo);
static napi_value IsSymbolicLink(napi_env env, napi_callback_info cbinfo);
static napi_value GetDev(napi_env env, napi_callback_info cbinfo);
static napi_value GetIno(napi_env env, napi_callback_info cbinfo);
static napi_value GetMode(napi_env env, napi_callback_info cbinfo);
static napi_value GetNlink(napi_env env, napi_callback_info cbinfo);
static napi_value GetUid(napi_env env, napi_callback_info cbinfo);
static napi_value GetGid(napi_env env, napi_callback_info cbinfo);
static napi_value GetRdev(napi_env env, napi_callback_info cbinfo);
static napi_value GetSize(napi_env env, napi_callback_info cbinfo);
static napi_value GetBlksize(napi_env env, napi_callback_info cbinfo);
static napi_value GetBlocks(napi_env env, napi_callback_info cbinfo);
static napi_value GetAtime(napi_env env, napi_callback_info cbinfo);
static napi_value GetMtime(napi_env env, napi_callback_info cbinfo);
static napi_value GetCtime(napi_env env, napi_callback_info cbinfo);
StatNExporter(napi_env env, napi_value exports);
~StatNExporter() override;
};
} // namespace ModuleFileIO
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <cstdio>
#include <memory>
namespace OHOS {
namespace DistributedFS {
namespace ModuleFileIO {
struct StreamEntity {
std::unique_ptr<FILE, decltype(&fclose)> fp = { nullptr, fclose };
};
} // namespace ModuleFileIO
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,316 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "stream_n_exporter.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <memory>
#include <sstream>
#include <string>
#include "securec.h"
#include "../../common/log.h"
#include "../../common/napi/n_class.h"
#include "../../common/napi/n_func_arg.h"
#include "../../common/uni_error.h"
#include "../common_func.h"
#include "stream_entity.h"
namespace OHOS {
namespace DistributedFS {
namespace ModuleFileIO {
using namespace std;
static NVal InstantiateStream(napi_env env, unique_ptr<FILE, decltype(&fclose)> fp)
{
napi_value objStream = NClass::InstantiateClass(env, StreamNExporter::className_, {});
if (!objStream) {
UniError(EIO).ThrowErr(env, "INNER BUG. Cannot instantiate stream");
return NVal();
}
auto streamEntity = NClass::GetEntityOf<StreamEntity>(env, objStream);
if (!streamEntity) {
UniError(EIO).ThrowErr(env, "Cannot instantiate stream because of void entity");
return NVal();
}
streamEntity->fp.swap(fp);
return { env, objStream };
}
static tuple<bool, string, string> GetCreateStreamArgs(napi_env env, const NFuncArg &funcArg)
{
bool succ = false;
unique_ptr<char[]> path;
tie(succ, path, ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid path");
return { false, "", "" };
}
unique_ptr<char[]> mode;
tie(succ, mode, ignore) = NVal(env, funcArg[NARG_POS::SECOND]).ToUTF8String();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid mode");
return { false, "", "" };
}
return { true, path.get(), mode.get() };
}
napi_value StreamNExporter::CreateStreamSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::TWO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
bool succ = false;
string argPath;
string argMode;
tie(succ, argPath, argMode) = GetCreateStreamArgs(env, funcArg);
if (!succ) {
return nullptr;
}
unique_ptr<FILE, decltype(&fclose)> fp = { fopen(argPath.c_str(), argMode.c_str()), fclose };
if (!fp) {
UniError(errno).ThrowErr(env);
return nullptr;
}
return InstantiateStream(env, move(fp)).val_;
}
napi_value StreamNExporter::FdopenStreamSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::TWO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
bool succ = false;
int fd;
tie(succ, fd) = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Arg fd is required to be type integer");
return nullptr;
}
unique_ptr<char[]> mode;
tie(succ, mode, ignore) = NVal(env, funcArg[NARG_POS::SECOND]).ToUTF8String();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Arg mode is required to be type string");
return nullptr;
}
unique_ptr<FILE, decltype(&fclose)> fp = { fdopen(fd, mode.get()), fclose };
if (!fp) {
UniError(errno).ThrowErr(env);
return nullptr;
}
return InstantiateStream(env, move(fp)).val_;
}
napi_value StreamNExporter::ReadSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
/* To get entity */
bool succ = false;
FILE *filp = nullptr;
auto streamEntity = NClass::GetEntityOf<StreamEntity>(env, funcArg.GetThisVar());
if (!streamEntity || !streamEntity->fp) {
UniError(EBADF).ThrowErr(env, "Stream may have been closed");
return nullptr;
} else {
filp = streamEntity->fp.get();
}
void *buf = nullptr;
int64_t len;
bool hasPos = false;
int64_t pos;
tie(succ, buf, len, hasPos, pos) = CommonFunc::GetReadArg(env, funcArg[NARG_POS::FIRST], funcArg[NARG_POS::SECOND]);
if (!succ) {
return nullptr;
}
if (hasPos && (fseek(filp, pos, SEEK_SET) == -1)) {
UniError(errno).ThrowErr(env);
return nullptr;
}
size_t actLen = fread(buf, 1, len, filp);
if (actLen != static_cast<size_t>(len) && ferror(filp)) {
UniError(errno).ThrowErr(env);
}
return NVal::CreateInt64(env, actLen).val_;
}
napi_value StreamNExporter::CloseSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
auto streamEntity = NClass::GetEntityOf<StreamEntity>(env, funcArg.GetThisVar());
if (!streamEntity || !streamEntity->fp) {
UniError(EINVAL).ThrowErr(env, "Stream may have been closed yet");
return nullptr;
}
streamEntity->fp.reset();
return NVal::CreateUndefined(env).val_;
}
napi_value StreamNExporter::WriteSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
bool succ = false;
FILE *filp = nullptr;
auto streamEntity = NClass::GetEntityOf<StreamEntity>(env, funcArg.GetThisVar());
if (!streamEntity || !streamEntity->fp) {
UniError(EBADF).ThrowErr(env, "Stream may has been closed");
return nullptr;
} else {
filp = streamEntity->fp.get();
}
void *buf = nullptr;
size_t len;
size_t position;
unique_ptr<char[]> bufGuard;
bool hasPos = false;
tie(succ, bufGuard, buf, len, hasPos, position) =
CommonFunc::GetWriteArg(env, funcArg[NARG_POS::FIRST], funcArg[NARG_POS::SECOND]);
if (!succ) {
return nullptr;
}
if (hasPos && (fseek(filp, position, SEEK_SET) == -1)) {
UniError(errno).ThrowErr(env);
return nullptr;
}
ssize_t writeLen = fwrite(buf, 1, len, filp);
if (writeLen == -1) {
UniError(errno).ThrowErr(env);
return nullptr;
}
return NVal::CreateInt64(env, writeLen).val_;
}
napi_value StreamNExporter::FlushSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
auto streamEntity = NClass::GetEntityOf<StreamEntity>(env, funcArg.GetThisVar());
if (!streamEntity || !streamEntity->fp) {
UniError(EBADF).ThrowErr(env, "Stream may has been closed");
return nullptr;
}
int ret = fflush(streamEntity->fp.get());
if (ret == -1) {
UniError(errno).ThrowErr(env);
return nullptr;
}
return NVal::CreateUndefined(env).val_;
}
napi_value StreamNExporter::Constructor(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
unique_ptr<StreamEntity> streamEntity = make_unique<StreamEntity>();
if (!NClass::SetEntityFor<StreamEntity>(env, funcArg.GetThisVar(), move(streamEntity))) {
stringstream ss;
ss << "INNER BUG. Failed to wrap entity for obj stat";
UniError(EIO).ThrowErr(env, ss.str());
return nullptr;
}
return funcArg.GetThisVar();
}
bool StreamNExporter::Export()
{
vector<napi_property_descriptor> props = {
NVal::DeclareNapiStaticFunction("createStreamSync", CreateStreamSync),
NVal::DeclareNapiStaticFunction("fdopenStreamSync", FdopenStreamSync),
NVal::DeclareNapiFunction("writeSync", WriteSync),
NVal::DeclareNapiFunction("flushSync", FlushSync),
NVal::DeclareNapiFunction("readSync", ReadSync),
NVal::DeclareNapiFunction("closeSync", CloseSync),
};
string className = GetClassName();
bool succ = false;
napi_value cls = nullptr;
tie(succ, cls) = NClass::DefineClass(exports_.env_, className, StreamNExporter::Constructor, move(props));
if (!succ) {
UniError(EIO).ThrowErr(exports_.env_, "INNER BUG. Failed to define class");
return false;
}
succ = NClass::SaveClass(exports_.env_, className, cls);
if (!succ) {
UniError(EIO).ThrowErr(exports_.env_, "INNER BUG. Failed to save class");
return false;
}
return exports_.AddProp(className, cls);
}
string StreamNExporter::GetClassName()
{
return StreamNExporter::className_;
}
StreamNExporter::StreamNExporter(napi_env env, napi_value exports) : NExporter(env, exports) {}
StreamNExporter::~StreamNExporter() {}
} // namespace ModuleFileIO
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <limits>
#include <memory>
#include <string>
#include "../../common/napi/n_exporter.h"
namespace OHOS {
namespace DistributedFS {
namespace ModuleFileIO {
class StreamNExporter final : public NExporter {
public:
inline static const std::string className_ = "Stream";
bool Export() override;
std::string GetClassName() override;
static napi_value Constructor(napi_env env, napi_callback_info cbinfo);
static napi_value CreateStreamSync(napi_env env, napi_callback_info info);
static napi_value FdopenStreamSync(napi_env env, napi_callback_info info);
static napi_value WriteSync(napi_env env, napi_callback_info cbinfo);
static napi_value FlushSync(napi_env env, napi_callback_info cbinfo);
static napi_value ReadSync(napi_env env, napi_callback_info cbinfo);
static napi_value CloseSync(napi_env env, napi_callback_info cbinfo);
StreamNExporter(napi_env env, napi_value exports);
~StreamNExporter() override;
};
} // namespace ModuleFileIO
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,204 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "common_func.h"
#include <dirent.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "../common/log.h"
#include "../common/napi/n_class.h"
#include "../common/napi/n_func_arg.h"
#include "../common/uni_error.h"
namespace OHOS {
namespace DistributedFS {
namespace ModuleFileIO {
using namespace std;
static tuple<bool, void *> GetActualBuf(napi_env env, void *rawBuf, int64_t bufLen, NVal op)
{
bool succ = false;
void *realBuf = nullptr;
if (op.HasProp("offset")) {
int64_t opOffset;
tie(succ, opOffset) = op.GetProp("offset").ToInt64();
if (!succ || opOffset < 0) {
UniError(EINVAL).ThrowErr(env, "Invalid option.offset, positive integer is desired");
return { false, nullptr };
} else if (opOffset > bufLen) {
UniError(EINVAL).ThrowErr(env, "Invalid option.offset, buffer limit exceeded");
return { false, nullptr };
} else {
realBuf = static_cast<uint8_t *>(rawBuf) + opOffset;
}
} else {
realBuf = rawBuf;
}
return { true, realBuf };
}
static tuple<bool, size_t> GetActualLen(napi_env env, int64_t bufLen, int64_t bufOff, NVal op)
{
bool succ = false;
int64_t retLen;
if (op.HasProp("length")) {
int64_t opLength;
tie(succ, opLength) = op.GetProp("length").ToInt64();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid option.length, expect integer");
return { false, 0 };
}
if (opLength < 0) {
retLen = bufLen - bufOff;
} else if (opLength + bufOff > bufLen) {
UniError(EINVAL).ThrowErr(env, "Invalid option.length, buffer limit exceeded");
return { false, 0 };
} else {
retLen = opLength;
}
} else {
retLen = bufLen - bufOff;
}
return { true, retLen };
}
tuple<bool, void *, int64_t, bool, int64_t> CommonFunc::GetReadArg(napi_env env, napi_value readBuf, napi_value option)
{
bool succ = false;
void *retBuf = nullptr;
int64_t retLen;
bool posAssigned = false;
int64_t position;
NVal txt(env, readBuf);
void *buf = nullptr;
int64_t bufLen;
tie(succ, buf, bufLen) = txt.ToArraybuffer();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid read buffer, expect arraybuffer");
return { false, nullptr, 0, posAssigned, position };
}
NVal op = NVal(env, option);
tie(succ, retBuf) = GetActualBuf(env, buf, bufLen, op);
if (!succ) {
return { false, nullptr, 0, posAssigned, position };
}
int64_t bufOff = static_cast<uint8_t *>(retBuf) - static_cast<uint8_t *>(buf);
tie(succ, retLen) = GetActualLen(env, bufLen, bufOff, op);
if (!succ) {
return { false, nullptr, 0, posAssigned, position };
}
tie(succ, position) = op.GetProp("position").ToInt64();
if (succ && position >= 0) {
posAssigned = true;
}
return { true, retBuf, retLen, posAssigned, position };
}
static tuple<bool, unique_ptr<char[]>, int64_t> DecodeString(napi_env env, NVal jsStr, NVal encoding)
{
unique_ptr<char[]> buf;
if (!jsStr.TypeIs(napi_string)) {
return { false, nullptr, 0 };
}
bool succ = false;
if (!encoding) {
return jsStr.ToUTF8String();
}
unique_ptr<char[]> encodingBuf;
tie(succ, encodingBuf, ignore) = encoding.ToUTF8String();
if (!succ) {
return { false, nullptr, 0 };
}
string encodingStr(encodingBuf.release());
if (encodingStr == "utf-8") {
return jsStr.ToUTF8String();
} else if (encodingStr == "utf-16") {
return jsStr.ToUTF16String();
} else {
return { false, nullptr, 0 };
}
}
// Is everthing ok? Do we need to free memory? What's the three args required by fwrite? Where to start writing?
tuple<bool, unique_ptr<char[]>, void *, int64_t, bool, int64_t> CommonFunc::GetWriteArg(napi_env env,
napi_value argWBuf,
napi_value argOption)
{
void *retBuf = nullptr;
int64_t retLen;
bool hasPos = false;
int64_t retPos;
/* To get write buffer */
bool succ = false;
void *buf = nullptr;
int64_t bufLen;
NVal op(env, argOption);
NVal jsBuffer(env, argWBuf);
unique_ptr<char[]> bufferGuard;
tie(succ, bufferGuard, bufLen) = DecodeString(env, jsBuffer, op.GetProp("encoding"));
if (!succ) {
tie(succ, buf, bufLen) = NVal(env, argWBuf).ToArraybuffer();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Illegal write buffer or encoding");
return { false, nullptr, nullptr, 0, hasPos, retPos };
}
} else {
buf = bufferGuard.get();
}
tie(succ, retBuf) = GetActualBuf(env, buf, bufLen, op);
if (!succ) {
return { false, nullptr, nullptr, 0, hasPos, retPos };
}
int64_t bufOff = static_cast<uint8_t *>(retBuf) - static_cast<uint8_t *>(buf);
tie(succ, retLen) = GetActualLen(env, bufLen, bufOff, op);
if (!succ) {
return { false, nullptr, nullptr, 0, hasPos, retPos };
}
/* To parse options - Where to begin writing */
if (op.HasProp("position")) {
int32_t position = 0;
tie(succ, position) = op.GetProp("position").ToInt32();
if (!succ || position < 0) {
UniError(EINVAL).ThrowErr(env, "option.position shall be positive number");
return { false, nullptr, nullptr, 0, hasPos, retPos };
}
hasPos = true;
retPos = position;
} else {
retPos = INVALID_POSITION;
}
return { true, move(bufferGuard), retBuf, retLen, hasPos, retPos };
}
} // namespace ModuleFileIO
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "../common/napi/uni_header.h"
#include <limits>
#include <memory>
#include <tuple>
namespace OHOS {
namespace DistributedFS {
namespace ModuleFileIO {
constexpr int64_t INVALID_POSITION = std::numeric_limits<decltype(INVALID_POSITION)>::max();
struct CommonFunc {
static std::tuple<bool, void *, int64_t, bool, int64_t> GetReadArg(napi_env env,
napi_value readBuf,
napi_value option);
static std::tuple<bool, std::unique_ptr<char[]>, void *, int64_t, bool, int64_t> GetWriteArg(napi_env env,
napi_value argWBuf,
napi_value argOption);
};
} // namespace ModuleFileIO
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <memory>
#include <vector>
#include "../common/log.h"
#include "class_dir/dir_n_exporter.h"
#include "class_dirent/dirent_n_exporter.h"
#include "class_stat/stat_n_exporter.h"
#include "class_stream/stream_n_exporter.h"
#include "properties/prop_n_exporter.h"
using namespace std;
namespace OHOS {
namespace DistributedFS {
namespace ModuleFileIO {
static napi_value Export(napi_env env, napi_value exports)
{
std::vector<unique_ptr<NExporter>> products;
products.emplace_back(make_unique<PropNExporter>(env, exports));
products.emplace_back(make_unique<DirentNExporter>(env, exports));
products.emplace_back(make_unique<DirNExporter>(env, exports));
products.emplace_back(make_unique<StatNExporter>(env, exports));
products.emplace_back(make_unique<StreamNExporter>(env, exports));
for (auto &&product : products) {
if (!product->Export()) {
HILOGE("INNER BUG. Failed to export class %{public}s for module fileio", product->GetClassName().c_str());
return nullptr;
} else {
HILOGE("Class %{public}s for module fileio has been exported", product->GetClassName().c_str());
}
}
return exports;
}
NAPI_MODULE(fileio, Export)
} // namespace ModuleFileIO
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,732 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "prop_n_exporter.h"
#include <cstring>
#include <dirent.h>
#include <fcntl.h>
#include <iostream>
#include <memory>
#include <sstream>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "../../common/fd_guard.h"
#include "../../common/log.h"
#include "../../common/napi/n_class.h"
#include "../../common/napi/n_func_arg.h"
#include "../../common/napi/n_val.h"
#include "../../common/uni_error.h"
#include "../class_dir/dir_entity.h"
#include "../class_dir/dir_n_exporter.h"
#include "../class_stat/stat_entity.h"
#include "../class_stat/stat_n_exporter.h"
#include "../class_stream/stream_entity.h"
#include "../class_stream/stream_n_exporter.h"
#include "../common_func.h"
namespace OHOS {
namespace DistributedFS {
namespace ModuleFileIO {
using namespace std;
napi_value PropNExporter::AccessSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
bool succ = false;
unique_ptr<char[]> path;
tie(succ, path, ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid path");
return nullptr;
}
int argc = funcArg.GetArgc();
int ret = -1;
if (argc == NARG_CNT::ONE) {
ret = access(path.get(), 0);
} else {
int mode;
tie(succ, mode) = NVal(env, funcArg[NARG_POS::SECOND]).ToInt32();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid mode");
return nullptr;
}
ret = access(path.get(), mode);
}
if (ret == -1) {
UniError(errno).ThrowErr(env);
return nullptr;
}
return NVal::CreateUndefined(env).val_;
}
napi_value PropNExporter::CopyFileSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::TWO, NARG_CNT::THREE)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
bool succ = false;
unique_ptr<char[]> src;
tie(succ, src, ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid src");
return nullptr;
}
unique_ptr<char[]> dest;
tie(succ, dest, ignore) = NVal(env, funcArg[NARG_POS::SECOND]).ToUTF8String();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid dest");
return nullptr;
}
FDGuard sfd;
FDGuard ofd;
struct stat statbf;
sfd.SetFD(open(src.get(), O_RDONLY));
if (sfd.GetFD() == -1) {
UniError(errno).ThrowErr(env);
return nullptr;
}
int res = fstat(sfd.GetFD(), &statbf);
if (res == -1) {
UniError(errno).ThrowErr(env);
return nullptr;
}
// Note that mode means if we should force to save instead of the mode of newly create file
ofd.SetFD(open(dest.get(), O_WRONLY | O_CREAT, statbf.st_mode));
if (ofd.GetFD() == -1) {
UniError(errno).ThrowErr(env);
return nullptr;
}
int ret = sendfile(ofd.GetFD(), sfd.GetFD(), nullptr, statbf.st_size);
if (ret == -1) {
UniError(errno).ThrowErr(env);
return nullptr;
}
return NVal::CreateUndefined(env).val_;
}
napi_value PropNExporter::MkdirSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
bool succ = false;
unique_ptr<char[]> path;
tie(succ, path, ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid path");
return nullptr;
}
int ret = -1;
int argc = funcArg.GetArgc();
if (argc == NARG_CNT::ONE) {
ret = mkdir(path.get(), 0775);
} else {
int mode;
tie(succ, mode) = NVal(env, funcArg[NARG_POS::SECOND]).ToInt32();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid mode");
return nullptr;
}
ret = mkdir(path.get(), mode);
}
if (ret == -1) {
UniError(errno).ThrowErr(env);
return nullptr;
}
return NVal::CreateUndefined(env).val_;
}
napi_value PropNExporter::OpenSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::THREE)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
bool succ = false;
unique_ptr<char[]> path;
tie(succ, path, ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid path");
return nullptr;
}
int flags = O_RDONLY;
if (funcArg.GetArgc() >= NARG_CNT::TWO) {
tie(succ, flags) = NVal(env, funcArg[NARG_POS::SECOND]).ToInt32();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid flags");
return nullptr;
}
}
int fd = -1;
int argc = funcArg.GetArgc();
if (argc != NARG_CNT::THREE) {
if ((flags & O_CREAT) || (flags & O_TMPFILE)) {
UniError(EINVAL).ThrowErr(env, "called with O_CREAT/O_TMPFILE but no mode");
return nullptr;
}
fd = open(path.get(), flags);
} else {
int mode;
tie(succ, mode) = NVal(env, funcArg.GetArg(NARG_POS::THIRD)).ToInt32();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid mode");
return nullptr;
}
fd = open(path.get(), flags, mode);
}
if (fd == -1) {
UniError(errno).ThrowErr(env);
return nullptr;
}
return NVal::CreateInt64(env, fd).val_;
}
napi_value PropNExporter::ChmodSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::TWO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
bool succ = false;
unique_ptr<char[]> path;
tie(succ, path, ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid path");
return nullptr;
}
int mode;
tie(succ, mode) = NVal(env, funcArg[NARG_POS::SECOND]).ToInt32();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid mode");
return nullptr;
}
if (chmod(path.get(), mode) == -1) {
UniError(errno).ThrowErr(env);
return nullptr;
}
return NVal::CreateUndefined(env).val_;
}
napi_value PropNExporter::ChownSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::THREE)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
bool succ = false;
unique_ptr<char[]> path;
tie(succ, path, ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid path");
return nullptr;
}
int owner;
tie(succ, owner) = NVal(env, funcArg[NARG_POS::SECOND]).ToInt32();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid owner");
}
int group;
tie(succ, group) = NVal(env, funcArg[NARG_POS::THIRD]).ToInt32();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid group");
}
if (chown(path.get(), owner, group) == -1) {
UniError(errno).ThrowErr(env);
return nullptr;
}
return NVal::CreateUndefined(env).val_;
}
napi_value PropNExporter::CloseSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ONE)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
bool succ = false;
int fd;
tie(succ, fd) = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid fd");
return nullptr;
}
if (close(fd) == -1) {
UniError(errno).ThrowErr(env);
return nullptr;
}
return NVal::CreateUndefined(env).val_;
}
napi_value PropNExporter::FchmodSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::TWO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
bool succ = false;
int fd;
tie(succ, fd) = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid fd");
return nullptr;
}
int mode;
tie(succ, mode) = NVal(env, funcArg[NARG_POS::SECOND]).ToInt32();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid mode");
return nullptr;
}
int ret = fchmod(fd, mode);
if (ret == -1) {
UniError(errno).ThrowErr(env);
return nullptr;
}
return NVal::CreateUndefined(env).val_;
}
napi_value PropNExporter::FchownSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::THREE)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
bool succ = false;
int fd;
tie(succ, fd) = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid fd");
return nullptr;
}
int owner;
tie(succ, owner) = NVal(env, funcArg[NARG_POS::SECOND]).ToInt32();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid owner");
}
int group;
tie(succ, group) = NVal(env, funcArg[NARG_POS::THIRD]).ToInt32();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid group");
}
int ret = fchown(fd, owner, group);
if (ret == -1) {
UniError(errno).ThrowErr(env);
return nullptr;
}
return NVal::CreateUndefined(env).val_;
}
napi_value PropNExporter::FstatSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ONE)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
bool succ = false;
int fd;
tie(succ, fd) = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid fd");
return nullptr;
}
struct stat buf;
if (fstat(fd, &buf) == -1) {
UniError(errno).ThrowErr(env);
return nullptr;
}
napi_value objStat = NClass::InstantiateClass(env, StatNExporter::className_, {});
if (!objStat) {
UniError(EINVAL).ThrowErr(env, "Cannot instantiate class");
return nullptr;
}
auto statEntity = NClass::GetEntityOf<StatEntity>(env, objStat);
if (!statEntity) {
UniError(EINVAL).ThrowErr(env, "Cannot get the entity of objStat");
return nullptr;
}
statEntity->stat_ = buf;
return objStat;
}
napi_value PropNExporter::FtruncateSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
bool succ = false;
int fd;
tie(succ, fd) = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid fd");
return nullptr;
}
int argc = funcArg.GetArgc();
int ret = -1;
if (argc == NARG_CNT::ONE) {
ret = ftruncate(fd, 0);
} else {
int len;
tie(succ, len) = NVal(env, funcArg[NARG_POS::SECOND]).ToInt32();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid len");
return nullptr;
}
ret = ftruncate(fd, len);
}
if (ret == -1) {
UniError(errno).ThrowErr(env);
return nullptr;
}
return NVal::CreateUndefined(env).val_;
}
napi_value PropNExporter::ReadSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::TWO, NARG_CNT::THREE)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
bool succ = false;
int fd;
tie(succ, fd) = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid fd");
return nullptr;
}
void *buf = nullptr;
int64_t len;
bool hasPos = false;
int64_t pos;
tie(succ, buf, len, hasPos, pos) = CommonFunc::GetReadArg(env, funcArg[NARG_POS::SECOND], funcArg[NARG_POS::THIRD]);
if (!succ) {
return nullptr;
}
ssize_t actLen;
if (hasPos) {
actLen = pread(fd, buf, len, pos);
} else {
actLen = read(fd, buf, len);
}
if (actLen == -1) {
UniError(errno).ThrowErr(env);
return nullptr;
}
return NVal::CreateInt64(env, actLen).val_;
}
napi_value PropNExporter::RenameSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::TWO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
bool succ = false;
unique_ptr<char[]> src;
tie(succ, src, ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid src");
return nullptr;
}
unique_ptr<char[]> dest;
tie(succ, dest, ignore) = NVal(env, funcArg[NARG_POS::SECOND]).ToUTF8String();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid dest");
return nullptr;
}
if (rename(src.get(), dest.get()) == -1) {
UniError(errno).ThrowErr(env);
return nullptr;
}
return NVal::CreateUndefined(env).val_;
}
napi_value PropNExporter::RmdirSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ONE)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
bool succ = false;
unique_ptr<char[]> path;
tie(succ, path, ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid path");
return nullptr;
}
if (rmdir(path.get()) == -1) {
UniError(errno).ThrowErr(env);
return nullptr;
}
return NVal::CreateUndefined(env).val_;
}
napi_value PropNExporter::UnlinkSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ONE)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
bool succ = false;
unique_ptr<char[]> path;
tie(succ, path, ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid path");
return nullptr;
}
if (unlink(path.get()) == -1) {
UniError(errno).ThrowErr(env);
return nullptr;
}
return NVal::CreateUndefined(env).val_;
}
napi_value PropNExporter::FsyncSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ONE)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
bool succ = false;
int fd;
tie(succ, fd) = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid fd");
return nullptr;
}
if (fsync(fd) == -1) {
UniError(errno).ThrowErr(env);
return nullptr;
}
return NVal::CreateUndefined(env).val_;
}
napi_value PropNExporter::TruncateSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
bool succ = false;
unique_ptr<char[]> path;
tie(succ, path, ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid path");
return nullptr;
}
int ret = -1;
if (funcArg.GetArgc() == NARG_CNT::ONE) {
ret = truncate(path.get(), 0);
} else {
int len;
tie(succ, len) = NVal(env, funcArg[NARG_POS::SECOND]).ToInt32();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid len");
}
ret = truncate(path.get(), len);
}
if (ret == -1) {
UniError(errno).ThrowErr(env);
return nullptr;
}
return NVal::CreateUndefined(env).val_;
}
napi_value PropNExporter::WriteSync(napi_env env, napi_callback_info info)
{
NFuncArg funcArg(env, info);
if (!funcArg.InitArgs(NARG_CNT::TWO, NARG_CNT::THREE)) {
UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
return nullptr;
}
bool succ = false;
int fd;
tie(succ, fd) = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32();
if (!succ) {
UniError(EINVAL).ThrowErr(env, "Invalid fd");
return nullptr;
}
void *buf = nullptr;
size_t len;
size_t position;
unique_ptr<char[]> bufGuard;
bool hasPos = false;
tie(succ, bufGuard, buf, len, hasPos, position) =
CommonFunc::GetWriteArg(env, funcArg[NARG_POS::SECOND], funcArg[NARG_POS::THIRD]);
if (!succ) {
return nullptr;
}
ssize_t writeLen;
if (position == (size_t)INVALID_POSITION) {
writeLen = write(fd, buf, len);
} else {
writeLen = pwrite(fd, buf, len, position);
}
if (writeLen == -1) {
UniError(errno).ThrowErr(env);
return nullptr;
}
return NVal::CreateInt64(env, writeLen).val_;
}
bool PropNExporter::Export()
{
return exports_.AddProp({
NVal::DeclareNapiFunction("openSync", OpenSync),
NVal::DeclareNapiFunction("accessSync", AccessSync),
NVal::DeclareNapiFunction("chmodSync", ChmodSync),
NVal::DeclareNapiFunction("chownSync", ChownSync),
NVal::DeclareNapiFunction("closeSync", CloseSync),
NVal::DeclareNapiFunction("copyFileSync", CopyFileSync),
NVal::DeclareNapiFunction("fchmodSync", FchmodSync),
NVal::DeclareNapiFunction("fchownSync", FchownSync),
NVal::DeclareNapiFunction("fstatSync", FstatSync),
NVal::DeclareNapiFunction("ftruncateSync", FtruncateSync),
NVal::DeclareNapiFunction("mkdirSync", MkdirSync),
NVal::DeclareNapiFunction("readSync", ReadSync),
NVal::DeclareNapiFunction("renameSync", RenameSync),
NVal::DeclareNapiFunction("rmdirSync", RmdirSync),
NVal::DeclareNapiFunction("unlinkSync", UnlinkSync),
NVal::DeclareNapiFunction("fsyncSync", FsyncSync),
NVal::DeclareNapiFunction("truncateSync", TruncateSync),
NVal::DeclareNapiFunction("writeSync", WriteSync),
});
}
string PropNExporter::GetClassName()
{
return PropNExporter::className_;
}
PropNExporter::PropNExporter(napi_env env, napi_value exports) : NExporter(env, exports) {}
PropNExporter::~PropNExporter() {}
} // namespace ModuleFileIO
} // namespace DistributedFS
} // namespace OHOS

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "../../common/napi/n_exporter.h"
namespace OHOS {
namespace DistributedFS {
namespace ModuleFileIO {
class PropNExporter final : public NExporter {
public:
inline static const std::string className_ = "__properities__";
static napi_value OpenSync(napi_env env, napi_callback_info info);
static napi_value AccessSync(napi_env env, napi_callback_info info);
static napi_value ChmodSync(napi_env env, napi_callback_info info);
static napi_value ChownSync(napi_env env, napi_callback_info info);
static napi_value CloseSync(napi_env env, napi_callback_info info);
static napi_value CopyFileSync(napi_env env, napi_callback_info info);
static napi_value FchmodSync(napi_env env, napi_callback_info info);
static napi_value FchownSync(napi_env env, napi_callback_info info);
static napi_value FstatSync(napi_env env, napi_callback_info info);
static napi_value FtruncateSync(napi_env env, napi_callback_info info);
static napi_value MkdirSync(napi_env env, napi_callback_info info);
static napi_value ReadSync(napi_env env, napi_callback_info info);
static napi_value RenameSync(napi_env env, napi_callback_info info);
static napi_value RmdirSync(napi_env env, napi_callback_info info);
static napi_value UnlinkSync(napi_env env, napi_callback_info info);
static napi_value FsyncSync(napi_env env, napi_callback_info info);
static napi_value TruncateSync(napi_env env, napi_callback_info info);
static napi_value WriteSync(napi_env env, napi_callback_info info);
static napi_value OpenDirSync(napi_env env, napi_callback_info info);
bool Export() override;
std::string GetClassName() override;
PropNExporter(napi_env env, napi_value exports);
~PropNExporter() override;
};
} // namespace ModuleFileIO
} // namespace DistributedFS
} // namespace OHOS

14
ohos.build Executable file
View File

@ -0,0 +1,14 @@
{
"subsystem": "distributeddatamgr",
"parts": {
"distributedfilejs": {
"variants": [
"wearable",
"phone"
],
"module_list": [
"//foundation/distributeddatamgr/distributedfile/interfaces/kits/js:build_kits_js"
]
}
}
}