1beacf11bSopenharmony_ci/****************************************************************************
2beacf11bSopenharmony_ci * fs/tmpfs/fs_tmpfs.c
3beacf11bSopenharmony_ci *
4beacf11bSopenharmony_ci * Licensed to the Apache Software Foundation (ASF) under one or more
5beacf11bSopenharmony_ci * contributor license agreements.  See the NOTICE file distributed with
6beacf11bSopenharmony_ci * this work for additional information regarding copyright ownership.  The
7beacf11bSopenharmony_ci * ASF licenses this file to you under the Apache License, Version 2.0 (the
8beacf11bSopenharmony_ci * "License"); you may not use this file except in compliance with the
9beacf11bSopenharmony_ci * License.  You may obtain a copy of the License at
10beacf11bSopenharmony_ci *
11beacf11bSopenharmony_ci *   http://www.apache.org/licenses/LICENSE-2.0
12beacf11bSopenharmony_ci *
13beacf11bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
14beacf11bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15beacf11bSopenharmony_ci * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
16beacf11bSopenharmony_ci * License for the specific language governing permissions and limitations
17beacf11bSopenharmony_ci * under the License.
18beacf11bSopenharmony_ci *
19beacf11bSopenharmony_ci ****************************************************************************/
20beacf11bSopenharmony_ci
21beacf11bSopenharmony_ci/****************************************************************************
22beacf11bSopenharmony_ci * Included Files
23beacf11bSopenharmony_ci ****************************************************************************/
24beacf11bSopenharmony_ci#include <string.h>
25beacf11bSopenharmony_ci#include <fcntl.h>
26beacf11bSopenharmony_ci#include <errno.h>
27beacf11bSopenharmony_ci#include <assert.h>
28beacf11bSopenharmony_ci#include <unistd.h>
29beacf11bSopenharmony_ci#include <limits.h>
30beacf11bSopenharmony_ci#include <sys/types.h>
31beacf11bSopenharmony_ci#include <sys/time.h>
32beacf11bSopenharmony_ci#include <linux/spinlock.h>
33beacf11bSopenharmony_ci#include <sys/statfs.h>
34beacf11bSopenharmony_ci#include "fs/dirent_fs.h"
35beacf11bSopenharmony_ci#include "fs/mount.h"
36beacf11bSopenharmony_ci#include "fs/file.h"
37beacf11bSopenharmony_ci#include "fs/fs.h"
38beacf11bSopenharmony_ci#include "los_tables.h"
39beacf11bSopenharmony_ci#include "fs_tmpfs.h"
40beacf11bSopenharmony_ci#include "los_vm_filemap.h"
41beacf11bSopenharmony_ci#include "user_copy.h"
42beacf11bSopenharmony_ci
43beacf11bSopenharmony_ci#ifdef LOSCFG_FS_RAMFS
44beacf11bSopenharmony_ci
45beacf11bSopenharmony_ci/****************************************************************************
46beacf11bSopenharmony_ci * Pre-processor Definitions
47beacf11bSopenharmony_ci ****************************************************************************/
48beacf11bSopenharmony_ci/*
49beacf11bSopenharmony_ci#if CONFIG_FS_TMPFS_DIRECTORY_FREEGUARD <= CONFIG_FS_TMPFS_DIRECTORY_ALLOCGUARD
50beacf11bSopenharmony_ci#  warning CONFIG_FS_TMPFS_DIRECTORY_FREEGUARD needs to be > ALLOCGUARD
51beacf11bSopenharmony_ci#endif
52beacf11bSopenharmony_ci
53beacf11bSopenharmony_ci#if CONFIG_FS_TMPFS_FILE_FREEGUARD <= CONFIG_FS_TMPFS_FILE_ALLOCGUARD
54beacf11bSopenharmony_ci#  warning CONFIG_FS_TMPFS_FILE_FREEGUARD needs to be > ALLOCGUARD
55beacf11bSopenharmony_ci#endif
56beacf11bSopenharmony_ci*/
57beacf11bSopenharmony_ci#define tmpfs_lock_file(tfo) \
58beacf11bSopenharmony_ci           (tmpfs_lock_object((struct tmpfs_object_s *)tfo))
59beacf11bSopenharmony_ci#define tmpfs_lock_directory(tdo) \
60beacf11bSopenharmony_ci           (tmpfs_lock_object((struct tmpfs_object_s *)tdo))
61beacf11bSopenharmony_ci#define tmpfs_unlock_file(tfo) \
62beacf11bSopenharmony_ci           (tmpfs_unlock_object((struct tmpfs_object_s *)tfo))
63beacf11bSopenharmony_ci#define tmpfs_unlock_directory(tdo) \
64beacf11bSopenharmony_ci           (tmpfs_unlock_object((struct tmpfs_object_s *)tdo))
65beacf11bSopenharmony_ci
66beacf11bSopenharmony_ci/****************************************************************************
67beacf11bSopenharmony_ci * Private Function Prototypes
68beacf11bSopenharmony_ci ****************************************************************************/
69beacf11bSopenharmony_ci
70beacf11bSopenharmony_ci/* TMPFS helpers */
71beacf11bSopenharmony_ci
72beacf11bSopenharmony_cistatic void tmpfs_lock_reentrant(struct tmpfs_sem_s *sem);
73beacf11bSopenharmony_cistatic void tmpfs_lock(struct tmpfs_s *fs);
74beacf11bSopenharmony_cistatic void tmpfs_unlock_reentrant(struct tmpfs_sem_s *sem);
75beacf11bSopenharmony_cistatic void tmpfs_unlock(struct tmpfs_s *fs);
76beacf11bSopenharmony_cistatic void tmpfs_lock_object(struct tmpfs_object_s *to);
77beacf11bSopenharmony_cistatic void tmpfs_unlock_object(struct tmpfs_object_s *to);
78beacf11bSopenharmony_cistatic void tmpfs_release_lockedobject(struct tmpfs_object_s *to);
79beacf11bSopenharmony_cistatic void tmpfs_release_lockedfile(struct tmpfs_file_s *tfo);
80beacf11bSopenharmony_cistatic struct tmpfs_dirent_s *tmpfs_find_dirent(struct tmpfs_directory_s *tdo,
81beacf11bSopenharmony_ci              const char *name);
82beacf11bSopenharmony_cistatic int  tmpfs_remove_dirent(struct tmpfs_directory_s *tdo,
83beacf11bSopenharmony_ci              struct tmpfs_object_s *to);
84beacf11bSopenharmony_cistatic int  tmpfs_add_dirent(struct tmpfs_directory_s **tdo,
85beacf11bSopenharmony_ci              struct tmpfs_object_s *to, const char *name);
86beacf11bSopenharmony_cistatic struct tmpfs_file_s *tmpfs_alloc_file(void);
87beacf11bSopenharmony_cistatic int tmpfs_create_file(struct tmpfs_s *fs,
88beacf11bSopenharmony_ci                             const char *relpath,
89beacf11bSopenharmony_ci                             struct tmpfs_directory_s *parent_input,
90beacf11bSopenharmony_ci                             struct tmpfs_file_s **tfo);
91beacf11bSopenharmony_ci
92beacf11bSopenharmony_cistatic struct tmpfs_directory_s *tmpfs_alloc_directory(void);
93beacf11bSopenharmony_cistatic int tmpfs_create_directory(struct tmpfs_s *fs,
94beacf11bSopenharmony_ci                                  const char *relpath,
95beacf11bSopenharmony_ci                                  struct tmpfs_directory_s *parent,
96beacf11bSopenharmony_ci                                  struct tmpfs_directory_s **tdo);
97beacf11bSopenharmony_ci
98beacf11bSopenharmony_cistatic int  tmpfs_find_object(struct tmpfs_s *fs,
99beacf11bSopenharmony_ci              const char *relpath, struct tmpfs_object_s **object,
100beacf11bSopenharmony_ci              struct tmpfs_directory_s **parent);
101beacf11bSopenharmony_cistatic int  tmpfs_find_file(struct tmpfs_s *fs,
102beacf11bSopenharmony_ci              const char *relpath,
103beacf11bSopenharmony_ci              struct tmpfs_file_s **tfo,
104beacf11bSopenharmony_ci              struct tmpfs_directory_s **parent);
105beacf11bSopenharmony_cistatic int  tmpfs_find_directory(struct tmpfs_s *fs,
106beacf11bSopenharmony_ci              const char *relpath,
107beacf11bSopenharmony_ci              struct tmpfs_directory_s **tdo,
108beacf11bSopenharmony_ci              struct tmpfs_directory_s **parent);
109beacf11bSopenharmony_ci
110beacf11bSopenharmony_ci/* File system operations */
111beacf11bSopenharmony_ci
112beacf11bSopenharmony_ciint tmpfs_close(struct file *filep);
113beacf11bSopenharmony_cioff_t tmpfs_seek(struct file *filep, off_t offset, int whence);
114beacf11bSopenharmony_ciint tmpfs_ioctl(struct file *filep, int cmd, unsigned long arg);
115beacf11bSopenharmony_ciint tmpfs_sync(struct file *filep);
116beacf11bSopenharmony_ciint tmpfs_closedir(struct Vnode *node, struct fs_dirent_s *dir);
117beacf11bSopenharmony_ciint tmpfs_rewinddir(struct Vnode *vp, struct fs_dirent_s *dir);
118beacf11bSopenharmony_ciint tmpfs_truncate(struct Vnode *vp, off_t len);
119beacf11bSopenharmony_ci
120beacf11bSopenharmony_ciint  tmpfs_mount(struct Mount *mnt, struct Vnode *device, const void *data);
121beacf11bSopenharmony_ciint  tmpfs_unmount(struct Mount *mnt, struct Vnode **blkdriver);
122beacf11bSopenharmony_ci
123beacf11bSopenharmony_ciint tmpfs_lookup(struct Vnode *parent, const char *name, int len, struct Vnode **vpp);
124beacf11bSopenharmony_cissize_t tmpfs_write(struct file *filep, const char *buffer, size_t buflen);
125beacf11bSopenharmony_cissize_t tmpfs_read(struct file *filep, char *buffer, size_t buflen);
126beacf11bSopenharmony_cissize_t tmpfs_readpage(struct Vnode *vnode, char *buffer, off_t off);
127beacf11bSopenharmony_ciint tmpfs_stat(struct Vnode *vp, struct stat *st);
128beacf11bSopenharmony_ciint tmpfs_opendir(struct Vnode *vp, struct fs_dirent_s *dir);
129beacf11bSopenharmony_ciint tmpfs_readdir(struct Vnode *vp, struct fs_dirent_s *dir);
130beacf11bSopenharmony_ciint tmpfs_rename(struct Vnode *oldVnode, struct Vnode *newParent, const char *oldname, const char *newname);
131beacf11bSopenharmony_ciint tmpfs_mkdir(struct Vnode *parent, const char *relpath, mode_t mode, struct Vnode **vpp);
132beacf11bSopenharmony_ciint tmpfs_create(struct Vnode *dvp, const char *path, int mode, struct Vnode **vpp);
133beacf11bSopenharmony_ciint tmpfs_unlink(struct Vnode *parent, struct Vnode *node, const char *relpath);
134beacf11bSopenharmony_ciint tmpfs_rmdir(struct Vnode *parent, struct Vnode *target, const char *dirname);
135beacf11bSopenharmony_ciint tmpfs_reclaim(struct Vnode *vp);
136beacf11bSopenharmony_ci
137beacf11bSopenharmony_ciint tmpfs_statfs(struct Mount *mp, struct statfs *sbp);
138beacf11bSopenharmony_ci
139beacf11bSopenharmony_cistatic void tmpfs_stat_common(struct tmpfs_object_s *to,
140beacf11bSopenharmony_ci                              struct stat *buf);
141beacf11bSopenharmony_ci
142beacf11bSopenharmony_ci/****************************************************************************
143beacf11bSopenharmony_ci * Public Data
144beacf11bSopenharmony_ci ****************************************************************************/
145beacf11bSopenharmony_ciconst struct MountOps tmpfs_operations = {
146beacf11bSopenharmony_ci    .Mount = tmpfs_mount,
147beacf11bSopenharmony_ci    .Unmount = tmpfs_unmount,
148beacf11bSopenharmony_ci    .Statfs = tmpfs_statfs,
149beacf11bSopenharmony_ci};
150beacf11bSopenharmony_ci
151beacf11bSopenharmony_cistruct VnodeOps tmpfs_vops = {
152beacf11bSopenharmony_ci    .Lookup = tmpfs_lookup,
153beacf11bSopenharmony_ci    .Getattr = tmpfs_stat,
154beacf11bSopenharmony_ci    .Opendir = tmpfs_opendir,
155beacf11bSopenharmony_ci    .Readdir = tmpfs_readdir,
156beacf11bSopenharmony_ci    .ReadPage = tmpfs_readpage,
157beacf11bSopenharmony_ci    .WritePage = NULL,
158beacf11bSopenharmony_ci    .Rename = tmpfs_rename,
159beacf11bSopenharmony_ci    .Mkdir = tmpfs_mkdir,
160beacf11bSopenharmony_ci    .Create = tmpfs_create,
161beacf11bSopenharmony_ci    .Unlink =  tmpfs_unlink,
162beacf11bSopenharmony_ci    .Rmdir = tmpfs_rmdir,
163beacf11bSopenharmony_ci    .Reclaim = tmpfs_reclaim,
164beacf11bSopenharmony_ci    .Closedir = tmpfs_closedir,
165beacf11bSopenharmony_ci    .Close = NULL,
166beacf11bSopenharmony_ci    .Rewinddir = tmpfs_rewinddir,
167beacf11bSopenharmony_ci    .Truncate = tmpfs_truncate,
168beacf11bSopenharmony_ci};
169beacf11bSopenharmony_ci
170beacf11bSopenharmony_cistruct file_operations_vfs tmpfs_fops = {
171beacf11bSopenharmony_ci    .seek = tmpfs_seek,
172beacf11bSopenharmony_ci    .write = tmpfs_write,
173beacf11bSopenharmony_ci    .read = tmpfs_read,
174beacf11bSopenharmony_ci    .ioctl = tmpfs_ioctl,
175beacf11bSopenharmony_ci    .mmap = OsVfsFileMmap,
176beacf11bSopenharmony_ci    .close = tmpfs_close,
177beacf11bSopenharmony_ci    .fsync = tmpfs_sync,
178beacf11bSopenharmony_ci};
179beacf11bSopenharmony_ci
180beacf11bSopenharmony_cistatic struct tmpfs_s tmpfs_superblock = {0};
181beacf11bSopenharmony_ci
182beacf11bSopenharmony_ci/****************************************************************************
183beacf11bSopenharmony_ci * Name: tmpfs_timestamp
184beacf11bSopenharmony_ci ****************************************************************************/
185beacf11bSopenharmony_ci
186beacf11bSopenharmony_cistatic time_t tmpfs_timestamp(void)
187beacf11bSopenharmony_ci{
188beacf11bSopenharmony_ci  struct timeval tv;
189beacf11bSopenharmony_ci
190beacf11bSopenharmony_ci  (void)gettimeofday(&tv, (struct timezone *)NULL);
191beacf11bSopenharmony_ci
192beacf11bSopenharmony_ci  return (time_t)(tv.tv_sec);
193beacf11bSopenharmony_ci}
194beacf11bSopenharmony_ci
195beacf11bSopenharmony_ci/****************************************************************************
196beacf11bSopenharmony_ci * Name: tmpfs_lock_reentrant
197beacf11bSopenharmony_ci ****************************************************************************/
198beacf11bSopenharmony_ci
199beacf11bSopenharmony_cistatic void tmpfs_lock_reentrant(struct tmpfs_sem_s *sem)
200beacf11bSopenharmony_ci{
201beacf11bSopenharmony_ci  pid_t me;
202beacf11bSopenharmony_ci
203beacf11bSopenharmony_ci  /* Do we already hold the semaphore? */
204beacf11bSopenharmony_ci
205beacf11bSopenharmony_ci  me = getpid();
206beacf11bSopenharmony_ci  if (me == sem->ts_holder)
207beacf11bSopenharmony_ci    {
208beacf11bSopenharmony_ci      /* Yes... just increment the count */
209beacf11bSopenharmony_ci
210beacf11bSopenharmony_ci      sem->ts_count++;
211beacf11bSopenharmony_ci      DEBUGASSERT(sem->ts_count > 0);
212beacf11bSopenharmony_ci    }
213beacf11bSopenharmony_ci
214beacf11bSopenharmony_ci  /* Take the semaphore (perhaps waiting) */
215beacf11bSopenharmony_ci
216beacf11bSopenharmony_ci  else
217beacf11bSopenharmony_ci    {
218beacf11bSopenharmony_ci      while (sem_wait(&sem->ts_sem) != 0)
219beacf11bSopenharmony_ci        {
220beacf11bSopenharmony_ci          /* The only case that an error should occur here is if the wait
221beacf11bSopenharmony_ci           * was awakened by a signal.
222beacf11bSopenharmony_ci           */
223beacf11bSopenharmony_ci
224beacf11bSopenharmony_ci          DEBUGASSERT(get_errno() == EINTR);
225beacf11bSopenharmony_ci        }
226beacf11bSopenharmony_ci
227beacf11bSopenharmony_ci      /* No we hold the semaphore */
228beacf11bSopenharmony_ci
229beacf11bSopenharmony_ci      sem->ts_holder = me;
230beacf11bSopenharmony_ci      sem->ts_count  = 1;
231beacf11bSopenharmony_ci    }
232beacf11bSopenharmony_ci}
233beacf11bSopenharmony_ci
234beacf11bSopenharmony_ci/****************************************************************************
235beacf11bSopenharmony_ci * Name: tmpfs_lock
236beacf11bSopenharmony_ci ****************************************************************************/
237beacf11bSopenharmony_ci
238beacf11bSopenharmony_cistatic void tmpfs_lock(struct tmpfs_s *fs)
239beacf11bSopenharmony_ci{
240beacf11bSopenharmony_ci  tmpfs_lock_reentrant(&fs->tfs_exclsem);
241beacf11bSopenharmony_ci}
242beacf11bSopenharmony_ci
243beacf11bSopenharmony_ci/****************************************************************************
244beacf11bSopenharmony_ci * Name: tmpfs_lock_object
245beacf11bSopenharmony_ci ****************************************************************************/
246beacf11bSopenharmony_ci
247beacf11bSopenharmony_cistatic void tmpfs_lock_object(struct tmpfs_object_s *to)
248beacf11bSopenharmony_ci{
249beacf11bSopenharmony_ci  tmpfs_lock_reentrant(&to->to_exclsem);
250beacf11bSopenharmony_ci}
251beacf11bSopenharmony_ci
252beacf11bSopenharmony_ci/****************************************************************************
253beacf11bSopenharmony_ci * Name: tmpfs_unlock_reentrant
254beacf11bSopenharmony_ci ****************************************************************************/
255beacf11bSopenharmony_ci
256beacf11bSopenharmony_cistatic void tmpfs_unlock_reentrant(struct tmpfs_sem_s *sem)
257beacf11bSopenharmony_ci{
258beacf11bSopenharmony_ci  DEBUGASSERT(sem->ts_holder == getpid());
259beacf11bSopenharmony_ci
260beacf11bSopenharmony_ci  /* Is this our last count on the semaphore? */
261beacf11bSopenharmony_ci
262beacf11bSopenharmony_ci  if (sem->ts_count > 1)
263beacf11bSopenharmony_ci    {
264beacf11bSopenharmony_ci      /* No.. just decrement the count */
265beacf11bSopenharmony_ci
266beacf11bSopenharmony_ci      sem->ts_count--;
267beacf11bSopenharmony_ci    }
268beacf11bSopenharmony_ci
269beacf11bSopenharmony_ci  /* Yes.. then we can really release the semaphore */
270beacf11bSopenharmony_ci
271beacf11bSopenharmony_ci  else
272beacf11bSopenharmony_ci    {
273beacf11bSopenharmony_ci      sem->ts_holder = TMPFS_NO_HOLDER;
274beacf11bSopenharmony_ci      sem->ts_count  = 0;
275beacf11bSopenharmony_ci      sem_post(&sem->ts_sem);
276beacf11bSopenharmony_ci    }
277beacf11bSopenharmony_ci}
278beacf11bSopenharmony_ci
279beacf11bSopenharmony_ci/****************************************************************************
280beacf11bSopenharmony_ci * Name: tmpfs_unlock
281beacf11bSopenharmony_ci ****************************************************************************/
282beacf11bSopenharmony_ci
283beacf11bSopenharmony_cistatic void tmpfs_unlock(struct tmpfs_s *fs)
284beacf11bSopenharmony_ci{
285beacf11bSopenharmony_ci  tmpfs_unlock_reentrant(&fs->tfs_exclsem);
286beacf11bSopenharmony_ci}
287beacf11bSopenharmony_ci
288beacf11bSopenharmony_ci/****************************************************************************
289beacf11bSopenharmony_ci * Name: tmpfs_unlock_object
290beacf11bSopenharmony_ci ****************************************************************************/
291beacf11bSopenharmony_ci
292beacf11bSopenharmony_cistatic void tmpfs_unlock_object(struct tmpfs_object_s *to)
293beacf11bSopenharmony_ci{
294beacf11bSopenharmony_ci  tmpfs_unlock_reentrant(&to->to_exclsem);
295beacf11bSopenharmony_ci}
296beacf11bSopenharmony_ci
297beacf11bSopenharmony_ci/****************************************************************************
298beacf11bSopenharmony_ci * Name: tmpfs_release_lockedobject
299beacf11bSopenharmony_ci ****************************************************************************/
300beacf11bSopenharmony_ci
301beacf11bSopenharmony_cistatic void tmpfs_release_lockedobject(struct tmpfs_object_s *to)
302beacf11bSopenharmony_ci{
303beacf11bSopenharmony_ci  DEBUGASSERT(to && to->to_refs > 0);
304beacf11bSopenharmony_ci
305beacf11bSopenharmony_ci  /* Is this a file object? */
306beacf11bSopenharmony_ci
307beacf11bSopenharmony_ci  if (to->to_type == TMPFS_REGULAR)
308beacf11bSopenharmony_ci    {
309beacf11bSopenharmony_ci      tmpfs_release_lockedfile((struct tmpfs_file_s *)to);
310beacf11bSopenharmony_ci    }
311beacf11bSopenharmony_ci  else
312beacf11bSopenharmony_ci    {
313beacf11bSopenharmony_ci      if(to->to_refs > 0)
314beacf11bSopenharmony_ci        {
315beacf11bSopenharmony_ci          to->to_refs--;
316beacf11bSopenharmony_ci        }
317beacf11bSopenharmony_ci      tmpfs_unlock_object(to);
318beacf11bSopenharmony_ci    }
319beacf11bSopenharmony_ci}
320beacf11bSopenharmony_ci
321beacf11bSopenharmony_ci/****************************************************************************
322beacf11bSopenharmony_ci * Name: tmpfs_release_lockedfile
323beacf11bSopenharmony_ci ****************************************************************************/
324beacf11bSopenharmony_ci
325beacf11bSopenharmony_cistatic void tmpfs_release_lockedfile(struct tmpfs_file_s *tfo)
326beacf11bSopenharmony_ci{
327beacf11bSopenharmony_ci  DEBUGASSERT(tfo && tfo->tfo_refs > 0);
328beacf11bSopenharmony_ci
329beacf11bSopenharmony_ci  /* If there are no longer any references to the file and the file has been
330beacf11bSopenharmony_ci   * unlinked from its parent directory, then free the file object now.
331beacf11bSopenharmony_ci   */
332beacf11bSopenharmony_ci
333beacf11bSopenharmony_ci  if (tfo->tfo_refs == 1 && (tfo->tfo_flags & TFO_FLAG_UNLINKED) != 0)
334beacf11bSopenharmony_ci    {
335beacf11bSopenharmony_ci      sem_destroy(&tfo->tfo_exclsem.ts_sem);
336beacf11bSopenharmony_ci      kmm_free(tfo->tfo_data);
337beacf11bSopenharmony_ci      kmm_free(tfo);
338beacf11bSopenharmony_ci    }
339beacf11bSopenharmony_ci
340beacf11bSopenharmony_ci  /* Otherwise, just decrement the reference count on the file object */
341beacf11bSopenharmony_ci
342beacf11bSopenharmony_ci  else
343beacf11bSopenharmony_ci    {
344beacf11bSopenharmony_ci      if(tfo->tfo_refs > 0)
345beacf11bSopenharmony_ci        {
346beacf11bSopenharmony_ci          tfo->tfo_refs--;
347beacf11bSopenharmony_ci        }
348beacf11bSopenharmony_ci      tmpfs_unlock_file(tfo);
349beacf11bSopenharmony_ci    }
350beacf11bSopenharmony_ci}
351beacf11bSopenharmony_ci
352beacf11bSopenharmony_ci/****************************************************************************
353beacf11bSopenharmony_ci * Name: tmpfs_find_dirent
354beacf11bSopenharmony_ci ****************************************************************************/
355beacf11bSopenharmony_ci
356beacf11bSopenharmony_cistatic struct tmpfs_dirent_s *tmpfs_find_dirent(struct tmpfs_directory_s *tdo,
357beacf11bSopenharmony_ci                                                const char *name)
358beacf11bSopenharmony_ci{
359beacf11bSopenharmony_ci  LOS_DL_LIST *node;
360beacf11bSopenharmony_ci  struct tmpfs_dirent_s *tde;
361beacf11bSopenharmony_ci
362beacf11bSopenharmony_ci  /* Search the list of directory entries for a match */
363beacf11bSopenharmony_ci
364beacf11bSopenharmony_ci  for (node = tdo->tdo_entry.pstNext; node != &tdo->tdo_entry; node = node->pstNext)
365beacf11bSopenharmony_ci    {
366beacf11bSopenharmony_ci      tde = (struct tmpfs_dirent_s *)node;
367beacf11bSopenharmony_ci      if (tde->tde_inuse == true && strcmp(tde->tde_name, name) == 0)
368beacf11bSopenharmony_ci        {
369beacf11bSopenharmony_ci          return tde;
370beacf11bSopenharmony_ci        }
371beacf11bSopenharmony_ci    }
372beacf11bSopenharmony_ci
373beacf11bSopenharmony_ci  /* Return NULL if not found */
374beacf11bSopenharmony_ci
375beacf11bSopenharmony_ci  return NULL;
376beacf11bSopenharmony_ci}
377beacf11bSopenharmony_ci
378beacf11bSopenharmony_ci/****************************************************************************
379beacf11bSopenharmony_ci * Name: tmpfs_remove_dirent
380beacf11bSopenharmony_ci ****************************************************************************/
381beacf11bSopenharmony_ci
382beacf11bSopenharmony_cistatic int tmpfs_remove_dirent(struct tmpfs_directory_s *tdo,
383beacf11bSopenharmony_ci                               struct tmpfs_object_s *to)
384beacf11bSopenharmony_ci{
385beacf11bSopenharmony_ci  struct tmpfs_dirent_s *tde;
386beacf11bSopenharmony_ci
387beacf11bSopenharmony_ci  /* Search the list of directory entries for a match */
388beacf11bSopenharmony_ci
389beacf11bSopenharmony_ci  tde = to->to_dirent;
390beacf11bSopenharmony_ci  if (tde == NULL)
391beacf11bSopenharmony_ci    {
392beacf11bSopenharmony_ci      return -ENONET;
393beacf11bSopenharmony_ci    }
394beacf11bSopenharmony_ci
395beacf11bSopenharmony_ci  /* Free the object name */
396beacf11bSopenharmony_ci
397beacf11bSopenharmony_ci  if (tde->tde_name != NULL)
398beacf11bSopenharmony_ci    {
399beacf11bSopenharmony_ci      kmm_free(tde->tde_name);
400beacf11bSopenharmony_ci      tde->tde_name = NULL;
401beacf11bSopenharmony_ci    }
402beacf11bSopenharmony_ci
403beacf11bSopenharmony_ci  if (tdo->tdo_count == 0)
404beacf11bSopenharmony_ci    {
405beacf11bSopenharmony_ci      LOS_ListDelete(&tde->tde_node);
406beacf11bSopenharmony_ci      kmm_free(tde);
407beacf11bSopenharmony_ci    }
408beacf11bSopenharmony_ci  else
409beacf11bSopenharmony_ci    {
410beacf11bSopenharmony_ci      tde->tde_inuse = false;
411beacf11bSopenharmony_ci      tde->tde_object = NULL;
412beacf11bSopenharmony_ci    }
413beacf11bSopenharmony_ci  if(tdo->tdo_nentries > 0)
414beacf11bSopenharmony_ci    {
415beacf11bSopenharmony_ci      tdo->tdo_nentries--;
416beacf11bSopenharmony_ci    }
417beacf11bSopenharmony_ci  return OK;
418beacf11bSopenharmony_ci}
419beacf11bSopenharmony_ci
420beacf11bSopenharmony_ci/****************************************************************************
421beacf11bSopenharmony_ci * Name: tmpfs_add_dirent
422beacf11bSopenharmony_ci ****************************************************************************/
423beacf11bSopenharmony_ci
424beacf11bSopenharmony_cistatic int tmpfs_add_dirent(struct tmpfs_directory_s **tdo,
425beacf11bSopenharmony_ci                            struct tmpfs_object_s *to,
426beacf11bSopenharmony_ci                            const char *name)
427beacf11bSopenharmony_ci{
428beacf11bSopenharmony_ci  struct tmpfs_directory_s *parent;
429beacf11bSopenharmony_ci  struct tmpfs_dirent_s *tde;
430beacf11bSopenharmony_ci  char *newname;
431beacf11bSopenharmony_ci
432beacf11bSopenharmony_ci  /* Copy the name string so that it will persist as long as the
433beacf11bSopenharmony_ci   * directory entry.
434beacf11bSopenharmony_ci   */
435beacf11bSopenharmony_ci
436beacf11bSopenharmony_ci  newname = strdup(name);
437beacf11bSopenharmony_ci  if (newname == NULL)
438beacf11bSopenharmony_ci    {
439beacf11bSopenharmony_ci      return -ENOSPC;
440beacf11bSopenharmony_ci    }
441beacf11bSopenharmony_ci
442beacf11bSopenharmony_ci  tde = (struct tmpfs_dirent_s *)malloc(sizeof(struct tmpfs_dirent_s));
443beacf11bSopenharmony_ci  if (tde == NULL)
444beacf11bSopenharmony_ci    {
445beacf11bSopenharmony_ci      free(newname);
446beacf11bSopenharmony_ci      return -ENOSPC;
447beacf11bSopenharmony_ci    }
448beacf11bSopenharmony_ci
449beacf11bSopenharmony_ci  tde->tde_object = to;
450beacf11bSopenharmony_ci  tde->tde_name   = newname;
451beacf11bSopenharmony_ci  tde->tde_inuse  = true;
452beacf11bSopenharmony_ci  to->to_dirent   = tde;
453beacf11bSopenharmony_ci
454beacf11bSopenharmony_ci  /* Save the new object info in the new directory entry */
455beacf11bSopenharmony_ci
456beacf11bSopenharmony_ci  parent = *tdo;
457beacf11bSopenharmony_ci  LOS_ListTailInsert(&parent->tdo_entry, &tde->tde_node);
458beacf11bSopenharmony_ci  parent->tdo_nentries++;
459beacf11bSopenharmony_ci
460beacf11bSopenharmony_ci  /* Update directory times */
461beacf11bSopenharmony_ci
462beacf11bSopenharmony_ci  parent->tdo_ctime = parent->tdo_mtime = tmpfs_timestamp();
463beacf11bSopenharmony_ci
464beacf11bSopenharmony_ci  return OK;
465beacf11bSopenharmony_ci}
466beacf11bSopenharmony_ci
467beacf11bSopenharmony_ci/****************************************************************************
468beacf11bSopenharmony_ci * Name: tmpfs_alloc_file
469beacf11bSopenharmony_ci ****************************************************************************/
470beacf11bSopenharmony_ci
471beacf11bSopenharmony_cistatic struct tmpfs_file_s *tmpfs_alloc_file(void)
472beacf11bSopenharmony_ci{
473beacf11bSopenharmony_ci  struct tmpfs_file_s *tfo;
474beacf11bSopenharmony_ci  size_t allocsize;
475beacf11bSopenharmony_ci
476beacf11bSopenharmony_ci  /* Create a new zero length file object */
477beacf11bSopenharmony_ci
478beacf11bSopenharmony_ci  allocsize = sizeof(struct tmpfs_file_s);
479beacf11bSopenharmony_ci  tfo = (struct tmpfs_file_s *)kmm_malloc(allocsize);
480beacf11bSopenharmony_ci  if (tfo == NULL)
481beacf11bSopenharmony_ci    {
482beacf11bSopenharmony_ci      return NULL;
483beacf11bSopenharmony_ci    }
484beacf11bSopenharmony_ci
485beacf11bSopenharmony_ci  /* Initialize the new file object.  NOTE that the initial state is
486beacf11bSopenharmony_ci   * locked with one reference count.
487beacf11bSopenharmony_ci   */
488beacf11bSopenharmony_ci
489beacf11bSopenharmony_ci  tfo->tfo_atime = tmpfs_timestamp();
490beacf11bSopenharmony_ci  tfo->tfo_mtime = tfo->tfo_atime;
491beacf11bSopenharmony_ci  tfo->tfo_ctime = tfo->tfo_atime;
492beacf11bSopenharmony_ci  tfo->tfo_type  = TMPFS_REGULAR;
493beacf11bSopenharmony_ci  tfo->tfo_refs  = 1;
494beacf11bSopenharmony_ci  tfo->tfo_flags = 0;
495beacf11bSopenharmony_ci  tfo->tfo_size  = 0;
496beacf11bSopenharmony_ci  tfo->tfo_data  = NULL;
497beacf11bSopenharmony_ci
498beacf11bSopenharmony_ci  tfo->tfo_exclsem.ts_holder = getpid();
499beacf11bSopenharmony_ci  tfo->tfo_exclsem.ts_count  = 1;
500beacf11bSopenharmony_ci  if (sem_init(&tfo->tfo_exclsem.ts_sem, 0, 0) != 0)
501beacf11bSopenharmony_ci    {
502beacf11bSopenharmony_ci      PRINT_ERR("%s %d, sem_init failed!\n", __FUNCTION__, __LINE__);
503beacf11bSopenharmony_ci      kmm_free(tfo);
504beacf11bSopenharmony_ci      return NULL;
505beacf11bSopenharmony_ci    }
506beacf11bSopenharmony_ci
507beacf11bSopenharmony_ci  return tfo;
508beacf11bSopenharmony_ci}
509beacf11bSopenharmony_ci
510beacf11bSopenharmony_ci/****************************************************************************
511beacf11bSopenharmony_ci * Name: tmpfs_create_file
512beacf11bSopenharmony_ci ****************************************************************************/
513beacf11bSopenharmony_ci
514beacf11bSopenharmony_cistatic int tmpfs_create_file(struct tmpfs_s *fs,
515beacf11bSopenharmony_ci                             const char *relpath,
516beacf11bSopenharmony_ci                             struct tmpfs_directory_s *parent_input,
517beacf11bSopenharmony_ci                             struct tmpfs_file_s **tfo)
518beacf11bSopenharmony_ci{
519beacf11bSopenharmony_ci  struct tmpfs_directory_s *parent;
520beacf11bSopenharmony_ci  struct tmpfs_file_s *newtfo;
521beacf11bSopenharmony_ci  struct tmpfs_dirent_s *tde;
522beacf11bSopenharmony_ci  char *copy;
523beacf11bSopenharmony_ci  int ret;
524beacf11bSopenharmony_ci
525beacf11bSopenharmony_ci  /* Duplicate the path variable so that we can modify it */
526beacf11bSopenharmony_ci
527beacf11bSopenharmony_ci  copy = strdup(relpath);
528beacf11bSopenharmony_ci  if (copy == NULL)
529beacf11bSopenharmony_ci    {
530beacf11bSopenharmony_ci      return -ENOSPC;
531beacf11bSopenharmony_ci    }
532beacf11bSopenharmony_ci
533beacf11bSopenharmony_ci  /* Separate the path into the file name and the path to the parent
534beacf11bSopenharmony_ci   * directory.
535beacf11bSopenharmony_ci   */
536beacf11bSopenharmony_ci  if (parent_input == NULL)
537beacf11bSopenharmony_ci    {
538beacf11bSopenharmony_ci      /* No subdirectories... use the root directory */
539beacf11bSopenharmony_ci      parent = (struct tmpfs_directory_s *)fs->tfs_root.tde_object;
540beacf11bSopenharmony_ci    }
541beacf11bSopenharmony_ci  else
542beacf11bSopenharmony_ci    {
543beacf11bSopenharmony_ci      parent = parent_input;
544beacf11bSopenharmony_ci    }
545beacf11bSopenharmony_ci  if (parent == NULL)
546beacf11bSopenharmony_ci    {
547beacf11bSopenharmony_ci      ret = -EEXIST;
548beacf11bSopenharmony_ci      goto errout_with_copy;
549beacf11bSopenharmony_ci    }
550beacf11bSopenharmony_ci  tmpfs_lock_directory(parent);
551beacf11bSopenharmony_ci  parent->tdo_refs++;
552beacf11bSopenharmony_ci
553beacf11bSopenharmony_ci  /* Verify that no object of this name already exists in the directory */
554beacf11bSopenharmony_ci  tde = tmpfs_find_dirent(parent, copy);
555beacf11bSopenharmony_ci  if (tde != NULL)
556beacf11bSopenharmony_ci    {
557beacf11bSopenharmony_ci      /* Something with this name already exists in the directory.
558beacf11bSopenharmony_ci       * OR perhaps some fatal error occurred.
559beacf11bSopenharmony_ci       */
560beacf11bSopenharmony_ci
561beacf11bSopenharmony_ci      ret = -EEXIST;
562beacf11bSopenharmony_ci      goto errout_with_parent;
563beacf11bSopenharmony_ci    }
564beacf11bSopenharmony_ci
565beacf11bSopenharmony_ci  /* Allocate an empty file.  The initial state of the file is locked with one
566beacf11bSopenharmony_ci   * reference count.
567beacf11bSopenharmony_ci   */
568beacf11bSopenharmony_ci
569beacf11bSopenharmony_ci  newtfo = tmpfs_alloc_file();
570beacf11bSopenharmony_ci  if (newtfo == NULL)
571beacf11bSopenharmony_ci    {
572beacf11bSopenharmony_ci      ret = -ENOSPC;
573beacf11bSopenharmony_ci      goto errout_with_parent;
574beacf11bSopenharmony_ci    }
575beacf11bSopenharmony_ci
576beacf11bSopenharmony_ci  /* Then add the new, empty file to the directory */
577beacf11bSopenharmony_ci
578beacf11bSopenharmony_ci  ret = tmpfs_add_dirent(&parent, (struct tmpfs_object_s *)newtfo, copy);
579beacf11bSopenharmony_ci  if (ret < 0)
580beacf11bSopenharmony_ci    {
581beacf11bSopenharmony_ci      goto errout_with_file;
582beacf11bSopenharmony_ci    }
583beacf11bSopenharmony_ci
584beacf11bSopenharmony_ci  /* Release the reference and lock on the parent directory */
585beacf11bSopenharmony_ci  if (parent->tdo_refs > 0)
586beacf11bSopenharmony_ci    {
587beacf11bSopenharmony_ci      parent->tdo_refs--;
588beacf11bSopenharmony_ci    }
589beacf11bSopenharmony_ci  tmpfs_unlock_directory(parent);
590beacf11bSopenharmony_ci
591beacf11bSopenharmony_ci  /* Free the copy of the relpath and return success */
592beacf11bSopenharmony_ci
593beacf11bSopenharmony_ci  kmm_free(copy);
594beacf11bSopenharmony_ci  *tfo = newtfo;
595beacf11bSopenharmony_ci  return OK;
596beacf11bSopenharmony_ci
597beacf11bSopenharmony_ci  /* Error exits */
598beacf11bSopenharmony_ci
599beacf11bSopenharmony_cierrout_with_file:
600beacf11bSopenharmony_ci  sem_destroy(&newtfo->tfo_exclsem.ts_sem);
601beacf11bSopenharmony_ci  kmm_free(newtfo);
602beacf11bSopenharmony_ci
603beacf11bSopenharmony_cierrout_with_parent:
604beacf11bSopenharmony_ci  if (parent->tdo_refs > 0)
605beacf11bSopenharmony_ci  {
606beacf11bSopenharmony_ci    parent->tdo_refs--;
607beacf11bSopenharmony_ci  }
608beacf11bSopenharmony_ci  tmpfs_unlock_directory(parent);
609beacf11bSopenharmony_ci
610beacf11bSopenharmony_cierrout_with_copy:
611beacf11bSopenharmony_ci  kmm_free(copy);
612beacf11bSopenharmony_ci  return ret;
613beacf11bSopenharmony_ci}
614beacf11bSopenharmony_ci
615beacf11bSopenharmony_ci/****************************************************************************
616beacf11bSopenharmony_ci * Name: tmpfs_alloc_directory
617beacf11bSopenharmony_ci ****************************************************************************/
618beacf11bSopenharmony_ci
619beacf11bSopenharmony_cistatic struct tmpfs_directory_s *tmpfs_alloc_directory(void)
620beacf11bSopenharmony_ci{
621beacf11bSopenharmony_ci  struct tmpfs_directory_s *tdo;
622beacf11bSopenharmony_ci  size_t allocsize;
623beacf11bSopenharmony_ci
624beacf11bSopenharmony_ci  allocsize = sizeof(struct tmpfs_directory_s);
625beacf11bSopenharmony_ci  tdo = (struct tmpfs_directory_s *)kmm_malloc(allocsize);
626beacf11bSopenharmony_ci  if (tdo == NULL)
627beacf11bSopenharmony_ci    {
628beacf11bSopenharmony_ci      return NULL;
629beacf11bSopenharmony_ci    }
630beacf11bSopenharmony_ci
631beacf11bSopenharmony_ci  /* Initialize the new directory object */
632beacf11bSopenharmony_ci
633beacf11bSopenharmony_ci  tdo->tdo_atime    = tmpfs_timestamp();
634beacf11bSopenharmony_ci  tdo->tdo_mtime    = tdo->tdo_mtime;
635beacf11bSopenharmony_ci  tdo->tdo_ctime    =  tdo->tdo_mtime;
636beacf11bSopenharmony_ci  tdo->tdo_type     = TMPFS_DIRECTORY;
637beacf11bSopenharmony_ci  tdo->tdo_refs     = 0;
638beacf11bSopenharmony_ci  tdo->tdo_nentries = 0;
639beacf11bSopenharmony_ci  tdo->tdo_count    = 0;
640beacf11bSopenharmony_ci  LOS_ListInit(&tdo->tdo_entry);
641beacf11bSopenharmony_ci
642beacf11bSopenharmony_ci  tdo->tdo_exclsem.ts_holder = TMPFS_NO_HOLDER;
643beacf11bSopenharmony_ci  tdo->tdo_exclsem.ts_count  = 0;
644beacf11bSopenharmony_ci  if (sem_init(&tdo->tdo_exclsem.ts_sem, 0, 1) != 0)
645beacf11bSopenharmony_ci    {
646beacf11bSopenharmony_ci      PRINT_ERR("%s %d, sem_init failed!\n", __FUNCTION__, __LINE__);
647beacf11bSopenharmony_ci      kmm_free(tdo);
648beacf11bSopenharmony_ci      return NULL;
649beacf11bSopenharmony_ci    }
650beacf11bSopenharmony_ci  return tdo;
651beacf11bSopenharmony_ci}
652beacf11bSopenharmony_ci
653beacf11bSopenharmony_ci/****************************************************************************
654beacf11bSopenharmony_ci * Name: tmpfs_create_directory
655beacf11bSopenharmony_ci ****************************************************************************/
656beacf11bSopenharmony_ci
657beacf11bSopenharmony_cistatic int tmpfs_create_directory(struct tmpfs_s *fs,
658beacf11bSopenharmony_ci                                  const char *relpath,
659beacf11bSopenharmony_ci                                  struct tmpfs_directory_s *parent_input,
660beacf11bSopenharmony_ci                                  struct tmpfs_directory_s **tdo)
661beacf11bSopenharmony_ci{
662beacf11bSopenharmony_ci  struct tmpfs_directory_s *parent;
663beacf11bSopenharmony_ci  struct tmpfs_directory_s *newtdo;
664beacf11bSopenharmony_ci  struct tmpfs_dirent_s *tde;
665beacf11bSopenharmony_ci  char *copy;
666beacf11bSopenharmony_ci  int ret;
667beacf11bSopenharmony_ci
668beacf11bSopenharmony_ci  /* Duplicate the path variable so that we can modify it */
669beacf11bSopenharmony_ci
670beacf11bSopenharmony_ci  copy = strdup(relpath);
671beacf11bSopenharmony_ci  if (copy == NULL)
672beacf11bSopenharmony_ci    {
673beacf11bSopenharmony_ci      return -ENOSPC;
674beacf11bSopenharmony_ci    }
675beacf11bSopenharmony_ci
676beacf11bSopenharmony_ci  /* Separate the path into the file name and the path to the parent
677beacf11bSopenharmony_ci   * directory.
678beacf11bSopenharmony_ci   */
679beacf11bSopenharmony_ci  if (parent_input == NULL)
680beacf11bSopenharmony_ci    {
681beacf11bSopenharmony_ci      /* No subdirectories... use the root directory */
682beacf11bSopenharmony_ci
683beacf11bSopenharmony_ci      parent = (struct tmpfs_directory_s *)fs->tfs_root.tde_object;
684beacf11bSopenharmony_ci    }
685beacf11bSopenharmony_ci  else
686beacf11bSopenharmony_ci    {
687beacf11bSopenharmony_ci      parent = parent_input;
688beacf11bSopenharmony_ci    }
689beacf11bSopenharmony_ci
690beacf11bSopenharmony_ci  /* Verify that no object of this name already exists in the directory */
691beacf11bSopenharmony_ci  if (parent == NULL)
692beacf11bSopenharmony_ci    {
693beacf11bSopenharmony_ci      ret = -EEXIST;
694beacf11bSopenharmony_ci      goto errout_with_copy;
695beacf11bSopenharmony_ci    }
696beacf11bSopenharmony_ci  tmpfs_lock_directory(parent);
697beacf11bSopenharmony_ci  parent->tdo_refs++;
698beacf11bSopenharmony_ci  tde = tmpfs_find_dirent(parent, copy);
699beacf11bSopenharmony_ci  if (tde != NULL)
700beacf11bSopenharmony_ci    {
701beacf11bSopenharmony_ci      /* Something with this name already exists in the directory.
702beacf11bSopenharmony_ci       * OR perhaps some fatal error occurred.
703beacf11bSopenharmony_ci       */
704beacf11bSopenharmony_ci
705beacf11bSopenharmony_ci      ret = -EEXIST;
706beacf11bSopenharmony_ci
707beacf11bSopenharmony_ci      goto errout_with_parent;
708beacf11bSopenharmony_ci    }
709beacf11bSopenharmony_ci
710beacf11bSopenharmony_ci  /* Allocate an empty directory object.  NOTE that there is no reference on
711beacf11bSopenharmony_ci   * the new directory and the object is not locked.
712beacf11bSopenharmony_ci   */
713beacf11bSopenharmony_ci
714beacf11bSopenharmony_ci  newtdo = tmpfs_alloc_directory();
715beacf11bSopenharmony_ci  if (newtdo == NULL)
716beacf11bSopenharmony_ci    {
717beacf11bSopenharmony_ci      ret = -ENOSPC;
718beacf11bSopenharmony_ci      goto errout_with_parent;
719beacf11bSopenharmony_ci    }
720beacf11bSopenharmony_ci
721beacf11bSopenharmony_ci  /* Then add the new, empty file to the directory */
722beacf11bSopenharmony_ci
723beacf11bSopenharmony_ci  ret = tmpfs_add_dirent(&parent, (struct tmpfs_object_s *)newtdo, copy);
724beacf11bSopenharmony_ci  if (ret < 0)
725beacf11bSopenharmony_ci    {
726beacf11bSopenharmony_ci      goto errout_with_directory;
727beacf11bSopenharmony_ci    }
728beacf11bSopenharmony_ci
729beacf11bSopenharmony_ci  /* Free the copy of the relpath, release our reference to the parent directory,
730beacf11bSopenharmony_ci   * and return success
731beacf11bSopenharmony_ci   */
732beacf11bSopenharmony_ci  if (parent->tdo_refs > 0)
733beacf11bSopenharmony_ci    {
734beacf11bSopenharmony_ci      parent->tdo_refs--;
735beacf11bSopenharmony_ci    }
736beacf11bSopenharmony_ci  tmpfs_unlock_directory(parent);
737beacf11bSopenharmony_ci  kmm_free(copy);
738beacf11bSopenharmony_ci
739beacf11bSopenharmony_ci  /* Return the (unlocked, unreferenced) directory object to the caller */
740beacf11bSopenharmony_ci
741beacf11bSopenharmony_ci  if (tdo != NULL)
742beacf11bSopenharmony_ci    {
743beacf11bSopenharmony_ci      *tdo = newtdo;
744beacf11bSopenharmony_ci    }
745beacf11bSopenharmony_ci
746beacf11bSopenharmony_ci  return OK;
747beacf11bSopenharmony_ci
748beacf11bSopenharmony_ci  /* Error exits */
749beacf11bSopenharmony_ci
750beacf11bSopenharmony_cierrout_with_directory:
751beacf11bSopenharmony_ci  sem_destroy(&newtdo->tdo_exclsem.ts_sem);
752beacf11bSopenharmony_ci  kmm_free(newtdo);
753beacf11bSopenharmony_ci
754beacf11bSopenharmony_cierrout_with_parent:
755beacf11bSopenharmony_ci  if (parent->tdo_refs > 0)
756beacf11bSopenharmony_ci    {
757beacf11bSopenharmony_ci      parent->tdo_refs--;
758beacf11bSopenharmony_ci    }
759beacf11bSopenharmony_ci  tmpfs_unlock_directory(parent);
760beacf11bSopenharmony_ci
761beacf11bSopenharmony_cierrout_with_copy:
762beacf11bSopenharmony_ci  kmm_free(copy);
763beacf11bSopenharmony_ci  return ret;
764beacf11bSopenharmony_ci}
765beacf11bSopenharmony_ci
766beacf11bSopenharmony_ci/****************************************************************************
767beacf11bSopenharmony_ci * Name: tmpfs_find_object
768beacf11bSopenharmony_ci ****************************************************************************/
769beacf11bSopenharmony_ci
770beacf11bSopenharmony_cistatic int tmpfs_find_object(struct tmpfs_s *fs,
771beacf11bSopenharmony_ci                             const char *relpath,
772beacf11bSopenharmony_ci                             struct tmpfs_object_s **object,
773beacf11bSopenharmony_ci                             struct tmpfs_directory_s **parent)
774beacf11bSopenharmony_ci{
775beacf11bSopenharmony_ci  struct tmpfs_object_s *to = NULL;
776beacf11bSopenharmony_ci  struct tmpfs_dirent_s *tde;
777beacf11bSopenharmony_ci  struct tmpfs_directory_s *tdo = NULL;
778beacf11bSopenharmony_ci  struct tmpfs_directory_s *next_tdo;
779beacf11bSopenharmony_ci  char *segment;
780beacf11bSopenharmony_ci  char *next_segment;
781beacf11bSopenharmony_ci  char *tkptr;
782beacf11bSopenharmony_ci  char *copy;
783beacf11bSopenharmony_ci
784beacf11bSopenharmony_ci  /* Make a copy of the path (so that we can modify it via strtok) */
785beacf11bSopenharmony_ci
786beacf11bSopenharmony_ci  copy = strdup(relpath);
787beacf11bSopenharmony_ci  if (copy == NULL)
788beacf11bSopenharmony_ci    {
789beacf11bSopenharmony_ci      return -ENOSPC;
790beacf11bSopenharmony_ci    }
791beacf11bSopenharmony_ci
792beacf11bSopenharmony_ci  /* Traverse the file system for any object with the matching name */
793beacf11bSopenharmony_ci
794beacf11bSopenharmony_ci  to       = fs->tfs_root.tde_object;
795beacf11bSopenharmony_ci  next_tdo = (struct tmpfs_directory_s *)fs->tfs_root.tde_object;
796beacf11bSopenharmony_ci  tdo      = next_tdo;
797beacf11bSopenharmony_ci  for (segment =  strtok_r(copy, "/", &tkptr);
798beacf11bSopenharmony_ci       segment != NULL;
799beacf11bSopenharmony_ci       segment = next_segment)
800beacf11bSopenharmony_ci    {
801beacf11bSopenharmony_ci      /* Get the next segment after the one we are currently working on.
802beacf11bSopenharmony_ci       * This will be NULL is we are working on the final segment of the
803beacf11bSopenharmony_ci       * relpath.
804beacf11bSopenharmony_ci       */
805beacf11bSopenharmony_ci
806beacf11bSopenharmony_ci      next_segment = strtok_r(NULL, "/", &tkptr);
807beacf11bSopenharmony_ci
808beacf11bSopenharmony_ci      /* Search the next directory. */
809beacf11bSopenharmony_ci
810beacf11bSopenharmony_ci      tdo = next_tdo;
811beacf11bSopenharmony_ci
812beacf11bSopenharmony_ci      /* Find the TMPFS object with the next segment name in the current
813beacf11bSopenharmony_ci       * directory.
814beacf11bSopenharmony_ci       */
815beacf11bSopenharmony_ci
816beacf11bSopenharmony_ci      tde = tmpfs_find_dirent(tdo, segment);
817beacf11bSopenharmony_ci      if (tde == NULL)
818beacf11bSopenharmony_ci        {
819beacf11bSopenharmony_ci          /* No object with this name exists in the directory. */
820beacf11bSopenharmony_ci
821beacf11bSopenharmony_ci          kmm_free(copy);
822beacf11bSopenharmony_ci          return -ENOENT;
823beacf11bSopenharmony_ci        }
824beacf11bSopenharmony_ci
825beacf11bSopenharmony_ci      to = tde->tde_object;
826beacf11bSopenharmony_ci
827beacf11bSopenharmony_ci      /* Is this object another directory? */
828beacf11bSopenharmony_ci
829beacf11bSopenharmony_ci      if (to->to_type != TMPFS_DIRECTORY)
830beacf11bSopenharmony_ci        {
831beacf11bSopenharmony_ci          /* No.  Was this the final segment in the path? */
832beacf11bSopenharmony_ci
833beacf11bSopenharmony_ci          if (next_segment == NULL)
834beacf11bSopenharmony_ci            {
835beacf11bSopenharmony_ci              /* Then we can break out of the loop now */
836beacf11bSopenharmony_ci
837beacf11bSopenharmony_ci               break;
838beacf11bSopenharmony_ci            }
839beacf11bSopenharmony_ci
840beacf11bSopenharmony_ci          /* No, this was not the final segement of the relpath.
841beacf11bSopenharmony_ci           * We cannot continue the search if any of the intermediate
842beacf11bSopenharmony_ci           * segments do no correspond to directories.
843beacf11bSopenharmony_ci           */
844beacf11bSopenharmony_ci
845beacf11bSopenharmony_ci          kmm_free(copy);
846beacf11bSopenharmony_ci          return -ENOTDIR;
847beacf11bSopenharmony_ci        }
848beacf11bSopenharmony_ci
849beacf11bSopenharmony_ci      /* Search this directory for the next segement.  If we
850beacf11bSopenharmony_ci       * exit the loop, tdo will still refer to the parent
851beacf11bSopenharmony_ci       * directory of to.
852beacf11bSopenharmony_ci       */
853beacf11bSopenharmony_ci
854beacf11bSopenharmony_ci      next_tdo = (struct tmpfs_directory_s *)to;
855beacf11bSopenharmony_ci    }
856beacf11bSopenharmony_ci
857beacf11bSopenharmony_ci  /* When we exit this loop (successfully), to will point to the TMPFS
858beacf11bSopenharmony_ci   * object associated with the terminal segment of the relpath.
859beacf11bSopenharmony_ci   * Increment the reference count on the located object.
860beacf11bSopenharmony_ci   */
861beacf11bSopenharmony_ci
862beacf11bSopenharmony_ci  /* Free the dup'ed string */
863beacf11bSopenharmony_ci
864beacf11bSopenharmony_ci  kmm_free(copy);
865beacf11bSopenharmony_ci
866beacf11bSopenharmony_ci  /* Return what we found */
867beacf11bSopenharmony_ci
868beacf11bSopenharmony_ci  if (parent)
869beacf11bSopenharmony_ci    {
870beacf11bSopenharmony_ci      if (tdo != NULL)
871beacf11bSopenharmony_ci        {
872beacf11bSopenharmony_ci          /* Get exclusive access to the parent and increment the reference
873beacf11bSopenharmony_ci           * count on the object.
874beacf11bSopenharmony_ci           */
875beacf11bSopenharmony_ci
876beacf11bSopenharmony_ci          tmpfs_lock_directory(tdo);
877beacf11bSopenharmony_ci          tdo->tdo_refs++;
878beacf11bSopenharmony_ci        }
879beacf11bSopenharmony_ci
880beacf11bSopenharmony_ci      *parent = tdo;
881beacf11bSopenharmony_ci    }
882beacf11bSopenharmony_ci
883beacf11bSopenharmony_ci  if (object)
884beacf11bSopenharmony_ci    {
885beacf11bSopenharmony_ci      if (to != NULL)
886beacf11bSopenharmony_ci        {
887beacf11bSopenharmony_ci          /* Get exclusive access to the object and increment the reference
888beacf11bSopenharmony_ci           * count on the object.
889beacf11bSopenharmony_ci           */
890beacf11bSopenharmony_ci
891beacf11bSopenharmony_ci          tmpfs_lock_object(to);
892beacf11bSopenharmony_ci          to->to_refs++;
893beacf11bSopenharmony_ci        }
894beacf11bSopenharmony_ci
895beacf11bSopenharmony_ci      *object = to;
896beacf11bSopenharmony_ci    }
897beacf11bSopenharmony_ci
898beacf11bSopenharmony_ci  return OK;
899beacf11bSopenharmony_ci}
900beacf11bSopenharmony_ci
901beacf11bSopenharmony_ci/****************************************************************************
902beacf11bSopenharmony_ci * Name: tmpfs_find_file
903beacf11bSopenharmony_ci ****************************************************************************/
904beacf11bSopenharmony_ci
905beacf11bSopenharmony_cistatic int tmpfs_find_file(struct tmpfs_s *fs,
906beacf11bSopenharmony_ci                           const char *relpath,
907beacf11bSopenharmony_ci                           struct tmpfs_file_s **tfo,
908beacf11bSopenharmony_ci                           struct tmpfs_directory_s **parent)
909beacf11bSopenharmony_ci{
910beacf11bSopenharmony_ci  struct tmpfs_object_s *to;
911beacf11bSopenharmony_ci  int ret;
912beacf11bSopenharmony_ci
913beacf11bSopenharmony_ci  /* Find the object at this path.  If successful, tmpfs_find_object() will
914beacf11bSopenharmony_ci   * lock both the object and the parent directory and will increment the
915beacf11bSopenharmony_ci   * reference count on both.
916beacf11bSopenharmony_ci   */
917beacf11bSopenharmony_ci
918beacf11bSopenharmony_ci  ret = tmpfs_find_object(fs, relpath, &to, parent);
919beacf11bSopenharmony_ci  if (ret >= 0)
920beacf11bSopenharmony_ci    {
921beacf11bSopenharmony_ci      /* We found it... but is it a regular file? */
922beacf11bSopenharmony_ci
923beacf11bSopenharmony_ci      if (to->to_type != TMPFS_REGULAR)
924beacf11bSopenharmony_ci        {
925beacf11bSopenharmony_ci          /* No... unlock the object and its parent and return an error */
926beacf11bSopenharmony_ci
927beacf11bSopenharmony_ci          tmpfs_release_lockedobject(to);
928beacf11bSopenharmony_ci
929beacf11bSopenharmony_ci          if (parent)
930beacf11bSopenharmony_ci            {
931beacf11bSopenharmony_ci              struct tmpfs_directory_s *tdo = *parent;
932beacf11bSopenharmony_ci
933beacf11bSopenharmony_ci              tdo->tdo_refs--;
934beacf11bSopenharmony_ci              tmpfs_unlock_directory(tdo);
935beacf11bSopenharmony_ci            }
936beacf11bSopenharmony_ci
937beacf11bSopenharmony_ci          ret = -EISDIR;
938beacf11bSopenharmony_ci        }
939beacf11bSopenharmony_ci
940beacf11bSopenharmony_ci      /* Return the verified file object */
941beacf11bSopenharmony_ci
942beacf11bSopenharmony_ci      *tfo = (struct tmpfs_file_s *)to;
943beacf11bSopenharmony_ci    }
944beacf11bSopenharmony_ci
945beacf11bSopenharmony_ci  return ret;
946beacf11bSopenharmony_ci}
947beacf11bSopenharmony_ci
948beacf11bSopenharmony_ci/****************************************************************************
949beacf11bSopenharmony_ci * Name: tmpfs_find_directory
950beacf11bSopenharmony_ci ****************************************************************************/
951beacf11bSopenharmony_ci
952beacf11bSopenharmony_cistatic int tmpfs_find_directory(struct tmpfs_s *fs,
953beacf11bSopenharmony_ci                           const char *relpath,
954beacf11bSopenharmony_ci                           struct tmpfs_directory_s **tdo,
955beacf11bSopenharmony_ci                           struct tmpfs_directory_s **parent)
956beacf11bSopenharmony_ci{
957beacf11bSopenharmony_ci  struct tmpfs_object_s *to;
958beacf11bSopenharmony_ci  int ret;
959beacf11bSopenharmony_ci
960beacf11bSopenharmony_ci  /* Find the object at this path */
961beacf11bSopenharmony_ci
962beacf11bSopenharmony_ci  ret = tmpfs_find_object(fs, relpath, &to, parent);
963beacf11bSopenharmony_ci  if (ret >= 0)
964beacf11bSopenharmony_ci    {
965beacf11bSopenharmony_ci      /* We found it... but is it a regular file? */
966beacf11bSopenharmony_ci
967beacf11bSopenharmony_ci      if (to->to_type != TMPFS_DIRECTORY)
968beacf11bSopenharmony_ci        {
969beacf11bSopenharmony_ci          /* No... unlock the object and its parent and return an error */
970beacf11bSopenharmony_ci
971beacf11bSopenharmony_ci          tmpfs_release_lockedobject(to);
972beacf11bSopenharmony_ci
973beacf11bSopenharmony_ci          if (parent)
974beacf11bSopenharmony_ci            {
975beacf11bSopenharmony_ci              struct tmpfs_directory_s *tmptdo = *parent;
976beacf11bSopenharmony_ci
977beacf11bSopenharmony_ci              tmptdo->tdo_refs--;
978beacf11bSopenharmony_ci              tmpfs_unlock_directory(tmptdo);
979beacf11bSopenharmony_ci            }
980beacf11bSopenharmony_ci
981beacf11bSopenharmony_ci          ret = -ENOTDIR;
982beacf11bSopenharmony_ci        }
983beacf11bSopenharmony_ci
984beacf11bSopenharmony_ci      /* Return the verified file object */
985beacf11bSopenharmony_ci
986beacf11bSopenharmony_ci      *tdo = (struct tmpfs_directory_s *)to;
987beacf11bSopenharmony_ci    }
988beacf11bSopenharmony_ci
989beacf11bSopenharmony_ci  return ret;
990beacf11bSopenharmony_ci}
991beacf11bSopenharmony_ci
992beacf11bSopenharmony_ci/****************************************************************************
993beacf11bSopenharmony_ci * Name: tmpfs_close
994beacf11bSopenharmony_ci ****************************************************************************/
995beacf11bSopenharmony_ci
996beacf11bSopenharmony_ciint tmpfs_close(struct file *filep)
997beacf11bSopenharmony_ci{
998beacf11bSopenharmony_ci  struct tmpfs_file_s *tfo;
999beacf11bSopenharmony_ci
1000beacf11bSopenharmony_ci  DEBUGASSERT(filep != NULL);
1001beacf11bSopenharmony_ci
1002beacf11bSopenharmony_ci  /* Recover our private data from the struct file instance */
1003beacf11bSopenharmony_ci  tfo = (struct tmpfs_file_s *)(filep->f_vnode->data);
1004beacf11bSopenharmony_ci  if (tfo == NULL)
1005beacf11bSopenharmony_ci    {
1006beacf11bSopenharmony_ci      return -EINVAL;
1007beacf11bSopenharmony_ci    }
1008beacf11bSopenharmony_ci  /* Get exclusive access to the file */
1009beacf11bSopenharmony_ci
1010beacf11bSopenharmony_ci  tmpfs_lock_file(tfo);
1011beacf11bSopenharmony_ci
1012beacf11bSopenharmony_ci  /* Decrement the reference count on the file */
1013beacf11bSopenharmony_ci
1014beacf11bSopenharmony_ci  if (tfo->tfo_refs > 0)
1015beacf11bSopenharmony_ci    {
1016beacf11bSopenharmony_ci      tfo->tfo_refs--;
1017beacf11bSopenharmony_ci    }
1018beacf11bSopenharmony_ci
1019beacf11bSopenharmony_ci  /* If the reference count decremented to zero and the file has been
1020beacf11bSopenharmony_ci   * unlinked, then free the file allocation now.
1021beacf11bSopenharmony_ci   */
1022beacf11bSopenharmony_ci
1023beacf11bSopenharmony_ci  if (tfo->tfo_refs == 0 && (tfo->tfo_flags & TFO_FLAG_UNLINKED) != 0)
1024beacf11bSopenharmony_ci    {
1025beacf11bSopenharmony_ci      /* Free the file object while we hold the lock?  Weird but this
1026beacf11bSopenharmony_ci       * should be safe because the object is unlinked and could not
1027beacf11bSopenharmony_ci       * have any other references.
1028beacf11bSopenharmony_ci       */
1029beacf11bSopenharmony_ci
1030beacf11bSopenharmony_ci      (void)sem_destroy(&tfo->tfo_exclsem.ts_sem);
1031beacf11bSopenharmony_ci      kmm_free(tfo->tfo_data);
1032beacf11bSopenharmony_ci      kmm_free(tfo);
1033beacf11bSopenharmony_ci      return OK;
1034beacf11bSopenharmony_ci    }
1035beacf11bSopenharmony_ci
1036beacf11bSopenharmony_ci  /* Release the lock on the file */
1037beacf11bSopenharmony_ci
1038beacf11bSopenharmony_ci  tmpfs_unlock_file(tfo);
1039beacf11bSopenharmony_ci  return OK;
1040beacf11bSopenharmony_ci}
1041beacf11bSopenharmony_ci
1042beacf11bSopenharmony_ci/****************************************************************************
1043beacf11bSopenharmony_ci * Name: tmpfs_read
1044beacf11bSopenharmony_ci ****************************************************************************/
1045beacf11bSopenharmony_ci
1046beacf11bSopenharmony_cissize_t tmpfs_read(struct file *filep, char *buffer, size_t buflen)
1047beacf11bSopenharmony_ci{
1048beacf11bSopenharmony_ci  struct tmpfs_file_s *tfo;
1049beacf11bSopenharmony_ci  ssize_t nread;
1050beacf11bSopenharmony_ci  loff_t startpos;
1051beacf11bSopenharmony_ci  loff_t endpos;
1052beacf11bSopenharmony_ci
1053beacf11bSopenharmony_ci  DEBUGASSERT(filep->f_vnode != NULL);
1054beacf11bSopenharmony_ci
1055beacf11bSopenharmony_ci  /* Recover our private data from the struct file instance */
1056beacf11bSopenharmony_ci
1057beacf11bSopenharmony_ci  tfo = (struct tmpfs_file_s *)(filep->f_vnode->data);
1058beacf11bSopenharmony_ci  if (tfo == NULL)
1059beacf11bSopenharmony_ci    {
1060beacf11bSopenharmony_ci      return -EINVAL;
1061beacf11bSopenharmony_ci    }
1062beacf11bSopenharmony_ci  if (filep->f_pos >= tfo->tfo_size || buflen == 0)
1063beacf11bSopenharmony_ci    {
1064beacf11bSopenharmony_ci      return 0;
1065beacf11bSopenharmony_ci    }
1066beacf11bSopenharmony_ci
1067beacf11bSopenharmony_ci  /* Get exclusive access to the file */
1068beacf11bSopenharmony_ci
1069beacf11bSopenharmony_ci  tmpfs_lock_file(tfo);
1070beacf11bSopenharmony_ci
1071beacf11bSopenharmony_ci  /* Handle attempts to read beyond the end of the file. */
1072beacf11bSopenharmony_ci
1073beacf11bSopenharmony_ci  startpos = filep->f_pos;
1074beacf11bSopenharmony_ci  nread    = buflen;
1075beacf11bSopenharmony_ci  endpos   = startpos + buflen;
1076beacf11bSopenharmony_ci
1077beacf11bSopenharmony_ci  if (endpos > tfo->tfo_size)
1078beacf11bSopenharmony_ci    {
1079beacf11bSopenharmony_ci      endpos = tfo->tfo_size;
1080beacf11bSopenharmony_ci      nread  = endpos - startpos;
1081beacf11bSopenharmony_ci    }
1082beacf11bSopenharmony_ci
1083beacf11bSopenharmony_ci  /* Copy data from the memory object to the user buffer */
1084beacf11bSopenharmony_ci
1085beacf11bSopenharmony_ci  if (LOS_CopyFromKernel(buffer, buflen, &tfo->tfo_data[startpos], nread) != 0)
1086beacf11bSopenharmony_ci    {
1087beacf11bSopenharmony_ci      tmpfs_unlock_file(tfo);
1088beacf11bSopenharmony_ci      return -EINVAL;
1089beacf11bSopenharmony_ci    }
1090beacf11bSopenharmony_ci  filep->f_pos += nread;
1091beacf11bSopenharmony_ci
1092beacf11bSopenharmony_ci  /* Update the node's access time */
1093beacf11bSopenharmony_ci
1094beacf11bSopenharmony_ci  tfo->tfo_atime = tmpfs_timestamp();
1095beacf11bSopenharmony_ci
1096beacf11bSopenharmony_ci  /* Release the lock on the file */
1097beacf11bSopenharmony_ci
1098beacf11bSopenharmony_ci  tmpfs_unlock_file(tfo);
1099beacf11bSopenharmony_ci  return nread;
1100beacf11bSopenharmony_ci}
1101beacf11bSopenharmony_ci
1102beacf11bSopenharmony_ci/****************************************************************************
1103beacf11bSopenharmony_ci * Name: tmpfs_readpage
1104beacf11bSopenharmony_ci ****************************************************************************/
1105beacf11bSopenharmony_ci
1106beacf11bSopenharmony_cissize_t tmpfs_readpage(struct Vnode *vnode, char *buffer, off_t off)
1107beacf11bSopenharmony_ci{
1108beacf11bSopenharmony_ci  struct tmpfs_file_s *tfo;
1109beacf11bSopenharmony_ci  ssize_t nread;
1110beacf11bSopenharmony_ci  loff_t startpos;
1111beacf11bSopenharmony_ci  loff_t endpos;
1112beacf11bSopenharmony_ci
1113beacf11bSopenharmony_ci  DEBUGASSERT(vnode->data != NULL);
1114beacf11bSopenharmony_ci
1115beacf11bSopenharmony_ci  /* Recover our private data from the vnode */
1116beacf11bSopenharmony_ci
1117beacf11bSopenharmony_ci  tfo = (struct tmpfs_file_s *)(vnode->data);
1118beacf11bSopenharmony_ci  if (tfo == NULL)
1119beacf11bSopenharmony_ci    {
1120beacf11bSopenharmony_ci      return -EINVAL;
1121beacf11bSopenharmony_ci    }
1122beacf11bSopenharmony_ci  if (off >= tfo->tfo_size)
1123beacf11bSopenharmony_ci    {
1124beacf11bSopenharmony_ci      return 0;
1125beacf11bSopenharmony_ci    }
1126beacf11bSopenharmony_ci
1127beacf11bSopenharmony_ci  /* Get exclusive access to the file */
1128beacf11bSopenharmony_ci
1129beacf11bSopenharmony_ci  tmpfs_lock_file(tfo);
1130beacf11bSopenharmony_ci
1131beacf11bSopenharmony_ci  /* Handle attempts to read beyond the end of the file. */
1132beacf11bSopenharmony_ci
1133beacf11bSopenharmony_ci  startpos = off;
1134beacf11bSopenharmony_ci  nread    = PAGE_SIZE;
1135beacf11bSopenharmony_ci  endpos   = startpos + PAGE_SIZE;
1136beacf11bSopenharmony_ci
1137beacf11bSopenharmony_ci  if (endpos > tfo->tfo_size)
1138beacf11bSopenharmony_ci    {
1139beacf11bSopenharmony_ci      endpos = tfo->tfo_size;
1140beacf11bSopenharmony_ci      nread  = endpos - startpos;
1141beacf11bSopenharmony_ci    }
1142beacf11bSopenharmony_ci
1143beacf11bSopenharmony_ci  /* Copy data from the memory object to the user buffer */
1144beacf11bSopenharmony_ci
1145beacf11bSopenharmony_ci  if (LOS_CopyFromKernel(buffer, PAGE_SIZE, &tfo->tfo_data[startpos], nread) != 0)
1146beacf11bSopenharmony_ci    {
1147beacf11bSopenharmony_ci      tmpfs_unlock_file(tfo);
1148beacf11bSopenharmony_ci      return -EINVAL;
1149beacf11bSopenharmony_ci    }
1150beacf11bSopenharmony_ci
1151beacf11bSopenharmony_ci  /* Update the node's access time */
1152beacf11bSopenharmony_ci
1153beacf11bSopenharmony_ci  tfo->tfo_atime = tmpfs_timestamp();
1154beacf11bSopenharmony_ci
1155beacf11bSopenharmony_ci  /* Release the lock on the file */
1156beacf11bSopenharmony_ci
1157beacf11bSopenharmony_ci  tmpfs_unlock_file(tfo);
1158beacf11bSopenharmony_ci  return nread;
1159beacf11bSopenharmony_ci}
1160beacf11bSopenharmony_ci
1161beacf11bSopenharmony_ci
1162beacf11bSopenharmony_ci/****************************************************************************
1163beacf11bSopenharmony_ci * Name: tmpfs_create
1164beacf11bSopenharmony_ci ****************************************************************************/
1165beacf11bSopenharmony_ci
1166beacf11bSopenharmony_ciint tmpfs_create(struct Vnode *dvp, const char *path, int mode, struct Vnode **vpp)
1167beacf11bSopenharmony_ci{
1168beacf11bSopenharmony_ci    struct Vnode *vp = NULL;
1169beacf11bSopenharmony_ci    struct tmpfs_file_s *tfo;
1170beacf11bSopenharmony_ci    struct tmpfs_s *fs;
1171beacf11bSopenharmony_ci    int ret = 0;
1172beacf11bSopenharmony_ci    struct tmpfs_directory_s *parent_tdo = NULL;
1173beacf11bSopenharmony_ci
1174beacf11bSopenharmony_ci    if (dvp == NULL)
1175beacf11bSopenharmony_ci      {
1176beacf11bSopenharmony_ci        return -ENOENT;
1177beacf11bSopenharmony_ci      }
1178beacf11bSopenharmony_ci
1179beacf11bSopenharmony_ci    fs = dvp->originMount->data;
1180beacf11bSopenharmony_ci    if (fs == NULL)
1181beacf11bSopenharmony_ci      {
1182beacf11bSopenharmony_ci        return -ENOENT;
1183beacf11bSopenharmony_ci      }
1184beacf11bSopenharmony_ci
1185beacf11bSopenharmony_ci    tmpfs_lock(fs);
1186beacf11bSopenharmony_ci
1187beacf11bSopenharmony_ci    if (dvp->data != NULL)
1188beacf11bSopenharmony_ci      {
1189beacf11bSopenharmony_ci        parent_tdo = (struct tmpfs_directory_s *)(dvp->data);
1190beacf11bSopenharmony_ci      }
1191beacf11bSopenharmony_ci
1192beacf11bSopenharmony_ci    ret = tmpfs_create_file(fs, path, parent_tdo, &tfo);
1193beacf11bSopenharmony_ci    if (ret < 0)
1194beacf11bSopenharmony_ci      {
1195beacf11bSopenharmony_ci        goto errout_with_fslock;
1196beacf11bSopenharmony_ci      }
1197beacf11bSopenharmony_ci
1198beacf11bSopenharmony_ci    ret = VnodeAlloc(&tmpfs_vops, &vp);
1199beacf11bSopenharmony_ci    if (ret != 0)
1200beacf11bSopenharmony_ci      {
1201beacf11bSopenharmony_ci        tmpfs_unlock_file(tfo);
1202beacf11bSopenharmony_ci        goto errout_with_fslock;
1203beacf11bSopenharmony_ci      }
1204beacf11bSopenharmony_ci    vp->parent = dvp;
1205beacf11bSopenharmony_ci    vp->vop = dvp->vop;
1206beacf11bSopenharmony_ci    vp->fop = dvp->fop;
1207beacf11bSopenharmony_ci    vp->data = tfo;
1208beacf11bSopenharmony_ci    vp->originMount = dvp->originMount;
1209beacf11bSopenharmony_ci    vp->type = VNODE_TYPE_REG;
1210beacf11bSopenharmony_ci    tfo->mode = mode;
1211beacf11bSopenharmony_ci    vp->mode = tfo->mode;
1212beacf11bSopenharmony_ci    vp->gid = tfo->gid;
1213beacf11bSopenharmony_ci    vp->uid = tfo->uid;
1214beacf11bSopenharmony_ci
1215beacf11bSopenharmony_ci    ret = VfsHashInsert(vp, (uint32_t)tfo);
1216beacf11bSopenharmony_ci
1217beacf11bSopenharmony_ci    *vpp = vp;
1218beacf11bSopenharmony_ci    tmpfs_unlock_file(tfo);
1219beacf11bSopenharmony_cierrout_with_fslock:
1220beacf11bSopenharmony_ci    tmpfs_unlock(fs);
1221beacf11bSopenharmony_ci    return 0;
1222beacf11bSopenharmony_ci}
1223beacf11bSopenharmony_ci
1224beacf11bSopenharmony_ci
1225beacf11bSopenharmony_ci/****************************************************************************
1226beacf11bSopenharmony_ci * Name: los_set_ramfs_unit
1227beacf11bSopenharmony_ci ****************************************************************************/
1228beacf11bSopenharmony_ci
1229beacf11bSopenharmony_cistatic spinlock_t tmpfs_alloc_unit_lock;
1230beacf11bSopenharmony_cibool is_tmpfs_lock_init = false;
1231beacf11bSopenharmony_ciunsigned int g_tmpfs_alloc_unit = 0;
1232beacf11bSopenharmony_ci
1233beacf11bSopenharmony_civoid los_set_ramfs_unit(off_t size)
1234beacf11bSopenharmony_ci{
1235beacf11bSopenharmony_ci  if (is_tmpfs_lock_init && size >= 0)
1236beacf11bSopenharmony_ci    {
1237beacf11bSopenharmony_ci      spin_lock(&tmpfs_alloc_unit_lock);
1238beacf11bSopenharmony_ci      g_tmpfs_alloc_unit = size;
1239beacf11bSopenharmony_ci      spin_unlock(&tmpfs_alloc_unit_lock);
1240beacf11bSopenharmony_ci    }
1241beacf11bSopenharmony_ci}
1242beacf11bSopenharmony_ci
1243beacf11bSopenharmony_ci/****************************************************************************
1244beacf11bSopenharmony_ci * Name: tmpfs_write
1245beacf11bSopenharmony_ci ****************************************************************************/
1246beacf11bSopenharmony_ci
1247beacf11bSopenharmony_cissize_t tmpfs_write(struct file *filep, const char *buffer, size_t buflen)
1248beacf11bSopenharmony_ci{
1249beacf11bSopenharmony_ci  struct tmpfs_file_s *tfo;
1250beacf11bSopenharmony_ci  ssize_t nwritten;
1251beacf11bSopenharmony_ci  loff_t startpos;
1252beacf11bSopenharmony_ci  loff_t endpos;
1253beacf11bSopenharmony_ci  int ret;
1254beacf11bSopenharmony_ci  int alloc;
1255beacf11bSopenharmony_ci  char *data;
1256beacf11bSopenharmony_ci
1257beacf11bSopenharmony_ci  DEBUGASSERT(filep->f_vnode != NULL);
1258beacf11bSopenharmony_ci
1259beacf11bSopenharmony_ci  if (buflen == 0)
1260beacf11bSopenharmony_ci    {
1261beacf11bSopenharmony_ci      return 0;
1262beacf11bSopenharmony_ci    }
1263beacf11bSopenharmony_ci
1264beacf11bSopenharmony_ci  /* Recover our private data from the struct file instance */
1265beacf11bSopenharmony_ci  tfo = (struct tmpfs_file_s *)(filep->f_vnode->data);
1266beacf11bSopenharmony_ci  if (tfo == NULL)
1267beacf11bSopenharmony_ci    {
1268beacf11bSopenharmony_ci      return -EINVAL;
1269beacf11bSopenharmony_ci    }
1270beacf11bSopenharmony_ci  /* Get exclusive access to the file */
1271beacf11bSopenharmony_ci
1272beacf11bSopenharmony_ci  tmpfs_lock_file(tfo);
1273beacf11bSopenharmony_ci
1274beacf11bSopenharmony_ci  /* Handle attempts to write beyond the end of the file */
1275beacf11bSopenharmony_ci
1276beacf11bSopenharmony_ci  startpos = filep->f_pos;
1277beacf11bSopenharmony_ci  nwritten = buflen;
1278beacf11bSopenharmony_ci  endpos   = startpos + buflen;
1279beacf11bSopenharmony_ci
1280beacf11bSopenharmony_ci  if (startpos < 0)
1281beacf11bSopenharmony_ci    {
1282beacf11bSopenharmony_ci      ret = -EPERM;
1283beacf11bSopenharmony_ci      goto errout_with_lock;
1284beacf11bSopenharmony_ci    }
1285beacf11bSopenharmony_ci
1286beacf11bSopenharmony_ci  if (endpos > tfo->tfo_size)
1287beacf11bSopenharmony_ci    {
1288beacf11bSopenharmony_ci      spin_lock(&tmpfs_alloc_unit_lock);
1289beacf11bSopenharmony_ci      alloc = (g_tmpfs_alloc_unit > buflen) ? g_tmpfs_alloc_unit : buflen;
1290beacf11bSopenharmony_ci      spin_unlock(&tmpfs_alloc_unit_lock);
1291beacf11bSopenharmony_ci      data  = (char *)malloc(startpos + alloc);
1292beacf11bSopenharmony_ci      if (!data)
1293beacf11bSopenharmony_ci        {
1294beacf11bSopenharmony_ci          ret = -ENOSPC;
1295beacf11bSopenharmony_ci          goto errout_with_lock;
1296beacf11bSopenharmony_ci        }
1297beacf11bSopenharmony_ci      if (tfo->tfo_size)
1298beacf11bSopenharmony_ci        {
1299beacf11bSopenharmony_ci          ret = memcpy_s(data, startpos + alloc, tfo->tfo_data, tfo->tfo_size);
1300beacf11bSopenharmony_ci          if (ret != EOK)
1301beacf11bSopenharmony_ci            {
1302beacf11bSopenharmony_ci              ret = -1;
1303beacf11bSopenharmony_ci              free(data);
1304beacf11bSopenharmony_ci              goto errout_with_lock;
1305beacf11bSopenharmony_ci            }
1306beacf11bSopenharmony_ci          free(tfo->tfo_data);
1307beacf11bSopenharmony_ci        }
1308beacf11bSopenharmony_ci      if (startpos > tfo->tfo_size)
1309beacf11bSopenharmony_ci        {
1310beacf11bSopenharmony_ci          (void)memset_s(data + tfo->tfo_size, startpos + alloc - tfo->tfo_size, 0, startpos - tfo->tfo_size);
1311beacf11bSopenharmony_ci        }
1312beacf11bSopenharmony_ci
1313beacf11bSopenharmony_ci      tfo->tfo_data = data;
1314beacf11bSopenharmony_ci      tfo->tfo_size = startpos + alloc;
1315beacf11bSopenharmony_ci    }
1316beacf11bSopenharmony_ci
1317beacf11bSopenharmony_ci  /* Copy data from the memory object to the user buffer */
1318beacf11bSopenharmony_ci  if (LOS_CopyToKernel(&tfo->tfo_data[startpos], nwritten, buffer, nwritten) != 0)
1319beacf11bSopenharmony_ci    {
1320beacf11bSopenharmony_ci      ret = -EINVAL;
1321beacf11bSopenharmony_ci      goto errout_with_lock;
1322beacf11bSopenharmony_ci    }
1323beacf11bSopenharmony_ci  filep->f_pos += nwritten;
1324beacf11bSopenharmony_ci
1325beacf11bSopenharmony_ci  /* Update the modified and access times of the node */
1326beacf11bSopenharmony_ci
1327beacf11bSopenharmony_ci  tfo->tfo_ctime = tfo->tfo_mtime = tmpfs_timestamp();
1328beacf11bSopenharmony_ci
1329beacf11bSopenharmony_ci  /* Release the lock on the file */
1330beacf11bSopenharmony_ci
1331beacf11bSopenharmony_ci  tmpfs_unlock_file(tfo);
1332beacf11bSopenharmony_ci  return nwritten;
1333beacf11bSopenharmony_ci
1334beacf11bSopenharmony_cierrout_with_lock:
1335beacf11bSopenharmony_ci  tmpfs_unlock_file(tfo);
1336beacf11bSopenharmony_ci  return (ssize_t)ret;
1337beacf11bSopenharmony_ci}
1338beacf11bSopenharmony_ci
1339beacf11bSopenharmony_ci/****************************************************************************
1340beacf11bSopenharmony_ci * Name: tmpfs_seek
1341beacf11bSopenharmony_ci ****************************************************************************/
1342beacf11bSopenharmony_ci
1343beacf11bSopenharmony_cioff_t tmpfs_seek(struct file *filep, off_t offset, int whence)
1344beacf11bSopenharmony_ci{
1345beacf11bSopenharmony_ci  struct tmpfs_file_s *tfo;
1346beacf11bSopenharmony_ci  off_t position;
1347beacf11bSopenharmony_ci
1348beacf11bSopenharmony_ci  DEBUGASSERT(filep->f_vnode != NULL);
1349beacf11bSopenharmony_ci
1350beacf11bSopenharmony_ci  /* Recover our private data from the struct file instance */
1351beacf11bSopenharmony_ci
1352beacf11bSopenharmony_ci  tfo = (struct tmpfs_file_s *)(filep->f_vnode->data);
1353beacf11bSopenharmony_ci  if (tfo == NULL)
1354beacf11bSopenharmony_ci    {
1355beacf11bSopenharmony_ci      return -EINVAL;
1356beacf11bSopenharmony_ci    }
1357beacf11bSopenharmony_ci  /* Map the offset according to the whence option */
1358beacf11bSopenharmony_ci
1359beacf11bSopenharmony_ci  switch (whence)
1360beacf11bSopenharmony_ci    {
1361beacf11bSopenharmony_ci      case SEEK_SET: /* The offset is set to offset bytes. */
1362beacf11bSopenharmony_ci          position = offset;
1363beacf11bSopenharmony_ci          break;
1364beacf11bSopenharmony_ci
1365beacf11bSopenharmony_ci      case SEEK_CUR: /* The offset is set to its current location plus
1366beacf11bSopenharmony_ci                      * offset bytes. */
1367beacf11bSopenharmony_ci          position = offset + filep->f_pos;
1368beacf11bSopenharmony_ci          break;
1369beacf11bSopenharmony_ci
1370beacf11bSopenharmony_ci      case SEEK_END: /* The offset is set to the size of the file plus
1371beacf11bSopenharmony_ci                      * offset bytes. */
1372beacf11bSopenharmony_ci          position = offset + tfo->tfo_size;
1373beacf11bSopenharmony_ci          break;
1374beacf11bSopenharmony_ci
1375beacf11bSopenharmony_ci      default:
1376beacf11bSopenharmony_ci          return -EINVAL;
1377beacf11bSopenharmony_ci    }
1378beacf11bSopenharmony_ci
1379beacf11bSopenharmony_ci  /* Attempts to set the position beyond the end of file will
1380beacf11bSopenharmony_ci   * work if the file is open for write access.
1381beacf11bSopenharmony_ci   *
1382beacf11bSopenharmony_ci   * REVISIT: This simple implementation has no per-open storage that
1383beacf11bSopenharmony_ci   * would be needed to retain the open flags.
1384beacf11bSopenharmony_ci   */
1385beacf11bSopenharmony_ci    if (position < 0)
1386beacf11bSopenharmony_ci    {
1387beacf11bSopenharmony_ci      return -EINVAL;
1388beacf11bSopenharmony_ci    }
1389beacf11bSopenharmony_ci
1390beacf11bSopenharmony_ci  /* Save the new file position */
1391beacf11bSopenharmony_ci
1392beacf11bSopenharmony_ci  filep->f_pos = position;
1393beacf11bSopenharmony_ci  return position;
1394beacf11bSopenharmony_ci}
1395beacf11bSopenharmony_ci
1396beacf11bSopenharmony_ci/****************************************************************************
1397beacf11bSopenharmony_ci * Name: tmpfs_ioctl
1398beacf11bSopenharmony_ci ****************************************************************************/
1399beacf11bSopenharmony_ci
1400beacf11bSopenharmony_ciint tmpfs_ioctl(struct file *filep, int cmd, unsigned long arg)
1401beacf11bSopenharmony_ci{
1402beacf11bSopenharmony_ci  return -EINVAL;
1403beacf11bSopenharmony_ci}
1404beacf11bSopenharmony_ci
1405beacf11bSopenharmony_ci/****************************************************************************
1406beacf11bSopenharmony_ci * Name: tmpfs_sync
1407beacf11bSopenharmony_ci ****************************************************************************/
1408beacf11bSopenharmony_ci
1409beacf11bSopenharmony_ciint tmpfs_sync(struct file *filep)
1410beacf11bSopenharmony_ci{
1411beacf11bSopenharmony_ci  return 0;
1412beacf11bSopenharmony_ci}
1413beacf11bSopenharmony_ci
1414beacf11bSopenharmony_ci/****************************************************************************
1415beacf11bSopenharmony_ci * Name: tmpfs_opendir
1416beacf11bSopenharmony_ci ****************************************************************************/
1417beacf11bSopenharmony_ci
1418beacf11bSopenharmony_ciint tmpfs_opendir(struct Vnode *vp, struct fs_dirent_s *dir)
1419beacf11bSopenharmony_ci{
1420beacf11bSopenharmony_ci  struct tmpfs_s *fs;
1421beacf11bSopenharmony_ci  struct tmpfs_directory_s *tdo;
1422beacf11bSopenharmony_ci  int ret = 0;
1423beacf11bSopenharmony_ci  struct fs_tmpfsdir_s *tmp;
1424beacf11bSopenharmony_ci
1425beacf11bSopenharmony_ci  DEBUGASSERT(vp != NULL && dir != NULL);
1426beacf11bSopenharmony_ci
1427beacf11bSopenharmony_ci  /* Get the mountpoint private data from the inode structure */
1428beacf11bSopenharmony_ci
1429beacf11bSopenharmony_ci  fs = vp->originMount->data;
1430beacf11bSopenharmony_ci  DEBUGASSERT(fs != NULL);
1431beacf11bSopenharmony_ci
1432beacf11bSopenharmony_ci  tmp = (struct fs_tmpfsdir_s *)malloc(sizeof(struct fs_tmpfsdir_s));
1433beacf11bSopenharmony_ci  if (!tmp)
1434beacf11bSopenharmony_ci    {
1435beacf11bSopenharmony_ci      return -ENOSPC;
1436beacf11bSopenharmony_ci    }
1437beacf11bSopenharmony_ci
1438beacf11bSopenharmony_ci  /* Get exclusive access to the file system */
1439beacf11bSopenharmony_ci
1440beacf11bSopenharmony_ci  tmpfs_lock(fs);
1441beacf11bSopenharmony_ci
1442beacf11bSopenharmony_ci  /* Find the directory object associated with this relative path.
1443beacf11bSopenharmony_ci   * If successful, this action will lock both the parent directory and
1444beacf11bSopenharmony_ci   * the file object, adding one to the reference count of both.
1445beacf11bSopenharmony_ci   * In the event that -ENOENT, there will still be a reference and
1446beacf11bSopenharmony_ci   * lock on the returned directory.
1447beacf11bSopenharmony_ci   */
1448beacf11bSopenharmony_ci
1449beacf11bSopenharmony_ci  if (vp->data != NULL)
1450beacf11bSopenharmony_ci    {
1451beacf11bSopenharmony_ci      tdo = (struct tmpfs_directory_s *)vp->data;
1452beacf11bSopenharmony_ci    }
1453beacf11bSopenharmony_ci  else
1454beacf11bSopenharmony_ci    {
1455beacf11bSopenharmony_ci      tdo = (struct tmpfs_directory_s *)fs->tfs_root.tde_object;
1456beacf11bSopenharmony_ci    }
1457beacf11bSopenharmony_ci
1458beacf11bSopenharmony_ci  if (tdo == NULL)
1459beacf11bSopenharmony_ci    {
1460beacf11bSopenharmony_ci      free(tmp);
1461beacf11bSopenharmony_ci      tmpfs_unlock(fs);
1462beacf11bSopenharmony_ci      return -EINTR;
1463beacf11bSopenharmony_ci    }
1464beacf11bSopenharmony_ci  tmpfs_lock_directory(tdo);
1465beacf11bSopenharmony_ci  tmp->tf_tdo   = tdo;
1466beacf11bSopenharmony_ci  tmp->tf_index = 0;
1467beacf11bSopenharmony_ci  dir->u.fs_dir = (fs_dir_s)tmp;
1468beacf11bSopenharmony_ci  tdo->tdo_count++;
1469beacf11bSopenharmony_ci  tdo->tdo_refs++;
1470beacf11bSopenharmony_ci  tmpfs_unlock_directory(tdo);
1471beacf11bSopenharmony_ci
1472beacf11bSopenharmony_ci  /* Release the lock on the file system and return the result */
1473beacf11bSopenharmony_ci
1474beacf11bSopenharmony_ci  tmpfs_unlock(fs);
1475beacf11bSopenharmony_ci  return ret;
1476beacf11bSopenharmony_ci}
1477beacf11bSopenharmony_ci
1478beacf11bSopenharmony_ci/****************************************************************************
1479beacf11bSopenharmony_ci * Name: tmpfs_closedir
1480beacf11bSopenharmony_ci ****************************************************************************/
1481beacf11bSopenharmony_ci
1482beacf11bSopenharmony_ciint tmpfs_closedir(struct Vnode *vp, struct fs_dirent_s *dir)
1483beacf11bSopenharmony_ci{
1484beacf11bSopenharmony_ci  struct tmpfs_directory_s *tdo;
1485beacf11bSopenharmony_ci  struct fs_tmpfsdir_s *tmp;
1486beacf11bSopenharmony_ci
1487beacf11bSopenharmony_ci  DEBUGASSERT(vp != NULL && dir != NULL);
1488beacf11bSopenharmony_ci
1489beacf11bSopenharmony_ci  /* Get the directory structure from the dir argument */
1490beacf11bSopenharmony_ci
1491beacf11bSopenharmony_ci  tmp = (struct fs_tmpfsdir_s *)dir->u.fs_dir;
1492beacf11bSopenharmony_ci  if (tmp == NULL)
1493beacf11bSopenharmony_ci    {
1494beacf11bSopenharmony_ci      return -ENOENT;
1495beacf11bSopenharmony_ci    }
1496beacf11bSopenharmony_ci  tdo = tmp->tf_tdo;
1497beacf11bSopenharmony_ci  DEBUGASSERT(tdo != NULL);
1498beacf11bSopenharmony_ci
1499beacf11bSopenharmony_ci  /* Decrement the reference count on the directory object */
1500beacf11bSopenharmony_ci
1501beacf11bSopenharmony_ci  tmpfs_lock_directory(tdo);
1502beacf11bSopenharmony_ci  if (tdo->tdo_count == 1)
1503beacf11bSopenharmony_ci    {
1504beacf11bSopenharmony_ci      LOS_DL_LIST *node = tdo->tdo_entry.pstNext;
1505beacf11bSopenharmony_ci      struct tmpfs_dirent_s *tde;
1506beacf11bSopenharmony_ci      while (node != &tdo->tdo_entry)
1507beacf11bSopenharmony_ci        {
1508beacf11bSopenharmony_ci          tde = (struct tmpfs_dirent_s *)node;
1509beacf11bSopenharmony_ci          node = node->pstNext;
1510beacf11bSopenharmony_ci          if (tde->tde_inuse == false)
1511beacf11bSopenharmony_ci            {
1512beacf11bSopenharmony_ci              LOS_ListDelete(&tde->tde_node);
1513beacf11bSopenharmony_ci              kmm_free(tde);
1514beacf11bSopenharmony_ci            }
1515beacf11bSopenharmony_ci        }
1516beacf11bSopenharmony_ci    }
1517beacf11bSopenharmony_ci  if (tdo->tdo_refs > 0)
1518beacf11bSopenharmony_ci    {
1519beacf11bSopenharmony_ci      tdo->tdo_refs--;
1520beacf11bSopenharmony_ci    }
1521beacf11bSopenharmony_ci  if (tdo->tdo_count > 0)
1522beacf11bSopenharmony_ci    {
1523beacf11bSopenharmony_ci      tdo->tdo_count--;
1524beacf11bSopenharmony_ci    }
1525beacf11bSopenharmony_ci  tmpfs_unlock_directory(tdo);
1526beacf11bSopenharmony_ci
1527beacf11bSopenharmony_ci  free(tmp);
1528beacf11bSopenharmony_ci
1529beacf11bSopenharmony_ci  return OK;
1530beacf11bSopenharmony_ci}
1531beacf11bSopenharmony_ci
1532beacf11bSopenharmony_ci/****************************************************************************
1533beacf11bSopenharmony_ci * Name: tmpfs_readdir
1534beacf11bSopenharmony_ci ****************************************************************************/
1535beacf11bSopenharmony_ci
1536beacf11bSopenharmony_ciint tmpfs_readdir(struct Vnode *vp, struct fs_dirent_s *dir)
1537beacf11bSopenharmony_ci{
1538beacf11bSopenharmony_ci  struct tmpfs_directory_s *tdo;
1539beacf11bSopenharmony_ci  unsigned int index;
1540beacf11bSopenharmony_ci  int ret;
1541beacf11bSopenharmony_ci  struct fs_tmpfsdir_s *tmp;
1542beacf11bSopenharmony_ci  LOS_DL_LIST *node;
1543beacf11bSopenharmony_ci  struct tmpfs_dirent_s *tde;
1544beacf11bSopenharmony_ci
1545beacf11bSopenharmony_ci  DEBUGASSERT(vp != NULL && dir != NULL);
1546beacf11bSopenharmony_ci
1547beacf11bSopenharmony_ci  /* Get the directory structure from the dir argument and lock it */
1548beacf11bSopenharmony_ci
1549beacf11bSopenharmony_ci  tmp = (struct fs_tmpfsdir_s *)dir->u.fs_dir;
1550beacf11bSopenharmony_ci  if (tmp == NULL)
1551beacf11bSopenharmony_ci    {
1552beacf11bSopenharmony_ci      return -ENOENT;
1553beacf11bSopenharmony_ci    }
1554beacf11bSopenharmony_ci
1555beacf11bSopenharmony_ci  tdo = tmp->tf_tdo;
1556beacf11bSopenharmony_ci  if (tdo == NULL)
1557beacf11bSopenharmony_ci    {
1558beacf11bSopenharmony_ci      return -ENOENT;
1559beacf11bSopenharmony_ci    }
1560beacf11bSopenharmony_ci
1561beacf11bSopenharmony_ci  tmpfs_lock_directory(tdo);
1562beacf11bSopenharmony_ci
1563beacf11bSopenharmony_ci  /* Have we reached the end of the directory? */
1564beacf11bSopenharmony_ci
1565beacf11bSopenharmony_ci  index = tmp->tf_index;
1566beacf11bSopenharmony_ci  node = tdo->tdo_entry.pstNext;
1567beacf11bSopenharmony_ci  while (node != &tdo->tdo_entry && index != 0)
1568beacf11bSopenharmony_ci    {
1569beacf11bSopenharmony_ci       node = node->pstNext;
1570beacf11bSopenharmony_ci       index--;
1571beacf11bSopenharmony_ci    }
1572beacf11bSopenharmony_ci
1573beacf11bSopenharmony_ci  while (node != &tdo->tdo_entry)
1574beacf11bSopenharmony_ci    {
1575beacf11bSopenharmony_ci      tde = (struct tmpfs_dirent_s *)node;
1576beacf11bSopenharmony_ci      tmp->tf_index++;
1577beacf11bSopenharmony_ci      if (tde->tde_inuse == true)
1578beacf11bSopenharmony_ci       {
1579beacf11bSopenharmony_ci         break;
1580beacf11bSopenharmony_ci       }
1581beacf11bSopenharmony_ci       node = node->pstNext;
1582beacf11bSopenharmony_ci    }
1583beacf11bSopenharmony_ci
1584beacf11bSopenharmony_ci  if (node == &tdo->tdo_entry)
1585beacf11bSopenharmony_ci    {
1586beacf11bSopenharmony_ci      /* We signal the end of the directory by returning the special error:
1587beacf11bSopenharmony_ci       * -ENOENT
1588beacf11bSopenharmony_ci       */
1589beacf11bSopenharmony_ci
1590beacf11bSopenharmony_ci      PRINT_INFO("End of directory\n");
1591beacf11bSopenharmony_ci      ret = -ENOENT;
1592beacf11bSopenharmony_ci    }
1593beacf11bSopenharmony_ci  else
1594beacf11bSopenharmony_ci    {
1595beacf11bSopenharmony_ci      struct tmpfs_object_s *to;
1596beacf11bSopenharmony_ci
1597beacf11bSopenharmony_ci      /* Does this entry refer to a file or a directory object? */
1598beacf11bSopenharmony_ci
1599beacf11bSopenharmony_ci      to  = tde->tde_object;
1600beacf11bSopenharmony_ci      DEBUGASSERT(to != NULL);
1601beacf11bSopenharmony_ci
1602beacf11bSopenharmony_ci      if (to->to_type == TMPFS_DIRECTORY)
1603beacf11bSopenharmony_ci        {
1604beacf11bSopenharmony_ci          /* A directory */
1605beacf11bSopenharmony_ci
1606beacf11bSopenharmony_ci           dir->fd_dir[0].d_type = DT_DIR;
1607beacf11bSopenharmony_ci        }
1608beacf11bSopenharmony_ci      else /* to->to_type == TMPFS_REGULAR) */
1609beacf11bSopenharmony_ci        {
1610beacf11bSopenharmony_ci          /* A regular file */
1611beacf11bSopenharmony_ci
1612beacf11bSopenharmony_ci           dir->fd_dir[0].d_type = DT_REG;
1613beacf11bSopenharmony_ci        }
1614beacf11bSopenharmony_ci
1615beacf11bSopenharmony_ci      /* Copy the entry name */
1616beacf11bSopenharmony_ci
1617beacf11bSopenharmony_ci      (void)strncpy_s(dir->fd_dir[0].d_name, NAME_MAX + 1, tde->tde_name, NAME_MAX);
1618beacf11bSopenharmony_ci
1619beacf11bSopenharmony_ci      dir->fd_position++;
1620beacf11bSopenharmony_ci      dir->fd_dir[0].d_off = dir->fd_position;
1621beacf11bSopenharmony_ci      dir->fd_dir[0].d_reclen = (uint16_t)sizeof(struct dirent);
1622beacf11bSopenharmony_ci
1623beacf11bSopenharmony_ci      ret = 1; // 1 means current file num is 1
1624beacf11bSopenharmony_ci    }
1625beacf11bSopenharmony_ci
1626beacf11bSopenharmony_ci  tmpfs_unlock_directory(tdo);
1627beacf11bSopenharmony_ci  return ret;
1628beacf11bSopenharmony_ci}
1629beacf11bSopenharmony_ci
1630beacf11bSopenharmony_ci/****************************************************************************
1631beacf11bSopenharmony_ci * Name: tmpfs_rewinddir
1632beacf11bSopenharmony_ci ****************************************************************************/
1633beacf11bSopenharmony_ci
1634beacf11bSopenharmony_ciint tmpfs_rewinddir(struct Vnode *vp, struct fs_dirent_s *dir)
1635beacf11bSopenharmony_ci{
1636beacf11bSopenharmony_ci  struct fs_tmpfsdir_s *tmp;
1637beacf11bSopenharmony_ci  PRINT_DEBUG("vp: %p dir: %p\n",  vp, dir);
1638beacf11bSopenharmony_ci  DEBUGASSERT(vp != NULL && dir != NULL);
1639beacf11bSopenharmony_ci  tmp = (struct fs_tmpfsdir_s *)dir->u.fs_dir;
1640beacf11bSopenharmony_ci
1641beacf11bSopenharmony_ci  /* Set the readdir index to zero */
1642beacf11bSopenharmony_ci
1643beacf11bSopenharmony_ci  tmp->tf_index = 0;
1644beacf11bSopenharmony_ci  return OK;
1645beacf11bSopenharmony_ci}
1646beacf11bSopenharmony_ci
1647beacf11bSopenharmony_ciint tmpfs_truncate(struct Vnode *vp, off_t len)
1648beacf11bSopenharmony_ci{
1649beacf11bSopenharmony_ci  struct tmpfs_file_s *tfo = NULL;
1650beacf11bSopenharmony_ci
1651beacf11bSopenharmony_ci  tfo = vp->data;
1652beacf11bSopenharmony_ci  tfo->tfo_size = 0;
1653beacf11bSopenharmony_ci
1654beacf11bSopenharmony_ci  if (tfo->tfo_data)
1655beacf11bSopenharmony_ci    {
1656beacf11bSopenharmony_ci      free(tfo->tfo_data);
1657beacf11bSopenharmony_ci    }
1658beacf11bSopenharmony_ci
1659beacf11bSopenharmony_ci  return OK;
1660beacf11bSopenharmony_ci}
1661beacf11bSopenharmony_ci
1662beacf11bSopenharmony_ci
1663beacf11bSopenharmony_ci/****************************************************************************
1664beacf11bSopenharmony_ci * Name: tmpfs_mount
1665beacf11bSopenharmony_ci ****************************************************************************/
1666beacf11bSopenharmony_ci
1667beacf11bSopenharmony_ciint tmpfs_mount(struct Mount *mnt, struct Vnode *device, const void *data)
1668beacf11bSopenharmony_ci{
1669beacf11bSopenharmony_ci  struct tmpfs_directory_s *tdo;
1670beacf11bSopenharmony_ci  struct tmpfs_s *fs = &tmpfs_superblock;
1671beacf11bSopenharmony_ci  struct Vnode *vp = NULL;
1672beacf11bSopenharmony_ci  int ret;
1673beacf11bSopenharmony_ci
1674beacf11bSopenharmony_ci  DEBUGASSERT(device == NULL);
1675beacf11bSopenharmony_ci
1676beacf11bSopenharmony_ci  if (fs->tfs_root.tde_object != NULL)
1677beacf11bSopenharmony_ci    {
1678beacf11bSopenharmony_ci      return -EPERM;
1679beacf11bSopenharmony_ci    }
1680beacf11bSopenharmony_ci
1681beacf11bSopenharmony_ci  /* Create a root file system.  This is like a single directory entry in
1682beacf11bSopenharmony_ci   * the file system structure.
1683beacf11bSopenharmony_ci   */
1684beacf11bSopenharmony_ci
1685beacf11bSopenharmony_ci  tdo = tmpfs_alloc_directory();
1686beacf11bSopenharmony_ci  if (tdo == NULL)
1687beacf11bSopenharmony_ci    {
1688beacf11bSopenharmony_ci      return -ENOSPC;
1689beacf11bSopenharmony_ci    }
1690beacf11bSopenharmony_ci
1691beacf11bSopenharmony_ci  LOS_ListInit(&fs->tfs_root.tde_node);
1692beacf11bSopenharmony_ci  fs->tfs_root.tde_object = (struct tmpfs_object_s *)tdo;
1693beacf11bSopenharmony_ci  fs->tfs_root.tde_name   = NULL;
1694beacf11bSopenharmony_ci
1695beacf11bSopenharmony_ci  /* Set up the backward link (to support reallocation) */
1696beacf11bSopenharmony_ci
1697beacf11bSopenharmony_ci  tdo->tdo_dirent         = &fs->tfs_root;
1698beacf11bSopenharmony_ci
1699beacf11bSopenharmony_ci  /* Initialize the file system state */
1700beacf11bSopenharmony_ci
1701beacf11bSopenharmony_ci  fs->tfs_exclsem.ts_holder = TMPFS_NO_HOLDER;
1702beacf11bSopenharmony_ci  fs->tfs_exclsem.ts_count  = 0;
1703beacf11bSopenharmony_ci  sem_init(&fs->tfs_exclsem.ts_sem, 0, 1);
1704beacf11bSopenharmony_ci
1705beacf11bSopenharmony_ci  /* Return the new file system handle */
1706beacf11bSopenharmony_ci
1707beacf11bSopenharmony_ci  spin_lock_init(&tmpfs_alloc_unit_lock);
1708beacf11bSopenharmony_ci  is_tmpfs_lock_init = true;
1709beacf11bSopenharmony_ci
1710beacf11bSopenharmony_ci  ret = VnodeAlloc(&tmpfs_vops, &vp);
1711beacf11bSopenharmony_ci  if (ret != 0)
1712beacf11bSopenharmony_ci    {
1713beacf11bSopenharmony_ci      ret = ENOMEM;
1714beacf11bSopenharmony_ci      goto ERROR_WITH_FSWIN;
1715beacf11bSopenharmony_ci    }
1716beacf11bSopenharmony_ci
1717beacf11bSopenharmony_ci  tdo->mode = mnt->vnodeBeCovered->mode;
1718beacf11bSopenharmony_ci  tdo->gid = mnt->vnodeBeCovered->gid;
1719beacf11bSopenharmony_ci  tdo->uid = mnt->vnodeBeCovered->uid;
1720beacf11bSopenharmony_ci  vp->originMount = mnt;
1721beacf11bSopenharmony_ci  vp->fop = &tmpfs_fops;
1722beacf11bSopenharmony_ci  vp->type = VNODE_TYPE_DIR;
1723beacf11bSopenharmony_ci  vp->data = NULL;
1724beacf11bSopenharmony_ci  vp->mode = tdo->mode;
1725beacf11bSopenharmony_ci  vp->gid = tdo->gid;
1726beacf11bSopenharmony_ci  vp->uid = tdo->uid;
1727beacf11bSopenharmony_ci  mnt->data = fs;
1728beacf11bSopenharmony_ci  mnt->vnodeCovered = vp;
1729beacf11bSopenharmony_ci
1730beacf11bSopenharmony_ci  return OK;
1731beacf11bSopenharmony_ci
1732beacf11bSopenharmony_ciERROR_WITH_FSWIN:
1733beacf11bSopenharmony_ci  return ret;
1734beacf11bSopenharmony_ci}
1735beacf11bSopenharmony_ci
1736beacf11bSopenharmony_ci/****************************************************************************
1737beacf11bSopenharmony_ci * Name: tmpfs_unmount
1738beacf11bSopenharmony_ci ****************************************************************************/
1739beacf11bSopenharmony_ci
1740beacf11bSopenharmony_ciint tmpfs_unmount(struct Mount *mnt, struct Vnode **blkdriver)
1741beacf11bSopenharmony_ci{
1742beacf11bSopenharmony_ci  struct tmpfs_s *fs = (struct tmpfs_s *)mnt->data;
1743beacf11bSopenharmony_ci  struct tmpfs_directory_s *tdo;
1744beacf11bSopenharmony_ci  int ret = 0;
1745beacf11bSopenharmony_ci
1746beacf11bSopenharmony_ci  DEBUGASSERT(fs != NULL && fs->tfs_root.tde_object != NULL);
1747beacf11bSopenharmony_ci
1748beacf11bSopenharmony_ci  /* Lock the file system */
1749beacf11bSopenharmony_ci
1750beacf11bSopenharmony_ci  tmpfs_lock(fs);
1751beacf11bSopenharmony_ci
1752beacf11bSopenharmony_ci  tdo = (struct tmpfs_directory_s *)fs->tfs_root.tde_object;
1753beacf11bSopenharmony_ci  if (tdo == NULL)
1754beacf11bSopenharmony_ci    {
1755beacf11bSopenharmony_ci      ret = -EINVAL;
1756beacf11bSopenharmony_ci      goto errout_with_objects;
1757beacf11bSopenharmony_ci    }
1758beacf11bSopenharmony_ci
1759beacf11bSopenharmony_ci  if (tdo->tdo_nentries > 0 || tdo->tdo_refs > 1)
1760beacf11bSopenharmony_ci    {
1761beacf11bSopenharmony_ci      ret = -EBUSY;
1762beacf11bSopenharmony_ci      goto errout_with_objects;
1763beacf11bSopenharmony_ci    }
1764beacf11bSopenharmony_ci
1765beacf11bSopenharmony_ci  /* Now we can destroy the root file system and the file system itself. */
1766beacf11bSopenharmony_ci
1767beacf11bSopenharmony_ci  sem_destroy(&tdo->tdo_exclsem.ts_sem);
1768beacf11bSopenharmony_ci  kmm_free(tdo);
1769beacf11bSopenharmony_ci
1770beacf11bSopenharmony_ci  sem_destroy(&fs->tfs_exclsem.ts_sem);
1771beacf11bSopenharmony_ci  fs->tfs_root.tde_object = NULL;
1772beacf11bSopenharmony_ci
1773beacf11bSopenharmony_ci  tmpfs_unlock(fs);
1774beacf11bSopenharmony_ci  is_tmpfs_lock_init = false;
1775beacf11bSopenharmony_ci  return ret;
1776beacf11bSopenharmony_ci
1777beacf11bSopenharmony_cierrout_with_objects:
1778beacf11bSopenharmony_ci  tmpfs_unlock(fs);
1779beacf11bSopenharmony_ci  return ret;
1780beacf11bSopenharmony_ci}
1781beacf11bSopenharmony_ci
1782beacf11bSopenharmony_ci
1783beacf11bSopenharmony_ciint tmpfs_lookup(struct Vnode *parent, const char *relPath, int len, struct Vnode **vpp)
1784beacf11bSopenharmony_ci{
1785beacf11bSopenharmony_ci  // 1. when first time create file, lookup fail, then call tmpfs_create.
1786beacf11bSopenharmony_ci  // 2. when  ls, lookup will success to show.
1787beacf11bSopenharmony_ci  // 3. when cd, lookup success.
1788beacf11bSopenharmony_ci  struct tmpfs_object_s *to;
1789beacf11bSopenharmony_ci  struct tmpfs_s *fs;
1790beacf11bSopenharmony_ci  struct tmpfs_dirent_s *tde = NULL;
1791beacf11bSopenharmony_ci  struct tmpfs_directory_s *parent_tdo;
1792beacf11bSopenharmony_ci
1793beacf11bSopenharmony_ci  struct Vnode *vp = NULL;
1794beacf11bSopenharmony_ci  int ret = 0;
1795beacf11bSopenharmony_ci  char filename[len + 1];
1796beacf11bSopenharmony_ci  ret = memcpy_s(filename, (len + 1), relPath, len);
1797beacf11bSopenharmony_ci  if (ret != 0)
1798beacf11bSopenharmony_ci    {
1799beacf11bSopenharmony_ci        ret = -ENOMEM;
1800beacf11bSopenharmony_ci        goto errout;
1801beacf11bSopenharmony_ci    }
1802beacf11bSopenharmony_ci  filename[len] = '\0';
1803beacf11bSopenharmony_ci
1804beacf11bSopenharmony_ci  fs = parent->originMount->data;
1805beacf11bSopenharmony_ci  DEBUGASSERT(fs != NULL && fs->tfs_root.tde_object != NULL);
1806beacf11bSopenharmony_ci
1807beacf11bSopenharmony_ci  tmpfs_lock(fs);
1808beacf11bSopenharmony_ci
1809beacf11bSopenharmony_ci  parent_tdo = (struct tmpfs_directory_s *)(parent->data);
1810beacf11bSopenharmony_ci
1811beacf11bSopenharmony_ci  if (parent_tdo == NULL)
1812beacf11bSopenharmony_ci    {
1813beacf11bSopenharmony_ci      // if parent_tdo don't exist, find file in root.
1814beacf11bSopenharmony_ci      ret = tmpfs_find_object(fs, filename, &to, NULL);
1815beacf11bSopenharmony_ci      if (ret < 0)
1816beacf11bSopenharmony_ci        {
1817beacf11bSopenharmony_ci          goto errout_with_lock;
1818beacf11bSopenharmony_ci        }
1819beacf11bSopenharmony_ci    }
1820beacf11bSopenharmony_ci  else
1821beacf11bSopenharmony_ci    {
1822beacf11bSopenharmony_ci      if (parent_tdo->tdo_type != TMPFS_DIRECTORY)
1823beacf11bSopenharmony_ci        {
1824beacf11bSopenharmony_ci          ret = -ENOENT;
1825beacf11bSopenharmony_ci          goto errout_with_lock;
1826beacf11bSopenharmony_ci        }
1827beacf11bSopenharmony_ci      // if parent_tdo exist£¬search for the relationship between parent_tdo and the current dirname.
1828beacf11bSopenharmony_ci      tde = tmpfs_find_dirent(parent_tdo, filename);
1829beacf11bSopenharmony_ci      if (tde == NULL)
1830beacf11bSopenharmony_ci        {
1831beacf11bSopenharmony_ci          ret = -ENOENT;
1832beacf11bSopenharmony_ci          goto errout_with_lock;
1833beacf11bSopenharmony_ci        }
1834beacf11bSopenharmony_ci      to = tde->tde_object;
1835beacf11bSopenharmony_ci    }
1836beacf11bSopenharmony_ci
1837beacf11bSopenharmony_ci  if (to == NULL)
1838beacf11bSopenharmony_ci    {
1839beacf11bSopenharmony_ci      ret = -ENOENT;
1840beacf11bSopenharmony_ci      goto errout_with_lock;
1841beacf11bSopenharmony_ci    }
1842beacf11bSopenharmony_ci  tmpfs_lock_object(to);
1843beacf11bSopenharmony_ci  to->to_refs++;
1844beacf11bSopenharmony_ci
1845beacf11bSopenharmony_ci  (void)VfsHashGet(parent->originMount, (uint32_t)to, &vp, NULL, NULL);
1846beacf11bSopenharmony_ci  if (vp == NULL)
1847beacf11bSopenharmony_ci    {
1848beacf11bSopenharmony_ci      ret = VnodeAlloc(&tmpfs_vops, &vp);
1849beacf11bSopenharmony_ci      if (ret != 0)
1850beacf11bSopenharmony_ci        {
1851beacf11bSopenharmony_ci          PRINTK("%s-%d \n", __FUNCTION__, __LINE__);
1852beacf11bSopenharmony_ci          goto errout_with_objects;
1853beacf11bSopenharmony_ci        }
1854beacf11bSopenharmony_ci
1855beacf11bSopenharmony_ci      vp->vop = parent->vop;
1856beacf11bSopenharmony_ci      vp->fop = parent->fop;
1857beacf11bSopenharmony_ci      vp->data = to;
1858beacf11bSopenharmony_ci      vp->originMount = parent->originMount;
1859beacf11bSopenharmony_ci      vp->type = to->to_type == TMPFS_REGULAR ? VNODE_TYPE_REG : VNODE_TYPE_DIR;
1860beacf11bSopenharmony_ci      vp->mode = to->mode;
1861beacf11bSopenharmony_ci      vp->gid = to->gid;
1862beacf11bSopenharmony_ci      vp->uid = to->uid;
1863beacf11bSopenharmony_ci
1864beacf11bSopenharmony_ci      ret = VfsHashInsert(vp, (uint32_t)to);
1865beacf11bSopenharmony_ci    }
1866beacf11bSopenharmony_ci  vp->parent = parent;
1867beacf11bSopenharmony_ci
1868beacf11bSopenharmony_ci  *vpp = vp;
1869beacf11bSopenharmony_ci
1870beacf11bSopenharmony_ci  tmpfs_release_lockedobject(to);
1871beacf11bSopenharmony_ci  tmpfs_unlock(fs);
1872beacf11bSopenharmony_ci
1873beacf11bSopenharmony_ci  return 0;
1874beacf11bSopenharmony_ci
1875beacf11bSopenharmony_cierrout_with_objects:
1876beacf11bSopenharmony_ci  tmpfs_release_lockedobject(to);
1877beacf11bSopenharmony_cierrout_with_lock:
1878beacf11bSopenharmony_ci  tmpfs_unlock(fs);
1879beacf11bSopenharmony_cierrout:
1880beacf11bSopenharmony_ci  return ret;
1881beacf11bSopenharmony_ci}
1882beacf11bSopenharmony_ci
1883beacf11bSopenharmony_ciint tmpfs_reclaim(struct Vnode *vp)
1884beacf11bSopenharmony_ci{
1885beacf11bSopenharmony_ci    vp->data = NULL;
1886beacf11bSopenharmony_ci    return 0;
1887beacf11bSopenharmony_ci}
1888beacf11bSopenharmony_ci
1889beacf11bSopenharmony_ci/****************************************************************************
1890beacf11bSopenharmony_ci * Name: tmpfs_statfs
1891beacf11bSopenharmony_ci ****************************************************************************/
1892beacf11bSopenharmony_ci
1893beacf11bSopenharmony_ciint tmpfs_statfs(struct Mount *mp, struct statfs *sbp)
1894beacf11bSopenharmony_ci{
1895beacf11bSopenharmony_ci  (void)memset_s(sbp, sizeof(struct statfs), 0, sizeof(struct statfs));
1896beacf11bSopenharmony_ci
1897beacf11bSopenharmony_ci  sbp->f_type = TMPFS_MAGIC;
1898beacf11bSopenharmony_ci  sbp->f_flags = mp->mountFlags;
1899beacf11bSopenharmony_ci
1900beacf11bSopenharmony_ci  return OK;
1901beacf11bSopenharmony_ci}
1902beacf11bSopenharmony_ci
1903beacf11bSopenharmony_ci/****************************************************************************
1904beacf11bSopenharmony_ci * Name: tmpfs_unlink
1905beacf11bSopenharmony_ci ****************************************************************************/
1906beacf11bSopenharmony_ci
1907beacf11bSopenharmony_ciint tmpfs_unlink(struct Vnode *parent, struct Vnode *node, const char *relpath)
1908beacf11bSopenharmony_ci{
1909beacf11bSopenharmony_ci  struct tmpfs_s *fs;
1910beacf11bSopenharmony_ci  struct tmpfs_directory_s *parent_dir;
1911beacf11bSopenharmony_ci  struct tmpfs_file_s *tfo = NULL;
1912beacf11bSopenharmony_ci  int ret;
1913beacf11bSopenharmony_ci
1914beacf11bSopenharmony_ci  PRINT_INFO("mountpt: %p node: %p relpath: %s\n", parent, node, relpath);
1915beacf11bSopenharmony_ci  DEBUGASSERT(parent != NULL && node != NULL && relpath != NULL);
1916beacf11bSopenharmony_ci
1917beacf11bSopenharmony_ci  if (strlen(relpath) == 0)
1918beacf11bSopenharmony_ci    {
1919beacf11bSopenharmony_ci      return -EISDIR;
1920beacf11bSopenharmony_ci    }
1921beacf11bSopenharmony_ci
1922beacf11bSopenharmony_ci  /* Get the file system structure from the inode reference. */
1923beacf11bSopenharmony_ci  if (node->originMount == NULL)
1924beacf11bSopenharmony_ci    {
1925beacf11bSopenharmony_ci      return -EISDIR;
1926beacf11bSopenharmony_ci    }
1927beacf11bSopenharmony_ci
1928beacf11bSopenharmony_ci  fs = node->originMount->data;
1929beacf11bSopenharmony_ci  if (fs == NULL)
1930beacf11bSopenharmony_ci    {
1931beacf11bSopenharmony_ci      return -EISDIR;
1932beacf11bSopenharmony_ci    }
1933beacf11bSopenharmony_ci
1934beacf11bSopenharmony_ci  DEBUGASSERT(fs != NULL && fs->tfs_root.tde_object != NULL);
1935beacf11bSopenharmony_ci
1936beacf11bSopenharmony_ci  /* Get exclusive access to the file system */
1937beacf11bSopenharmony_ci
1938beacf11bSopenharmony_ci  tmpfs_lock(fs);
1939beacf11bSopenharmony_ci
1940beacf11bSopenharmony_ci  /* Find the file object and parent directory associated with this relative
1941beacf11bSopenharmony_ci   * path.  If successful, tmpfs_find_file will lock both the file object
1942beacf11bSopenharmony_ci   * and the parent directory and take one reference count on each.
1943beacf11bSopenharmony_ci   */
1944beacf11bSopenharmony_ci
1945beacf11bSopenharmony_ci  parent_dir = (struct tmpfs_directory_s *)(parent->data);
1946beacf11bSopenharmony_ci  if (parent_dir == NULL)
1947beacf11bSopenharmony_ci    {
1948beacf11bSopenharmony_ci      ret = tmpfs_find_file(fs, relpath, &tfo, &parent_dir);
1949beacf11bSopenharmony_ci      if (ret < 0)
1950beacf11bSopenharmony_ci        {
1951beacf11bSopenharmony_ci          goto errout_with_lock;
1952beacf11bSopenharmony_ci        }
1953beacf11bSopenharmony_ci    }
1954beacf11bSopenharmony_ci  else
1955beacf11bSopenharmony_ci    {
1956beacf11bSopenharmony_ci      tfo = (struct tmpfs_file_s *)node->data;
1957beacf11bSopenharmony_ci    }
1958beacf11bSopenharmony_ci
1959beacf11bSopenharmony_ci  if (tfo == NULL || parent_dir == NULL)
1960beacf11bSopenharmony_ci    {
1961beacf11bSopenharmony_ci      ret = -EISDIR;
1962beacf11bSopenharmony_ci      goto errout_with_lock;
1963beacf11bSopenharmony_ci    }
1964beacf11bSopenharmony_ci  DEBUGASSERT(tfo != NULL);
1965beacf11bSopenharmony_ci  tmpfs_lock_directory(parent_dir);
1966beacf11bSopenharmony_ci  tmpfs_lock_file(tfo);
1967beacf11bSopenharmony_ci
1968beacf11bSopenharmony_ci  /* Remove the file from parent directory */
1969beacf11bSopenharmony_ci  ret = tmpfs_remove_dirent(parent_dir, (struct tmpfs_object_s *)tfo);
1970beacf11bSopenharmony_ci  if (ret < 0)
1971beacf11bSopenharmony_ci    {
1972beacf11bSopenharmony_ci      goto errout_with_objects;
1973beacf11bSopenharmony_ci    }
1974beacf11bSopenharmony_ci
1975beacf11bSopenharmony_ci  /* If the reference count is not one, then just mark the file as
1976beacf11bSopenharmony_ci   * unlinked
1977beacf11bSopenharmony_ci   */
1978beacf11bSopenharmony_ci
1979beacf11bSopenharmony_ci  if (tfo->tfo_refs > 1)
1980beacf11bSopenharmony_ci    {
1981beacf11bSopenharmony_ci      /* Make the file object as unlinked */
1982beacf11bSopenharmony_ci
1983beacf11bSopenharmony_ci      tfo->tfo_flags |= TFO_FLAG_UNLINKED;
1984beacf11bSopenharmony_ci
1985beacf11bSopenharmony_ci      /* Release the reference count on the file object */
1986beacf11bSopenharmony_ci
1987beacf11bSopenharmony_ci      tfo->tfo_refs--;
1988beacf11bSopenharmony_ci      tmpfs_unlock_file(tfo);
1989beacf11bSopenharmony_ci    }
1990beacf11bSopenharmony_ci
1991beacf11bSopenharmony_ci  /* Otherwise we can free the object now */
1992beacf11bSopenharmony_ci
1993beacf11bSopenharmony_ci  else
1994beacf11bSopenharmony_ci    {
1995beacf11bSopenharmony_ci      sem_destroy(&tfo->tfo_exclsem.ts_sem);
1996beacf11bSopenharmony_ci      kmm_free(tfo->tfo_data);
1997beacf11bSopenharmony_ci      kmm_free(tfo);
1998beacf11bSopenharmony_ci      node->data = NULL;
1999beacf11bSopenharmony_ci    }
2000beacf11bSopenharmony_ci
2001beacf11bSopenharmony_ci  /* Release the reference and lock on the parent directory */
2002beacf11bSopenharmony_ci
2003beacf11bSopenharmony_ci  if (parent_dir->tdo_refs > 0)
2004beacf11bSopenharmony_ci    {
2005beacf11bSopenharmony_ci      parent_dir->tdo_refs--;
2006beacf11bSopenharmony_ci    }
2007beacf11bSopenharmony_ci  tmpfs_unlock_directory(parent_dir);
2008beacf11bSopenharmony_ci  tmpfs_unlock(fs);
2009beacf11bSopenharmony_ci
2010beacf11bSopenharmony_ci  return OK;
2011beacf11bSopenharmony_ci
2012beacf11bSopenharmony_cierrout_with_objects:
2013beacf11bSopenharmony_ci  tmpfs_release_lockedfile(tfo);
2014beacf11bSopenharmony_ci
2015beacf11bSopenharmony_ci  if (parent_dir->tdo_refs > 0)
2016beacf11bSopenharmony_ci    {
2017beacf11bSopenharmony_ci      parent_dir->tdo_refs--;
2018beacf11bSopenharmony_ci    }
2019beacf11bSopenharmony_ci
2020beacf11bSopenharmony_ci  tmpfs_unlock_directory(parent_dir);
2021beacf11bSopenharmony_ci
2022beacf11bSopenharmony_cierrout_with_lock:
2023beacf11bSopenharmony_ci  tmpfs_unlock(fs);
2024beacf11bSopenharmony_ci  return ret;
2025beacf11bSopenharmony_ci}
2026beacf11bSopenharmony_ci
2027beacf11bSopenharmony_ci/****************************************************************************
2028beacf11bSopenharmony_ci * Name: tmpfs_mkdir
2029beacf11bSopenharmony_ci ****************************************************************************/
2030beacf11bSopenharmony_ci
2031beacf11bSopenharmony_ciint tmpfs_mkdir(struct Vnode *parent, const char *relpath, mode_t mode, struct Vnode **vpp)
2032beacf11bSopenharmony_ci{
2033beacf11bSopenharmony_ci  struct tmpfs_s *fs;
2034beacf11bSopenharmony_ci  struct Vnode *vp = NULL;
2035beacf11bSopenharmony_ci  struct tmpfs_directory_s *tdo;
2036beacf11bSopenharmony_ci  struct tmpfs_directory_s *parent_tdo = NULL;
2037beacf11bSopenharmony_ci  int ret;
2038beacf11bSopenharmony_ci
2039beacf11bSopenharmony_ci  DEBUGASSERT(parent != NULL && relpath != NULL);
2040beacf11bSopenharmony_ci
2041beacf11bSopenharmony_ci  if (strlen(relpath) == 0)
2042beacf11bSopenharmony_ci    {
2043beacf11bSopenharmony_ci      return -EEXIST;
2044beacf11bSopenharmony_ci    }
2045beacf11bSopenharmony_ci
2046beacf11bSopenharmony_ci  /* Get the file system structure from the inode reference. */
2047beacf11bSopenharmony_ci
2048beacf11bSopenharmony_ci  fs = parent->originMount->data;
2049beacf11bSopenharmony_ci  DEBUGASSERT(fs != NULL && fs->tfs_root.tde_object != NULL);
2050beacf11bSopenharmony_ci
2051beacf11bSopenharmony_ci  /* Get exclusive access to the file system */
2052beacf11bSopenharmony_ci
2053beacf11bSopenharmony_ci  tmpfs_lock(fs);
2054beacf11bSopenharmony_ci
2055beacf11bSopenharmony_ci  if (parent->data != NULL)
2056beacf11bSopenharmony_ci    {
2057beacf11bSopenharmony_ci      parent_tdo = (struct tmpfs_directory_s *)(parent->data);
2058beacf11bSopenharmony_ci    }
2059beacf11bSopenharmony_ci  /* Create the directory. */
2060beacf11bSopenharmony_ci  ret = tmpfs_create_directory(fs, relpath, parent_tdo, &tdo);
2061beacf11bSopenharmony_ci  if (ret != OK)
2062beacf11bSopenharmony_ci    {
2063beacf11bSopenharmony_ci      goto errout_with_lock;
2064beacf11bSopenharmony_ci    }
2065beacf11bSopenharmony_ci
2066beacf11bSopenharmony_ci  ret = VnodeAlloc(&tmpfs_vops, &vp);
2067beacf11bSopenharmony_ci  if (ret != 0)
2068beacf11bSopenharmony_ci    {
2069beacf11bSopenharmony_ci      goto errout_with_lock;
2070beacf11bSopenharmony_ci    }
2071beacf11bSopenharmony_ci
2072beacf11bSopenharmony_ci  tdo->mode = mode;
2073beacf11bSopenharmony_ci  vp->parent = parent;
2074beacf11bSopenharmony_ci  vp->vop = parent->vop;
2075beacf11bSopenharmony_ci  vp->fop = parent->fop;
2076beacf11bSopenharmony_ci  vp->data = tdo;
2077beacf11bSopenharmony_ci  vp->originMount = parent->originMount;
2078beacf11bSopenharmony_ci  vp->type = VNODE_TYPE_DIR;
2079beacf11bSopenharmony_ci  vp->mode = tdo->mode;
2080beacf11bSopenharmony_ci  vp->gid = tdo->gid;
2081beacf11bSopenharmony_ci  vp->uid = tdo->uid;
2082beacf11bSopenharmony_ci
2083beacf11bSopenharmony_ci  ret = VfsHashInsert(vp, (uint32_t)tdo);
2084beacf11bSopenharmony_ci  *vpp = vp;
2085beacf11bSopenharmony_ci
2086beacf11bSopenharmony_cierrout_with_lock:
2087beacf11bSopenharmony_ci  tmpfs_unlock(fs);
2088beacf11bSopenharmony_ci  return ret;
2089beacf11bSopenharmony_ci}
2090beacf11bSopenharmony_ci
2091beacf11bSopenharmony_ci/****************************************************************************
2092beacf11bSopenharmony_ci * Name: tmpfs_rmdir
2093beacf11bSopenharmony_ci ****************************************************************************/
2094beacf11bSopenharmony_ci
2095beacf11bSopenharmony_ciint tmpfs_rmdir(struct Vnode *parent, struct Vnode *target, const char *dirname)
2096beacf11bSopenharmony_ci{
2097beacf11bSopenharmony_ci  struct tmpfs_s *fs;
2098beacf11bSopenharmony_ci  struct tmpfs_directory_s *parent_dir;
2099beacf11bSopenharmony_ci  struct tmpfs_directory_s *tdo;
2100beacf11bSopenharmony_ci  int ret = 0;
2101beacf11bSopenharmony_ci
2102beacf11bSopenharmony_ci  DEBUGASSERT(parent != NULL && target != NULL && dirname != NULL);
2103beacf11bSopenharmony_ci
2104beacf11bSopenharmony_ci  /* Get the file system structure from the inode reference. */
2105beacf11bSopenharmony_ci  fs = parent->originMount->data;
2106beacf11bSopenharmony_ci  if (fs == NULL)
2107beacf11bSopenharmony_ci    {
2108beacf11bSopenharmony_ci      return -EISDIR;
2109beacf11bSopenharmony_ci    }
2110beacf11bSopenharmony_ci  DEBUGASSERT(fs != NULL && fs->tfs_root.tde_object != NULL);
2111beacf11bSopenharmony_ci
2112beacf11bSopenharmony_ci  /* Get exclusive access to the file system */
2113beacf11bSopenharmony_ci
2114beacf11bSopenharmony_ci  tmpfs_lock(fs);
2115beacf11bSopenharmony_ci
2116beacf11bSopenharmony_ci  /* Find the directory object and parent directory associated with this
2117beacf11bSopenharmony_ci   * relative path.  If successful, tmpfs_find_file will lock both the
2118beacf11bSopenharmony_ci   * directory object and the parent directory and take one reference count
2119beacf11bSopenharmony_ci   * on each.
2120beacf11bSopenharmony_ci   */
2121beacf11bSopenharmony_ci  parent_dir = (struct tmpfs_directory_s *)(parent->data);
2122beacf11bSopenharmony_ci  if (parent_dir == NULL)
2123beacf11bSopenharmony_ci    {
2124beacf11bSopenharmony_ci      ret = tmpfs_find_directory(fs, dirname, &tdo, &parent_dir);
2125beacf11bSopenharmony_ci      if (ret < 0)
2126beacf11bSopenharmony_ci        {
2127beacf11bSopenharmony_ci          goto errout_with_lock;
2128beacf11bSopenharmony_ci        }
2129beacf11bSopenharmony_ci    }
2130beacf11bSopenharmony_ci  else
2131beacf11bSopenharmony_ci    {
2132beacf11bSopenharmony_ci      tdo = (struct tmpfs_directory_s *)target->data;
2133beacf11bSopenharmony_ci    }
2134beacf11bSopenharmony_ci
2135beacf11bSopenharmony_ci  if (tdo == NULL || tdo->tdo_type != TMPFS_DIRECTORY)
2136beacf11bSopenharmony_ci    {
2137beacf11bSopenharmony_ci      ret = -EISDIR;
2138beacf11bSopenharmony_ci      goto errout_with_lock;
2139beacf11bSopenharmony_ci    }
2140beacf11bSopenharmony_ci  tmpfs_lock_directory(parent_dir);
2141beacf11bSopenharmony_ci
2142beacf11bSopenharmony_ci  /* Is the directory empty?  We cannot remove directories that still
2143beacf11bSopenharmony_ci   * contain references to file system objects.  No can we remove the
2144beacf11bSopenharmony_ci   * directory if there are outstanding references on it (other than
2145beacf11bSopenharmony_ci   * our reference).
2146beacf11bSopenharmony_ci   */
2147beacf11bSopenharmony_ci
2148beacf11bSopenharmony_ci  if (tdo->tdo_nentries > 0 || tdo->tdo_refs > 1)
2149beacf11bSopenharmony_ci    {
2150beacf11bSopenharmony_ci      ret = -EBUSY;
2151beacf11bSopenharmony_ci      goto errout_with_objects;
2152beacf11bSopenharmony_ci    }
2153beacf11bSopenharmony_ci  /* Remove the directory from parent directory */
2154beacf11bSopenharmony_ci  ret = tmpfs_remove_dirent(parent_dir, (struct tmpfs_object_s *)tdo);
2155beacf11bSopenharmony_ci  if (ret < 0)
2156beacf11bSopenharmony_ci    {
2157beacf11bSopenharmony_ci      goto errout_with_objects;
2158beacf11bSopenharmony_ci    }
2159beacf11bSopenharmony_ci
2160beacf11bSopenharmony_ci  /* Free the directory object */
2161beacf11bSopenharmony_ci
2162beacf11bSopenharmony_ci  sem_destroy(&tdo->tdo_exclsem.ts_sem);
2163beacf11bSopenharmony_ci  kmm_free(tdo);
2164beacf11bSopenharmony_ci  target->data = NULL;
2165beacf11bSopenharmony_ci
2166beacf11bSopenharmony_ci  /* Release the reference and lock on the parent directory */
2167beacf11bSopenharmony_ci
2168beacf11bSopenharmony_ci  if (parent_dir->tdo_refs > 0)
2169beacf11bSopenharmony_ci    {
2170beacf11bSopenharmony_ci      parent_dir->tdo_refs--;
2171beacf11bSopenharmony_ci    }
2172beacf11bSopenharmony_ci
2173beacf11bSopenharmony_ci  tmpfs_unlock_directory(parent_dir);
2174beacf11bSopenharmony_ci  tmpfs_unlock(fs);
2175beacf11bSopenharmony_ci
2176beacf11bSopenharmony_ci  return OK;
2177beacf11bSopenharmony_ci
2178beacf11bSopenharmony_cierrout_with_objects:
2179beacf11bSopenharmony_ci  if (tdo->tdo_refs > 0)
2180beacf11bSopenharmony_ci    {
2181beacf11bSopenharmony_ci      tdo->tdo_refs--;
2182beacf11bSopenharmony_ci    }
2183beacf11bSopenharmony_ci  tmpfs_unlock_directory(tdo);
2184beacf11bSopenharmony_ci
2185beacf11bSopenharmony_ci  if (parent_dir->tdo_refs > 0)
2186beacf11bSopenharmony_ci    {
2187beacf11bSopenharmony_ci      parent_dir->tdo_refs--;
2188beacf11bSopenharmony_ci    }
2189beacf11bSopenharmony_ci  tmpfs_unlock_directory(parent_dir);
2190beacf11bSopenharmony_ci
2191beacf11bSopenharmony_cierrout_with_lock:
2192beacf11bSopenharmony_ci  tmpfs_unlock(fs);
2193beacf11bSopenharmony_ci  return ret;
2194beacf11bSopenharmony_ci}
2195beacf11bSopenharmony_ci
2196beacf11bSopenharmony_ci/****************************************************************************
2197beacf11bSopenharmony_ci * Name: tmpfs_rename
2198beacf11bSopenharmony_ci ****************************************************************************/
2199beacf11bSopenharmony_ci
2200beacf11bSopenharmony_ciint tmpfs_rename(struct Vnode *oldVnode, struct Vnode *newParent, const char *oldname, const char *newname)
2201beacf11bSopenharmony_ci{
2202beacf11bSopenharmony_ci  struct tmpfs_directory_s *oldparent;
2203beacf11bSopenharmony_ci  struct tmpfs_directory_s *newparent_tdo;
2204beacf11bSopenharmony_ci  struct tmpfs_object_s *old_to;
2205beacf11bSopenharmony_ci  struct tmpfs_dirent_s *tde;
2206beacf11bSopenharmony_ci  struct tmpfs_directory_s *tdo;
2207beacf11bSopenharmony_ci  struct tmpfs_file_s *tfo;
2208beacf11bSopenharmony_ci  struct tmpfs_s *fs;
2209beacf11bSopenharmony_ci  struct tmpfs_s *new_fs;
2210beacf11bSopenharmony_ci  struct Vnode *old_parent_vnode;
2211beacf11bSopenharmony_ci
2212beacf11bSopenharmony_ci  char *copy;
2213beacf11bSopenharmony_ci  int ret = 0;
2214beacf11bSopenharmony_ci  unsigned int oldrelpath_len, newrelpath_len, cmp_namelen;
2215beacf11bSopenharmony_ci
2216beacf11bSopenharmony_ci  oldrelpath_len = strlen(oldname);
2217beacf11bSopenharmony_ci  newrelpath_len = strlen(newname);
2218beacf11bSopenharmony_ci
2219beacf11bSopenharmony_ci  cmp_namelen = (oldrelpath_len <= newrelpath_len) ? oldrelpath_len : newrelpath_len;
2220beacf11bSopenharmony_ci  if (!cmp_namelen || ((!strncmp(oldname, newname, cmp_namelen)) &&
2221beacf11bSopenharmony_ci           (oldname[cmp_namelen] == '/' ||
2222beacf11bSopenharmony_ci            newname[cmp_namelen] == '/')))
2223beacf11bSopenharmony_ci    {
2224beacf11bSopenharmony_ci      return -EPERM;
2225beacf11bSopenharmony_ci    }
2226beacf11bSopenharmony_ci
2227beacf11bSopenharmony_ci  /* Get the file system structure from the inode reference. */
2228beacf11bSopenharmony_ci  if (oldVnode->parent == NULL)
2229beacf11bSopenharmony_ci    {
2230beacf11bSopenharmony_ci      return -EPERM;
2231beacf11bSopenharmony_ci    }
2232beacf11bSopenharmony_ci
2233beacf11bSopenharmony_ci  fs = oldVnode->parent->originMount->data;
2234beacf11bSopenharmony_ci  if (fs == NULL)
2235beacf11bSopenharmony_ci    {
2236beacf11bSopenharmony_ci      return -EPERM;
2237beacf11bSopenharmony_ci    }
2238beacf11bSopenharmony_ci
2239beacf11bSopenharmony_ci  DEBUGASSERT(fs != NULL && fs->tfs_root.tde_object != NULL);
2240beacf11bSopenharmony_ci
2241beacf11bSopenharmony_ci  /* Duplicate the newpath variable so that we can modify it */
2242beacf11bSopenharmony_ci
2243beacf11bSopenharmony_ci  copy = strdup(newname);
2244beacf11bSopenharmony_ci  if (copy == NULL)
2245beacf11bSopenharmony_ci    {
2246beacf11bSopenharmony_ci      return -ENOSPC;
2247beacf11bSopenharmony_ci    }
2248beacf11bSopenharmony_ci
2249beacf11bSopenharmony_ci  /* Get exclusive access to the file system */
2250beacf11bSopenharmony_ci
2251beacf11bSopenharmony_ci  tmpfs_lock(fs);
2252beacf11bSopenharmony_ci
2253beacf11bSopenharmony_ci  /* Separate the new path into the new file name and the path to the new
2254beacf11bSopenharmony_ci   * parent directory.
2255beacf11bSopenharmony_ci   */
2256beacf11bSopenharmony_ci  newparent_tdo = (struct tmpfs_directory_s *)(newParent->data);
2257beacf11bSopenharmony_ci  if (newparent_tdo == NULL)
2258beacf11bSopenharmony_ci    {
2259beacf11bSopenharmony_ci      new_fs = newParent->originMount->data;
2260beacf11bSopenharmony_ci      newparent_tdo = (struct tmpfs_directory_s *)new_fs->tfs_root.tde_object;
2261beacf11bSopenharmony_ci      if (newparent_tdo == NULL)
2262beacf11bSopenharmony_ci        {
2263beacf11bSopenharmony_ci          ret = -ENOTEMPTY;
2264beacf11bSopenharmony_ci          goto errout_with_lock;
2265beacf11bSopenharmony_ci        }
2266beacf11bSopenharmony_ci      tmpfs_lock_directory(newparent_tdo);
2267beacf11bSopenharmony_ci      newparent_tdo->tdo_refs++;
2268beacf11bSopenharmony_ci    }
2269beacf11bSopenharmony_ci
2270beacf11bSopenharmony_ci  /* Find the old object at oldpath.  If successful, tmpfs_find_object()
2271beacf11bSopenharmony_ci   * will lock both the object and the parent directory and will increment
2272beacf11bSopenharmony_ci   * the reference count on both.
2273beacf11bSopenharmony_ci   */
2274beacf11bSopenharmony_ci  old_parent_vnode = oldVnode->parent;
2275beacf11bSopenharmony_ci  oldparent = (struct tmpfs_directory_s *)(old_parent_vnode->data);
2276beacf11bSopenharmony_ci  old_to = (struct tmpfs_object_s *)oldVnode->data;
2277beacf11bSopenharmony_ci
2278beacf11bSopenharmony_ci  if (oldparent == NULL)
2279beacf11bSopenharmony_ci    {
2280beacf11bSopenharmony_ci      oldparent = (struct tmpfs_directory_s *)fs->tfs_root.tde_object;
2281beacf11bSopenharmony_ci      if (oldparent == NULL || old_to == NULL)
2282beacf11bSopenharmony_ci        {
2283beacf11bSopenharmony_ci          ret = -ENOTEMPTY;
2284beacf11bSopenharmony_ci          goto errout_with_newparent;
2285beacf11bSopenharmony_ci        }
2286beacf11bSopenharmony_ci    }
2287beacf11bSopenharmony_ci
2288beacf11bSopenharmony_ci  tmpfs_lock_directory(oldparent);
2289beacf11bSopenharmony_ci  tmpfs_lock_object(old_to);
2290beacf11bSopenharmony_ci  oldparent->tdo_refs++;
2291beacf11bSopenharmony_ci  old_to->to_refs++;
2292beacf11bSopenharmony_ci  tde = tmpfs_find_dirent(newparent_tdo, copy);
2293beacf11bSopenharmony_ci  if (tde != NULL)
2294beacf11bSopenharmony_ci    {
2295beacf11bSopenharmony_ci      struct tmpfs_object_s *new_to = tde->tde_object;
2296beacf11bSopenharmony_ci
2297beacf11bSopenharmony_ci      /* Cannot rename a directory to a noempty directory */
2298beacf11bSopenharmony_ci
2299beacf11bSopenharmony_ci      if (tde->tde_object->to_type == TMPFS_DIRECTORY)
2300beacf11bSopenharmony_ci        {
2301beacf11bSopenharmony_ci          tdo = (struct tmpfs_directory_s *)new_to;
2302beacf11bSopenharmony_ci          if (tdo->tdo_nentries != 0)
2303beacf11bSopenharmony_ci            {
2304beacf11bSopenharmony_ci              ret = -ENOTEMPTY;
2305beacf11bSopenharmony_ci              goto errout_with_oldparent;
2306beacf11bSopenharmony_ci            }
2307beacf11bSopenharmony_ci        }
2308beacf11bSopenharmony_ci
2309beacf11bSopenharmony_ci      /* Null rename, just return */
2310beacf11bSopenharmony_ci
2311beacf11bSopenharmony_ci      if (old_to == new_to)
2312beacf11bSopenharmony_ci        {
2313beacf11bSopenharmony_ci          ret = ENOERR;
2314beacf11bSopenharmony_ci          goto errout_with_oldparent;
2315beacf11bSopenharmony_ci        }
2316beacf11bSopenharmony_ci
2317beacf11bSopenharmony_ci      /* Check that we are renaming like-for-like */
2318beacf11bSopenharmony_ci
2319beacf11bSopenharmony_ci      if (old_to->to_type == TMPFS_REGULAR && new_to->to_type == TMPFS_DIRECTORY)
2320beacf11bSopenharmony_ci        {
2321beacf11bSopenharmony_ci          ret = -EISDIR;
2322beacf11bSopenharmony_ci          goto errout_with_oldparent;
2323beacf11bSopenharmony_ci        }
2324beacf11bSopenharmony_ci
2325beacf11bSopenharmony_ci      if (old_to->to_type == TMPFS_DIRECTORY && new_to->to_type == TMPFS_REGULAR)
2326beacf11bSopenharmony_ci        {
2327beacf11bSopenharmony_ci          ret = -ENOTDIR;
2328beacf11bSopenharmony_ci          goto errout_with_oldparent;
2329beacf11bSopenharmony_ci        }
2330beacf11bSopenharmony_ci
2331beacf11bSopenharmony_ci      /* Now delete the destination directory entry */
2332beacf11bSopenharmony_ci
2333beacf11bSopenharmony_ci      ret = tmpfs_remove_dirent(newparent_tdo, new_to);
2334beacf11bSopenharmony_ci      if (ret < 0)
2335beacf11bSopenharmony_ci        {
2336beacf11bSopenharmony_ci          goto errout_with_oldparent;
2337beacf11bSopenharmony_ci        }
2338beacf11bSopenharmony_ci
2339beacf11bSopenharmony_ci      if (new_to->to_type == TMPFS_DIRECTORY)
2340beacf11bSopenharmony_ci        {
2341beacf11bSopenharmony_ci          (void)sem_destroy(&new_to->to_exclsem.ts_sem);
2342beacf11bSopenharmony_ci          kmm_free(new_to);
2343beacf11bSopenharmony_ci        }
2344beacf11bSopenharmony_ci      else
2345beacf11bSopenharmony_ci        {
2346beacf11bSopenharmony_ci          tfo = (struct tmpfs_file_s *)new_to;
2347beacf11bSopenharmony_ci          if (new_to->to_refs > 0)
2348beacf11bSopenharmony_ci            {
2349beacf11bSopenharmony_ci              /* Make the file object as unlinked */
2350beacf11bSopenharmony_ci
2351beacf11bSopenharmony_ci              tfo->tfo_flags |= TFO_FLAG_UNLINKED;
2352beacf11bSopenharmony_ci            }
2353beacf11bSopenharmony_ci
2354beacf11bSopenharmony_ci          /* Otherwise we can free the object now */
2355beacf11bSopenharmony_ci
2356beacf11bSopenharmony_ci          else
2357beacf11bSopenharmony_ci            {
2358beacf11bSopenharmony_ci              (void)sem_destroy(&tfo->tfo_exclsem.ts_sem);
2359beacf11bSopenharmony_ci              kmm_free(tfo->tfo_data);
2360beacf11bSopenharmony_ci              kmm_free(tfo);
2361beacf11bSopenharmony_ci            }
2362beacf11bSopenharmony_ci        }
2363beacf11bSopenharmony_ci    }
2364beacf11bSopenharmony_ci
2365beacf11bSopenharmony_ci  /* Remove the entry from the parent directory */
2366beacf11bSopenharmony_ci
2367beacf11bSopenharmony_ci  ret = tmpfs_remove_dirent(oldparent, old_to);
2368beacf11bSopenharmony_ci  if (ret < 0)
2369beacf11bSopenharmony_ci    {
2370beacf11bSopenharmony_ci      goto errout_with_oldparent;
2371beacf11bSopenharmony_ci    }
2372beacf11bSopenharmony_ci
2373beacf11bSopenharmony_ci  /* Add an entry to the new parent directory. */
2374beacf11bSopenharmony_ci
2375beacf11bSopenharmony_ci  ret = tmpfs_add_dirent(&newparent_tdo, old_to, copy);
2376beacf11bSopenharmony_ci  oldVnode->parent = newParent;
2377beacf11bSopenharmony_ci
2378beacf11bSopenharmony_cierrout_with_oldparent:
2379beacf11bSopenharmony_ci  if (oldparent == NULL)
2380beacf11bSopenharmony_ci    {
2381beacf11bSopenharmony_ci      tmpfs_unlock(fs);
2382beacf11bSopenharmony_ci      kmm_free(copy);
2383beacf11bSopenharmony_ci      return ret;
2384beacf11bSopenharmony_ci    }
2385beacf11bSopenharmony_ci  if (oldparent->tdo_refs > 0)
2386beacf11bSopenharmony_ci    {
2387beacf11bSopenharmony_ci      oldparent->tdo_refs--;
2388beacf11bSopenharmony_ci    }
2389beacf11bSopenharmony_ci  tmpfs_unlock_directory(oldparent);
2390beacf11bSopenharmony_ci  tmpfs_release_lockedobject(old_to);
2391beacf11bSopenharmony_ci
2392beacf11bSopenharmony_cierrout_with_newparent:
2393beacf11bSopenharmony_ci  if (newparent_tdo == NULL)
2394beacf11bSopenharmony_ci    {
2395beacf11bSopenharmony_ci      tmpfs_unlock(fs);
2396beacf11bSopenharmony_ci      kmm_free(copy);
2397beacf11bSopenharmony_ci      return ret;
2398beacf11bSopenharmony_ci    }
2399beacf11bSopenharmony_ci  if (newparent_tdo->tdo_refs > 0)
2400beacf11bSopenharmony_ci    {
2401beacf11bSopenharmony_ci      newparent_tdo->tdo_refs--;
2402beacf11bSopenharmony_ci    }
2403beacf11bSopenharmony_ci  tmpfs_unlock_directory(newparent_tdo);
2404beacf11bSopenharmony_ci
2405beacf11bSopenharmony_cierrout_with_lock:
2406beacf11bSopenharmony_ci  tmpfs_unlock(fs);
2407beacf11bSopenharmony_ci  kmm_free(copy);
2408beacf11bSopenharmony_ci  return ret;
2409beacf11bSopenharmony_ci}
2410beacf11bSopenharmony_ci
2411beacf11bSopenharmony_ci/****************************************************************************
2412beacf11bSopenharmony_ci * Name: tmpfs_stat_common
2413beacf11bSopenharmony_ci ****************************************************************************/
2414beacf11bSopenharmony_ci
2415beacf11bSopenharmony_cistatic void tmpfs_stat_common(struct tmpfs_object_s *to,
2416beacf11bSopenharmony_ci                              struct stat *buf)
2417beacf11bSopenharmony_ci{
2418beacf11bSopenharmony_ci  size_t objsize;
2419beacf11bSopenharmony_ci
2420beacf11bSopenharmony_ci  /* Is the tmpfs object a regular file? */
2421beacf11bSopenharmony_ci
2422beacf11bSopenharmony_ci  (VOID)memset_s(buf, sizeof(struct stat), 0, sizeof(struct stat));
2423beacf11bSopenharmony_ci
2424beacf11bSopenharmony_ci  if (to->to_type == TMPFS_REGULAR)
2425beacf11bSopenharmony_ci    {
2426beacf11bSopenharmony_ci      struct tmpfs_file_s *tfo =
2427beacf11bSopenharmony_ci        (struct tmpfs_file_s *)to;
2428beacf11bSopenharmony_ci
2429beacf11bSopenharmony_ci      /* -rwxrwxrwx */
2430beacf11bSopenharmony_ci
2431beacf11bSopenharmony_ci      buf->st_mode = S_IRWXO | S_IRWXG | S_IRWXU | S_IFREG;
2432beacf11bSopenharmony_ci      buf->st_nlink = tfo->tfo_refs - 1;
2433beacf11bSopenharmony_ci
2434beacf11bSopenharmony_ci      /* Get the size of the object */
2435beacf11bSopenharmony_ci
2436beacf11bSopenharmony_ci      objsize = tfo->tfo_size;
2437beacf11bSopenharmony_ci    }
2438beacf11bSopenharmony_ci  else /* if (to->to_type == TMPFS_DIRECTORY) */
2439beacf11bSopenharmony_ci    {
2440beacf11bSopenharmony_ci      struct tmpfs_directory_s *tdo =
2441beacf11bSopenharmony_ci        (struct tmpfs_directory_s *)to;
2442beacf11bSopenharmony_ci
2443beacf11bSopenharmony_ci      /* drwxrwxrwx */
2444beacf11bSopenharmony_ci
2445beacf11bSopenharmony_ci      buf->st_mode = S_IRWXO | S_IRWXG | S_IRWXU | S_IFDIR;
2446beacf11bSopenharmony_ci      buf->st_nlink   = tdo->tdo_nentries + tdo->tdo_refs;
2447beacf11bSopenharmony_ci
2448beacf11bSopenharmony_ci      /* Get the size of the object */
2449beacf11bSopenharmony_ci
2450beacf11bSopenharmony_ci      objsize = sizeof(struct tmpfs_directory_s);
2451beacf11bSopenharmony_ci    }
2452beacf11bSopenharmony_ci
2453beacf11bSopenharmony_ci  /* Fake the rest of the information */
2454beacf11bSopenharmony_ci
2455beacf11bSopenharmony_ci  buf->st_size    = objsize;
2456beacf11bSopenharmony_ci  buf->st_blksize = 0;
2457beacf11bSopenharmony_ci  buf->st_blocks  = 0;
2458beacf11bSopenharmony_ci  buf->st_atime   = to->to_atime;
2459beacf11bSopenharmony_ci  buf->st_mtime   = to->to_mtime;
2460beacf11bSopenharmony_ci  buf->st_ctime   = to->to_ctime;
2461beacf11bSopenharmony_ci
2462beacf11bSopenharmony_ci  /* Adapt to kstat member "long tv_sec" */
2463beacf11bSopenharmony_ci  buf->__st_atim32.tv_sec = (long)to->to_atime;
2464beacf11bSopenharmony_ci  buf->__st_mtim32.tv_sec = (long)to->to_mtime;
2465beacf11bSopenharmony_ci  buf->__st_ctim32.tv_sec = (long)to->to_ctime;
2466beacf11bSopenharmony_ci
2467beacf11bSopenharmony_ci}
2468beacf11bSopenharmony_ci
2469beacf11bSopenharmony_ci/****************************************************************************
2470beacf11bSopenharmony_ci * Name: tmpfs_stat
2471beacf11bSopenharmony_ci ****************************************************************************/
2472beacf11bSopenharmony_ci
2473beacf11bSopenharmony_ciint tmpfs_stat(struct Vnode *vp, struct stat *st)
2474beacf11bSopenharmony_ci{
2475beacf11bSopenharmony_ci  struct tmpfs_s *fs;
2476beacf11bSopenharmony_ci  struct tmpfs_object_s *to;
2477beacf11bSopenharmony_ci  int ret;
2478beacf11bSopenharmony_ci
2479beacf11bSopenharmony_ci  DEBUGASSERT(vp != NULL && st != NULL);
2480beacf11bSopenharmony_ci  /* Get the file system structure from the inode reference. */
2481beacf11bSopenharmony_ci
2482beacf11bSopenharmony_ci  fs = vp->originMount->data;
2483beacf11bSopenharmony_ci  DEBUGASSERT(fs != NULL && fs->tfs_root.tde_object != NULL);
2484beacf11bSopenharmony_ci
2485beacf11bSopenharmony_ci  /* Get exclusive access to the file system */
2486beacf11bSopenharmony_ci
2487beacf11bSopenharmony_ci  tmpfs_lock(fs);
2488beacf11bSopenharmony_ci
2489beacf11bSopenharmony_ci  /* Find the tmpfs object at the relpath.  If successful,
2490beacf11bSopenharmony_ci   * tmpfs_find_object() will lock the object and increment the
2491beacf11bSopenharmony_ci   * reference count on the object.
2492beacf11bSopenharmony_ci   */
2493beacf11bSopenharmony_ci  if (vp->data != NULL)
2494beacf11bSopenharmony_ci    {
2495beacf11bSopenharmony_ci      to = (struct tmpfs_object_s *)vp->data;
2496beacf11bSopenharmony_ci    }
2497beacf11bSopenharmony_ci  else
2498beacf11bSopenharmony_ci    {
2499beacf11bSopenharmony_ci      to = fs->tfs_root.tde_object;
2500beacf11bSopenharmony_ci    }
2501beacf11bSopenharmony_ci  tmpfs_lock_object(to);
2502beacf11bSopenharmony_ci  to->to_refs++;
2503beacf11bSopenharmony_ci
2504beacf11bSopenharmony_ci  /* We found it... Return information about the file object in the stat
2505beacf11bSopenharmony_ci   * buffer.
2506beacf11bSopenharmony_ci   */
2507beacf11bSopenharmony_ci  if(to == NULL)
2508beacf11bSopenharmony_ci    {
2509beacf11bSopenharmony_ci      ret = -ENOENT;
2510beacf11bSopenharmony_ci      goto errout_with_fslock;
2511beacf11bSopenharmony_ci    }
2512beacf11bSopenharmony_ci  DEBUGASSERT(to != NULL);
2513beacf11bSopenharmony_ci  tmpfs_stat_common(to, st);
2514beacf11bSopenharmony_ci
2515beacf11bSopenharmony_ci  /* Unlock the object and return success */
2516beacf11bSopenharmony_ci
2517beacf11bSopenharmony_ci  tmpfs_release_lockedobject(to);
2518beacf11bSopenharmony_ci  ret = OK;
2519beacf11bSopenharmony_ci
2520beacf11bSopenharmony_cierrout_with_fslock:
2521beacf11bSopenharmony_ci  tmpfs_unlock(fs);
2522beacf11bSopenharmony_ci  return ret;
2523beacf11bSopenharmony_ci}
2524beacf11bSopenharmony_ci
2525beacf11bSopenharmony_ciFSMAP_ENTRY(ramfs_fsmap, "ramfs", tmpfs_operations, FALSE, FALSE);
2526beacf11bSopenharmony_ci
2527beacf11bSopenharmony_ci#endif
2528beacf11bSopenharmony_ci
2529