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