• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "los_fs.h"
33 #include "los_config.h"
34 #include "fs_operations.h"
35 #if (LOSCFG_SUPPORT_FATFS == 1)
36 #include "fatfs.h"
37 #endif
38 #include "dirent.h"
39 #include "errno.h"
40 #include "fcntl.h"
41 #include "securec.h"
42 #include "stdio.h"
43 #include "stdlib.h"
44 #include "string.h"
45 #include "sys/mount.h"
46 #include "sys/statfs.h"
47 #include "sys/stat.h"
48 #include "unistd.h"
49 
50 #ifdef LOSCFG_NET_LWIP_SACK
51 #define _BSD_SOURCE
52 #include "lwip/sockets.h"
53 #endif
54 
55 #include "vfs_config.h"
56 
57 #ifdef LOSCFG_RANDOM_DEV
58 #include "hks_client.h"
59 #define RANDOM_DEV_FD  CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS
60 #define RANDOM_DEV_PATH  "/dev/random"
61 #endif
62 
63 #if (LOSCFG_POSIX_PIPE_API == 1)
64 #include "pipe_impl.h"
65 #ifdef LOSCFG_RANDOM_DEV
66 #define PIPE_DEV_FD (RANDOM_DEV_FD + 1)
67 #else
68 #define PIPE_DEV_FD (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)
69 #endif
70 
PollQueryFd(int fd,struct PollTable * table)71 int PollQueryFd(int fd, struct PollTable *table)
72 {
73     if (fd >= PIPE_DEV_FD) {
74         return PipePoll(fd, table);
75     }
76 
77     return -ENODEV;
78 }
79 #endif
80 
81 #define FREE_AND_SET_NULL(ptr) do { \
82     free(ptr);                      \
83     ptr = NULL;                     \
84 } while (0)
85 
86 #ifdef LOSCFG_RANDOM_DEV
87 /**
88  * @brief Get canonical form of a given path based on cwd(Current working directory).
89  *
90  * @param cwd Indicates the current working directory.
91  * @param path Indicates the path to be canonicalization.
92  * @param buf Indicates the pointer to the buffer where the result will be return.
93  * @param bufSize Indicates the size of the buffer.
94  * @return Returns the length of the canonical path.
95  *
96  * @attention if path is an absolute path, cwd is ignored. if cwd if not specified, it is assumed to be root('/').
97  *            if the buffer is not big enough the result will be truncated, but the return value will always be the
98  *            length of the canonical path.
99  */
GetCanonicalPath(const char * cwd,const char * path,char * buf,size_t bufSize)100 static size_t GetCanonicalPath(const char *cwd, const char *path, char *buf, size_t bufSize)
101 {
102     size_t offset;
103     if (!path) {
104         path = "";
105     }
106 
107     if (!cwd || path[0] == '/') {
108         cwd = "";
109     }
110 
111     offset = strlen("///") + 1; // three '/' and one '\0'
112     size_t tmpLen = strlen(cwd) + strlen(path) + offset;
113     char *tmpBuf = (char *)malloc(tmpLen);
114     if (tmpBuf == NULL) {
115         return FS_SUCCESS;
116     }
117 
118     if (-1 == sprintf_s(tmpBuf, tmpLen, "/%s/%s/", cwd, path)) {
119         free(tmpBuf);
120         return FS_SUCCESS;
121     }
122 
123     char *p;
124     /* replace /./ to / */
125     offset = strlen("/./") - 1;
126     while ((p = strstr(tmpBuf, "/./")) != NULL) {
127         if (EOK != memmove_s(p, tmpLen - (p - tmpBuf), p + offset, tmpLen - (p - tmpBuf) - offset)) {
128             free(tmpBuf);
129             return FS_SUCCESS;
130         }
131     }
132 
133     /* replace // to / */
134     while ((p = strstr(tmpBuf, "//")) != NULL) {
135         if (EOK != memmove_s(p, tmpLen - (p - tmpBuf), p + 1, tmpLen - (p - tmpBuf) - 1)) {
136             free(tmpBuf);
137             return FS_SUCCESS;
138         }
139     }
140 
141     /* handle /../ (e.g., replace /aa/bb/../ to /aa/) */
142     offset = strlen("/../") - 1;
143     while ((p = strstr(tmpBuf, "/../")) != NULL) {
144         char *start = p;
145         while (start > tmpBuf && *(start - 1) != '/') {
146             --start;
147         }
148         if (EOK != memmove_s(start, tmpLen - (start - tmpBuf), p + offset, tmpLen - (p - tmpBuf) - offset)) {
149             free(tmpBuf);
150             return FS_SUCCESS;
151         }
152     }
153 
154     size_t totalLen = strlen(tmpBuf);
155     /* strip the last / */
156     if (totalLen > 1 && tmpBuf[totalLen - 1] == '/') {
157         tmpBuf[--totalLen] = 0;
158     }
159 
160     if (!buf || bufSize == 0) {
161         free(tmpBuf);
162         return totalLen;
163     }
164 
165     if (EOK != memcpy_s(buf, bufSize, tmpBuf, (((totalLen + 1) > bufSize) ? bufSize : (totalLen + 1)))) {
166         free(tmpBuf);
167         return FS_SUCCESS;
168     }
169 
170     buf[bufSize - 1] = 0;
171     free(tmpBuf);
172     return totalLen;
173 }
174 #endif
175 
176 static struct FsMap g_fsmap[MAX_FILESYSTEM_LEN] = {0};
177 static struct FsMap *g_fs = NULL;
178 
InitMountInfo(void)179 static void InitMountInfo(void)
180 {
181 #if (LOSCFG_SUPPORT_FATFS == 1)
182     extern struct MountOps g_fatfsMnt;
183     extern struct FileOps g_fatfsFops;
184     g_fsmap[0].fileSystemtype = strdup("fat");
185     g_fsmap[0].fsMops = &g_fatfsMnt;
186     g_fsmap[0].fsFops = &g_fatfsFops;
187 #endif
188 #if (LOSCFG_SUPPORT_LITTLEFS == 1)
189     extern struct MountOps g_lfsMnt;
190     extern struct FileOps g_lfsFops;
191     g_fsmap[1].fileSystemtype = strdup("littlefs");
192     g_fsmap[1].fsMops = &g_lfsMnt;
193     g_fsmap[1].fsFops = &g_lfsFops;
194 #endif
195 }
196 
MountFindfs(const char * fileSystemtype)197 static struct FsMap *MountFindfs(const char *fileSystemtype)
198 {
199     struct FsMap *m = NULL;
200 
201     for (int i = 0; i < MAX_FILESYSTEM_LEN; i++) {
202         m = &(g_fsmap[i]);
203         if (m->fileSystemtype && strcmp(fileSystemtype, m->fileSystemtype) == 0) {
204             return m;
205         }
206     }
207 
208     return NULL;
209 }
210 
LOS_FsMount(const char * source,const char * target,const char * filesystemtype,unsigned long mountflags,const void * data)211 int LOS_FsMount(const char *source, const char *target,
212                 const char *filesystemtype, unsigned long mountflags,
213                 const void *data)
214 {
215     static int initFlag = 0;
216 
217     if (initFlag == 0) {
218         InitMountInfo();
219         initFlag = 1;
220     }
221 
222     g_fs = MountFindfs(filesystemtype);
223     if (g_fs == NULL) {
224         errno = ENODEV;
225         return FS_FAILURE;
226     }
227 
228     if (g_fs->fsMops == NULL || g_fs->fsMops->Mount == NULL) {
229         errno = ENOSYS;
230         return FS_FAILURE;
231     }
232 
233     return g_fs->fsMops->Mount(source, target, filesystemtype, mountflags, data);
234 }
235 
LOS_FsUmount(const char * target)236 int LOS_FsUmount(const char *target)
237 {
238     if (g_fs == NULL) {
239         errno = ENODEV;
240         return FS_FAILURE;
241     }
242     if (g_fs->fsMops == NULL || g_fs->fsMops->Umount == NULL) {
243         errno = ENOSYS;
244         return FS_FAILURE;
245     }
246     return g_fs->fsMops->Umount(target);
247 }
248 
LOS_FsUmount2(const char * target,int flag)249 int LOS_FsUmount2(const char *target, int flag)
250 {
251     if (g_fs == NULL) {
252         errno = ENODEV;
253         return FS_FAILURE;
254     }
255     if (g_fs->fsMops == NULL || g_fs->fsMops->Umount2 == NULL) {
256         errno = ENOSYS;
257         return FS_FAILURE;
258     }
259     return g_fs->fsMops->Umount2(target, flag);
260 }
261 
LOS_Open(const char * path,int oflag,...)262 int LOS_Open(const char *path, int oflag, ...)
263 {
264 #ifdef LOSCFG_RANDOM_DEV
265     unsigned flags = O_RDONLY | O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_LARGEFILE | O_TRUNC | O_EXCL | O_DIRECTORY;
266     if ((unsigned)oflag & ~flags) {
267         errno = EINVAL;
268         return FS_FAILURE;
269     }
270 
271     size_t pathLen = strlen(path) + 1;
272     if ((unsigned)pathLen > PATH_MAX) {
273         errno = EINVAL;
274         return FS_FAILURE;
275     }
276     char *canonicalPath = (char *)malloc(pathLen);
277     if (!canonicalPath) {
278         errno = ENOMEM;
279         return FS_FAILURE;
280     }
281     if (GetCanonicalPath(NULL, path, canonicalPath, pathLen) == 0) {
282         FREE_AND_SET_NULL(canonicalPath);
283         errno = ENOMEM;
284         return FS_FAILURE;
285     }
286 
287     if (strcmp(canonicalPath, RANDOM_DEV_PATH) == 0) {
288         FREE_AND_SET_NULL(canonicalPath);
289         if ((O_ACCMODE & (unsigned)oflag) != O_RDONLY) {
290             errno = EPERM;
291             return FS_FAILURE;
292         }
293         if ((unsigned)oflag & O_DIRECTORY) {
294             errno = ENOTDIR;
295             return FS_FAILURE;
296         }
297         return RANDOM_DEV_FD;
298     }
299     if (strcmp(canonicalPath, "/") == 0 || strcmp(canonicalPath, "/dev") == 0) {
300         FREE_AND_SET_NULL(canonicalPath);
301         if ((unsigned)oflag & O_DIRECTORY) {
302             errno = EPERM;
303             return FS_FAILURE;
304         }
305         errno = EISDIR;
306         return FS_FAILURE;
307     }
308     FREE_AND_SET_NULL(canonicalPath);
309 #endif
310 
311 #if (LOSCFG_POSIX_PIPE_API == 1)
312     if ((path != NULL) && !strncmp(path, PIPE_DEV_PATH, strlen(PIPE_DEV_PATH))) {
313         return PipeOpen(path, oflag, PIPE_DEV_FD);
314     }
315 #endif
316 
317     if (g_fs == NULL) {
318         errno = ENODEV;
319         return FS_FAILURE;
320     }
321     if (g_fs->fsFops == NULL || g_fs->fsFops->Open == NULL) {
322         errno = ENOSYS;
323         return FS_FAILURE;
324     }
325     return g_fs->fsFops->Open(path, oflag);
326 }
327 
LOS_Close(int fd)328 int LOS_Close(int fd)
329 {
330 #ifdef LOSCFG_RANDOM_DEV
331     if (fd == RANDOM_DEV_FD) {
332         return FS_SUCCESS;
333     }
334 #endif
335 #ifdef LOSCFG_NET_LWIP_SACK
336     if (fd >= CONFIG_NFILE_DESCRIPTORS && fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) {
337         return closesocket(fd);
338     }
339 #endif
340 
341 #if (LOSCFG_POSIX_PIPE_API == 1)
342     if (fd >= PIPE_DEV_FD) {
343         return PipeClose(fd);
344     }
345 #endif
346 
347     if (g_fs == NULL) {
348         errno = ENODEV;
349         return FS_FAILURE;
350     }
351     if (g_fs->fsFops == NULL || g_fs->fsFops->Close == NULL) {
352         errno = ENOSYS;
353         return FS_FAILURE;
354     }
355     return g_fs->fsFops->Close(fd);
356 }
357 
LOS_Read(int fd,void * buf,size_t nbyte)358 ssize_t LOS_Read(int fd, void *buf, size_t nbyte)
359 {
360 #ifdef LOSCFG_RANDOM_DEV
361     if (fd == RANDOM_DEV_FD) {
362         if (nbyte == 0) {
363             return FS_SUCCESS;
364         }
365         if (buf == NULL) {
366             errno = EINVAL;
367             return FS_FAILURE;
368         }
369         if (nbyte > 1024) { /* 1024, max random_size */
370             nbyte = 1024; /* hks_generate_random: random_size must <= 1024 */
371         }
372         struct hks_blob key = {HKS_BLOB_TYPE_RAW, (uint8_t *)buf, nbyte};
373         if (hks_generate_random(&key) != 0) {
374             errno = EIO;
375             return FS_FAILURE;
376         }
377         return (ssize_t)nbyte;
378     }
379 #endif
380 #ifdef LOSCFG_NET_LWIP_SACK
381     if (fd >= CONFIG_NFILE_DESCRIPTORS && fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) {
382         return recv(fd, buf, nbyte, 0);
383     }
384 #endif
385 
386 #if (LOSCFG_POSIX_PIPE_API == 1)
387     if (fd >= PIPE_DEV_FD) {
388         return PipeRead(fd, buf, nbyte);
389     }
390 #endif
391 
392     if (g_fs == NULL) {
393         errno = ENODEV;
394         return FS_FAILURE;
395     }
396     if (g_fs->fsFops == NULL || g_fs->fsFops->Read == NULL) {
397         errno = ENOSYS;
398         return FS_FAILURE;
399     }
400     return g_fs->fsFops->Read(fd, buf, nbyte);
401 }
402 
LOS_Write(int fd,const void * buf,size_t nbyte)403 ssize_t LOS_Write(int fd, const void *buf, size_t nbyte)
404 {
405 #ifdef LOSCFG_RANDOM_DEV
406     if (fd == RANDOM_DEV_FD) {
407         errno = EBADF; /* "/dev/random" is readonly */
408         return FS_FAILURE;
409     }
410 #endif
411 #ifdef LOSCFG_NET_LWIP_SACK
412     if (fd >= CONFIG_NFILE_DESCRIPTORS && fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) {
413         return send(fd, buf, nbyte, 0);
414     }
415 #endif
416 
417 #if (LOSCFG_POSIX_PIPE_API == 1)
418     if (fd >= PIPE_DEV_FD) {
419         return PipeWrite(fd, buf, nbyte);
420     }
421 #endif
422 
423     if (g_fs == NULL) {
424         errno = ENODEV;
425         return FS_FAILURE;
426     }
427     if (g_fs->fsFops == NULL || g_fs->fsFops->Write == NULL) {
428         errno = ENOSYS;
429         return FS_FAILURE;
430     }
431     return g_fs->fsFops->Write(fd, buf, nbyte);
432 }
433 
LOS_Lseek(int fd,off_t offset,int whence)434 off_t LOS_Lseek(int fd, off_t offset, int whence)
435 {
436     if (g_fs == NULL) {
437         errno = ENODEV;
438         return FS_FAILURE;
439     }
440     if (g_fs->fsFops == NULL || g_fs->fsFops->Seek == NULL) {
441         errno = ENOSYS;
442         return FS_FAILURE;
443     }
444     return g_fs->fsFops->Seek(fd, offset, whence);
445 }
446 
LOS_Unlink(const char * path)447 int LOS_Unlink(const char *path)
448 {
449     if (g_fs == NULL) {
450         errno = ENODEV;
451         return FS_FAILURE;
452     }
453     if (g_fs->fsFops == NULL || g_fs->fsFops->Unlink == NULL) {
454         errno = ENOSYS;
455         return FS_FAILURE;
456     }
457     return g_fs->fsFops->Unlink(path);
458 }
459 
LOS_Fstat(int fd,struct stat * buf)460 int LOS_Fstat(int fd, struct stat *buf)
461 {
462     if (g_fs == NULL) {
463         errno = ENODEV;
464         return FS_FAILURE;
465     }
466     if (g_fs->fsFops == NULL || g_fs->fsFops->Fstat == NULL) {
467         errno = ENOSYS;
468         return FS_FAILURE;
469     }
470     return g_fs->fsFops->Fstat(fd, buf);
471 }
472 
LOS_Stat(const char * path,struct stat * buf)473 int LOS_Stat(const char *path, struct stat *buf)
474 {
475     if (g_fs == NULL) {
476         errno = ENODEV;
477         return FS_FAILURE;
478     }
479     if (g_fs->fsFops == NULL || g_fs->fsFops->Getattr == NULL) {
480         errno = ENOSYS;
481         return FS_FAILURE;
482     }
483     return g_fs->fsFops->Getattr(path, buf);
484 }
485 
LOS_Fsync(int fd)486 int LOS_Fsync(int fd)
487 {
488     if (g_fs == NULL) {
489         errno = ENODEV;
490         return FS_FAILURE;
491     }
492     if (g_fs->fsFops == NULL || g_fs->fsFops->Fsync == NULL) {
493         errno = ENOSYS;
494         return FS_FAILURE;
495     }
496     return g_fs->fsFops->Fsync(fd);
497 }
498 
LOS_Mkdir(const char * path,mode_t mode)499 int LOS_Mkdir(const char *path, mode_t mode)
500 {
501     if (g_fs == NULL) {
502         errno = ENODEV;
503         return FS_FAILURE;
504     }
505     if (g_fs->fsFops == NULL || g_fs->fsFops->Mkdir == NULL) {
506         errno = ENOSYS;
507         return FS_FAILURE;
508     }
509     return g_fs->fsFops->Mkdir(path, mode);
510 }
511 
LOS_Opendir(const char * dirName)512 DIR *LOS_Opendir(const char *dirName)
513 {
514     if (g_fs == NULL) {
515         errno = ENODEV;
516         return NULL;
517     }
518     if (g_fs->fsFops == NULL || g_fs->fsFops->Opendir == NULL) {
519         errno = ENOSYS;
520         return NULL;
521     }
522     return g_fs->fsFops->Opendir(dirName);
523 }
524 
LOS_Readdir(DIR * dir)525 struct dirent *LOS_Readdir(DIR *dir)
526 {
527     if (g_fs == NULL) {
528         errno = ENODEV;
529         return NULL;
530     }
531     if (g_fs->fsFops == NULL || g_fs->fsFops->Readdir == NULL) {
532         errno = ENOSYS;
533         return NULL;
534     }
535     return g_fs->fsFops->Readdir(dir);
536 }
537 
LOS_Closedir(DIR * dir)538 int LOS_Closedir(DIR *dir)
539 {
540     if (g_fs == NULL) {
541         errno = ENODEV;
542         return FS_FAILURE;
543     }
544     if (g_fs->fsFops == NULL || g_fs->fsFops->Closedir == NULL) {
545         errno = ENOSYS;
546         return FS_FAILURE;
547     }
548     return g_fs->fsFops->Closedir(dir);
549 }
550 
LOS_Rmdir(const char * path)551 int LOS_Rmdir(const char *path)
552 {
553     if (g_fs == NULL) {
554         errno = ENODEV;
555         return FS_FAILURE;
556     }
557     if (g_fs->fsFops == NULL || g_fs->fsFops->Rmdir == NULL) {
558         errno = ENOSYS;
559         return FS_FAILURE;
560     }
561     return g_fs->fsFops->Rmdir(path);
562 }
563 
LOS_Rename(const char * oldName,const char * newName)564 int LOS_Rename(const char *oldName, const char *newName)
565 {
566     if (g_fs == NULL) {
567         errno = ENODEV;
568         return FS_FAILURE;
569     }
570     if (g_fs->fsFops == NULL || g_fs->fsFops->Rename == NULL) {
571         errno = ENOSYS;
572         return FS_FAILURE;
573     }
574     return g_fs->fsFops->Rename(oldName, newName);
575 }
576 
LOS_Statfs(const char * path,struct statfs * buf)577 int LOS_Statfs(const char *path, struct statfs *buf)
578 {
579     if (g_fs == NULL) {
580         errno = ENODEV;
581         return FS_FAILURE;
582     }
583     if (g_fs->fsMops == NULL || g_fs->fsMops->Statfs == NULL) {
584         errno = ENOSYS;
585         return FS_FAILURE;
586     }
587     return g_fs->fsMops->Statfs(path, buf);
588 }
589 
LOS_Ftruncate(int fd,off_t length)590 int LOS_Ftruncate(int fd, off_t length)
591 {
592     if (g_fs == NULL) {
593         errno = ENODEV;
594         return FS_FAILURE;
595     }
596     if (g_fs->fsFops == NULL || g_fs->fsFops->Ftruncate == NULL) {
597         errno = ENOSYS;
598         return FS_FAILURE;
599     }
600     return g_fs->fsFops->Ftruncate(fd, length);
601 }
602 
LOS_Pread(int fd,void * buf,size_t nbyte,off_t offset)603 ssize_t LOS_Pread(int fd, void *buf, size_t nbyte, off_t offset)
604 {
605 #ifdef LOSCFG_RANDOM_DEV
606     if (fd == RANDOM_DEV_FD) {
607         if (nbyte == 0) {
608             return FS_SUCCESS;
609         }
610         if (buf == NULL) {
611             errno = EINVAL;
612             return FS_FAILURE;
613         }
614         if (nbyte > 1024) { /* 1024, max random_size */
615             nbyte = 1024; /* hks_generate_random: random_size must <= 1024 */
616         }
617         struct hks_blob key = {HKS_BLOB_TYPE_RAW, (uint8_t *)buf, nbyte};
618         if (hks_generate_random(&key) != 0) {
619             errno = EIO;
620             return FS_FAILURE;
621         }
622         return (ssize_t)nbyte;
623     }
624 #endif
625     if (g_fs == NULL) {
626         errno = ENODEV;
627         return FS_FAILURE;
628     }
629     if (g_fs->fsFops == NULL || g_fs->fsFops->Pread == NULL) {
630         errno = ENOSYS;
631         return FS_FAILURE;
632     }
633     return g_fs->fsFops->Pread(fd, buf, nbyte, offset);
634 }
635 
LOS_Pwrite(int fd,const void * buf,size_t nbyte,off_t offset)636 ssize_t LOS_Pwrite(int fd, const void *buf, size_t nbyte, off_t offset)
637 {
638 #ifdef LOSCFG_RANDOM_DEV
639     if (fd == RANDOM_DEV_FD) {
640         errno = EBADF; /* "/dev/random" is readonly */
641         return FS_FAILURE;
642     }
643 #endif
644     if (g_fs == NULL) {
645         errno = ENODEV;
646         return FS_FAILURE;
647     }
648     if (g_fs->fsFops == NULL || g_fs->fsFops->Pwrite == NULL) {
649         errno = ENOSYS;
650         return FS_FAILURE;
651     }
652     return g_fs->fsFops->Pwrite(fd, buf, nbyte, offset);
653 }
654