1/**************************************************************************** 2 * fs/inode/fs_files.c 3 * 4 * Copyright (c) 2023 Huawei Device Co., Ltd. All rights reserved. 5 * Based on NuttX originally written by Gregory Nutt 6 * 7 * Copyright (C) 2007-2009, 2011-2013, 2016-2017 Gregory Nutt. All rights 8 * reserved. 9 * Author: Gregory Nutt <gnutt@nuttx.org> 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in 19 * the documentation and/or other materials provided with the 20 * distribution. 21 * 3. Neither the name NuttX nor the names of its contributors may be 22 * used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 28 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 29 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 31 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 32 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 33 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 35 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 * 38 ****************************************************************************/ 39 40/**************************************************************************** 41 * Included Files 42 ****************************************************************************/ 43#include "unistd.h" 44#include "vfs_config.h" 45#include "sys/types.h" 46#include "string.h" 47#include "dirent.h" 48#include "semaphore.h" 49#include "assert.h" 50#include "errno.h" 51#include "fs/file.h" 52#include "stdio.h" 53#include "stdlib.h" 54#include "vnode.h" 55#include "los_mux.h" 56#include "fs/fd_table.h" 57#ifdef LOSCFG_NET_LWIP_SACK 58#include "lwip/sockets.h" 59#endif 60#include "los_process_pri.h" 61#include "los_vm_filemap.h" 62#include "mqueue.h" 63#define ferr PRINTK 64 65#if CONFIG_NFILE_DESCRIPTORS > 0 66struct filelist tg_filelist = { 0 }; 67#endif 68 69/**************************************************************************** 70 * Pre-processor Definitions 71 ****************************************************************************/ 72 73struct filelist *sched_getfiles(void) 74{ 75#if CONFIG_NFILE_DESCRIPTORS > 0 76 return &tg_filelist; 77#else 78 return NULL; 79#endif 80} 81 82/* 32: An unsigned int takes 32 bits */ 83 84static unsigned int bitmap[CONFIG_NFILE_DESCRIPTORS / 32 + 1] = {0}; 85 86static void set_bit(int i, void *addr) 87{ 88 unsigned int tem = (unsigned int)i >> 5; /* Get the bitmap subscript */ 89 unsigned int *addri = (unsigned int *)addr + tem; 90 unsigned int old = *addri; 91 old = old | (1UL << ((unsigned int)i & 0x1f)); /* set the new map bit */ 92 *addri = old; 93} 94 95static void clear_bit(int i, void *addr) 96{ 97 unsigned int tem = (unsigned int)i >> 5; /* Get the bitmap subscript */ 98 unsigned int *addri = (unsigned int *)addr + tem; 99 unsigned int old = *addri; 100 old = old & ~(1UL << ((unsigned int)i & 0x1f)); /* Clear the old map bit */ 101 *addri = old; 102} 103 104bool get_bit(int i) 105{ 106 unsigned int *p = NULL; 107 unsigned int mask; 108 109 p = ((unsigned int *)bitmap) + (i >> 5); /* Gets the location in the bitmap */ 110 mask = 1 << (i & 0x1f); /* Gets the mask for the current bit int bitmap */ 111 if (!(~(*p) & mask)){ 112 return true; 113 } 114 return false; 115} 116 117/**************************************************************************** 118 * Private Functions 119 ****************************************************************************/ 120 121/**************************************************************************** 122 * Name: _files_semtake 123 ****************************************************************************/ 124 125static void _files_semtake(struct filelist *list) 126{ 127 /* Take the semaphore (perhaps waiting) */ 128 129 while (sem_wait(&list->fl_sem) != 0) 130 { 131 /* The only case that an error should occur here is if the wait was 132 * awakened by a signal. 133 */ 134 135 LOS_ASSERT(get_errno() == EINTR); 136 } 137} 138 139/**************************************************************************** 140 * Name: _files_semgive 141 ****************************************************************************/ 142 143#define _files_semgive(list) (void)sem_post(&list->fl_sem) 144 145void file_hold(struct file *filep) 146{ 147 struct filelist *list = sched_getfiles(); 148 if (!list) 149 { 150 return; 151 } 152 153 _files_semtake(list); 154 if (filep != NULL) 155 { 156 assert(filep->f_refcount > 0); 157 filep->f_refcount++; 158 } 159 _files_semgive(list); 160} 161 162void file_release(struct file *filep) 163{ 164 struct filelist *list = sched_getfiles(); 165 if (!list) 166 { 167 return; 168 } 169 170 _files_semtake(list); 171 if (filep != NULL) 172 { 173 assert(filep->f_refcount > 0); 174 filep->f_refcount--; 175 } 176 _files_semgive(list); 177} 178 179/**************************************************************************** 180 * Name: _files_close 181 * 182 * Description: 183 * Close an vnode (if open) 184 * 185 * Assumuptions: 186 * Caller holds the list semaphore because the file descriptor will be freed. 187 * 188 ****************************************************************************/ 189 190static int _files_close(struct file *filep) 191{ 192 struct Vnode *vnode = filep->f_vnode; 193 int ret = OK; 194 195 /* Check if the struct file is open (i.e., assigned an vnode) */ 196 if (filep->f_oflags & O_DIRECTORY) 197 { 198 ret = closedir(filep->f_dir); 199 if (ret != OK) 200 { 201 return ret; 202 } 203 } 204 else 205 { 206 /* Close the file, driver, or mountpoint. */ 207 if (filep->ops && filep->ops->close) 208 { 209 /* Perform the close operation */ 210 211 ret = filep->ops->close(filep); 212 if (ret != OK) 213 { 214 return ret; 215 } 216 } 217 VnodeHold(); 218 vnode->useCount--; 219 /* Block char device is removed when close */ 220 if (vnode->type == VNODE_TYPE_BCHR) 221 { 222 ret = VnodeFree(vnode); 223 if (ret < 0) 224 { 225 PRINTK("Removing bchar device %s failed\n", filep->f_path); 226 } 227 } 228 VnodeDrop(); 229 } 230 231 /* Release the file descriptor */ 232 233 memset(filep, 0, sizeof(struct file)); 234 filep->fd = -1; 235 236 return ret; 237} 238 239/**************************************************************************** 240 * Public Functions 241 ****************************************************************************/ 242 243/**************************************************************************** 244 * Name: files_initialize 245 * 246 * Description: 247 * This is called from the FS initialization logic to configure the files. 248 * 249 ****************************************************************************/ 250 251void files_initialize(void) 252{ 253} 254 255/**************************************************************************** 256 * Name: files_initlist 257 * 258 * Description: Initializes the list of files for a new task 259 * 260 ****************************************************************************/ 261 262void files_initlist(struct filelist *list) 263{ 264 DEBUGASSERT(list); 265 266 /* Initialize the list access mutex */ 267 268 (void)sem_init(&list->fl_sem, 0, 1); 269} 270 271/**************************************************************************** 272 * Name: files_releaselist 273 * 274 * Description: 275 * Release a reference to the file list 276 * 277 ****************************************************************************/ 278 279void files_releaselist(struct filelist *list) 280{ 281 int i; 282 283 DEBUGASSERT(list); 284 285 /* Close each file descriptor .. Normally, you would need take the list 286 * semaphore, but it is safe to ignore the semaphore in this context because 287 * there should not be any references in this context. 288 */ 289 290 for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) 291 { 292 (void)_files_close(&list->fl_files[i]); 293 } 294 295 /* Destroy the semaphore */ 296 297 (void)sem_destroy(&list->fl_sem); 298} 299 300/**************************************************************************** 301 * Name: file_dup2 302 * 303 * Description: 304 * Assign an vnode to a specific files structure. This is the heart of 305 * dup2. 306 * 307 * Equivalent to the non-standard fs_dupfd2() function except that it 308 * accepts struct file instances instead of file descriptors and it does 309 * not set the errno variable. 310 * 311 * Returned Value: 312 * Zero (OK) is returned on success; a negated errno value is return on 313 * any failure. 314 * 315 ****************************************************************************/ 316 317int file_dup2(struct file *filep1, struct file *filep2) 318{ 319 struct filelist *list = NULL; 320 struct Vnode *vnode_ptr = NULL; 321 int err; 322 int ret; 323 324 if (!filep1 || !filep1->f_vnode || !filep2) 325 { 326 err = -EBADF; 327 goto errout; 328 } 329 330 list = sched_getfiles(); 331 DEBUGASSERT(list); 332 /* The file list can be NULL under two cases: (1) One is an obscure 333 * cornercase: When memory management debug output is enabled. Then 334 * there may be attempts to write to stdout from malloc before the group 335 * data has been allocated. The other other is (2) if this is a kernel 336 * thread. Kernel threads have no allocated file descriptors. 337 */ 338 339 if (list != NULL) 340 { 341 _files_semtake(list); 342 } 343 344 /* If there is already an vnode contained in the new file structure, 345 * close the file and release the vnode. 346 */ 347 348 ret = _files_close(filep2); 349 if (ret < 0) 350 { 351 /* An error occurred while closing the driver */ 352 353 goto errout_with_ret; 354 } 355 356 /* Increment the reference count on the contained vnode */ 357 358 vnode_ptr = filep1->f_vnode; 359 360 /* Then clone the file structure */ 361 362 filep2->f_oflags = filep1->f_oflags; 363 filep2->f_pos = filep1->f_pos; 364 filep2->f_vnode = filep1->f_vnode; 365 filep2->f_priv = filep1->f_priv; 366 filep2->f_path = filep1->f_path; 367 filep2->ops = filep1->ops; 368 filep2->f_refcount = filep1->f_refcount; 369 370 /* Call the open method on the file, driver, mountpoint so that it 371 * can maintain the correct open counts. 372 */ 373 if (vnode_ptr->vop) 374 { 375 if (vnode_ptr->flag & VNODE_FLAG_MOUNT_NEW) 376 { 377 ret = -ENOSYS; 378 } 379 else 380 { 381 /* (Re-)open the pseudo file or device driver */ 382 383 if (vnode_ptr->vop->Open) 384 { 385 ret = vnode_ptr->vop->Open(vnode_ptr, 0, 0, 0); 386 } 387 else 388 { 389 ret = -ENOSYS; 390 } 391 } 392 393 /* Handle open failures */ 394 395 if (ret < 0) 396 { 397 goto errout_with_vnode; 398 } 399 } 400 401 if (list != NULL) 402 { 403 _files_semgive(list); 404 } 405 return OK; 406 407 /* Handle various error conditions */ 408 409errout_with_vnode: 410 memset(filep2, 0, sizeof(struct file)); 411 filep2->fd = -1; 412 413errout_with_ret: 414 err = -ret; 415 _files_semgive(list); 416 417errout: 418 set_errno(err); 419 return VFS_ERROR; 420} 421 422struct file *files_allocate(const struct Vnode *vnode_ptr, int oflags, off_t pos, const void *priv, int minfd) 423{ 424 struct filelist *list = NULL; 425 unsigned int *p = NULL; 426 unsigned int mask; 427 unsigned int i; 428 struct file *filep = NULL; 429 430 if (minfd < FILE_START_FD) 431 { 432 minfd = FILE_START_FD; 433 } 434 i = (unsigned int)minfd; 435 436 list = sched_getfiles(); 437 DEBUGASSERT(list); 438 439 _files_semtake(list); 440 441 while (i < CONFIG_NFILE_DESCRIPTORS) 442 { 443 p = ((unsigned int *)bitmap) + (i >> 5); /* Gets the location in the bitmap */ 444 mask = 1 << (i & 0x1f); /* Gets the mask for the current bit int bitmap */ 445 if ((~(*p) & mask)) 446 { 447 set_bit(i, bitmap); 448 filep = &list->fl_files[i]; 449 filep->f_oflags = oflags; 450 filep->f_pos = pos; 451 filep->f_vnode = (struct Vnode *)vnode_ptr; 452 filep->f_priv = (void *)priv; 453 filep->f_refcount = 1; 454 filep->f_mapping = (struct page_mapping *)&vnode_ptr->mapping; 455 filep->f_dir = NULL; 456 filep->f_path = vnode_ptr->filePath; 457 filep->fd = i; 458 filep->ops = vnode_ptr->fop; 459 _files_semgive(list); 460 return filep; 461 } 462 i++; 463 } 464 465 _files_semgive(list); 466 return NULL; 467} 468 469int files_close_internal(int fd, LosProcessCB *processCB) 470{ 471 int ret = OK; 472 struct filelist *list = NULL; 473 struct files_struct *process_files = NULL; 474 475 /* 0,1,2 fd is not opened in system, no need to close them */ 476 if ((fd >= STDIN_FILENO) && (fd <= STDERR_FILENO)) 477 { 478 return OK; 479 } 480 481 /* Get the thread-specific file list. It should never be NULL in this 482 * context. 483 */ 484 485 list = sched_getfiles(); 486 DEBUGASSERT(list != NULL); 487 488 /* If the file was properly opened, there should be an vnode assigned */ 489 490 if (fd < 0 || fd >= CONFIG_NFILE_DESCRIPTORS || !list->fl_files[fd].f_vnode) 491 { 492 return -EBADF; 493 } 494 495 /* Perform the protected close operation */ 496 497 _files_semtake(list); 498 process_files = processCB->files; 499 if (process_files == NULL) 500 { 501 PRINT_ERR("process files is NULL, %s %d\n", __FUNCTION__ ,__LINE__); 502 _files_semgive(list); 503 return -EINVAL; 504 } 505 506 list->fl_files[fd].f_refcount--; 507 if (list->fl_files[fd].f_refcount == 0) 508 { 509 ret = _files_close(&list->fl_files[fd]); 510 if (ret == OK) 511 { 512 clear_bit(fd, bitmap); 513 } 514 } 515 516 _files_semgive(list); 517 return ret; 518} 519 520/**************************************************************************** 521 * Name: files_close 522 * 523 * Description: 524 * Close an inode (if open) 525 * 526 * Assumuptions: 527 * Caller holds the list semaphore because the file descriptor will be freed. 528 * 529 ****************************************************************************/ 530 531int files_close(int fd) 532{ 533 return files_close_internal(fd, OsCurrProcessGet()); 534} 535 536/**************************************************************************** 537 * Name: files_release 538 * 539 * Assumuptions: 540 * Similar to files_close(). Called only from open() logic on error 541 * conditions. 542 * 543 ****************************************************************************/ 544 545void files_release(int fd) 546{ 547 struct filelist *list = NULL; 548 549 list = sched_getfiles(); 550 DEBUGASSERT(list); 551 552 if (fd >=0 && fd < CONFIG_NFILE_DESCRIPTORS) 553 { 554 _files_semtake(list); 555 struct file *filep = &list->fl_files[fd]; 556 557 memset(filep, 0, sizeof(struct file)); 558 filep->fd = -1; 559 clear_bit(fd, bitmap); 560 _files_semgive(list); 561 } 562} 563 564struct Vnode *files_get_openfile(int fd) 565{ 566 struct filelist *list = NULL; 567 unsigned int *p = NULL; 568 unsigned int mask; 569 570 list = sched_getfiles(); 571 DEBUGASSERT(list); 572 573 p = ((unsigned int *)bitmap) + ((unsigned int)fd >> 5); /* Gets the location in the bitmap */ 574 mask = 1 << ((unsigned int)fd & 0x1f); /* Gets the mask for the current bit int bitmap */ 575 if ((~(*p) & mask)) 576 { 577 return NULL; 578 } 579 580 return list->fl_files[fd].f_vnode; 581} 582 583int alloc_fd(int minfd) 584{ 585 struct filelist *list = NULL; 586 unsigned int *p = NULL; 587 unsigned int mask; 588 unsigned int i; 589 590 /* minfd should be a positive number,and 0,1,2 had be distributed to stdin,stdout,stderr */ 591 592 if (minfd < FILE_START_FD) 593 { 594 minfd = FILE_START_FD; 595 } 596 i = (unsigned int)minfd; 597 598 list = sched_getfiles(); 599 DEBUGASSERT(list); 600 601 _files_semtake(list); 602 603 while (i < CONFIG_NFILE_DESCRIPTORS) 604 { 605 p = ((unsigned int *)bitmap) + (i >> 5); /* Gets the location in the bitmap */ 606 mask = 1 << (i & 0x1f); /* Gets the mask for the current bit int bitmap */ 607 if ((~(*p) & mask)) 608 { 609 set_bit(i, bitmap); 610 _files_semgive(list); 611 return (int)i; 612 } 613 i++; 614 } 615 _files_semgive(list); 616 return VFS_ERROR; 617} 618 619void clear_fd(int fd) 620{ 621 clear_bit(fd, bitmap); 622} 623 624int close_files(struct Vnode *vnode) 625{ 626 int fd = 0; 627 int ret = 0; 628 struct Vnode *open_file_vnode = NULL; 629 630 for (fd = FILE_START_FD; fd < CONFIG_NFILE_DESCRIPTORS; fd++) 631 { 632 open_file_vnode = files_get_openfile(fd); 633 if (open_file_vnode && (open_file_vnode == vnode)) 634 { 635 ret = files_close(fd); 636 if (ret < 0) 637 { 638 return -EBUSY; 639 } 640 } 641 } 642 643 return 0; 644} 645 646void files_refer(int fd) 647{ 648 struct file *filep = NULL; 649 650 struct filelist *list = sched_getfiles(); 651 if (!list || fd < 0 || fd >= CONFIG_NFILE_DESCRIPTORS) 652 { 653 return; 654 } 655 656 _files_semtake(list); 657 (void)fs_getfilep(fd, &filep); 658 if (filep != NULL) 659 { 660 filep->f_refcount++; 661 } 662 _files_semgive(list); 663} 664 665void alloc_std_fd(struct fd_table_s *fdt) 666{ 667 fdt->ft_fds[STDIN_FILENO].sysFd = STDIN_FILENO; 668 fdt->ft_fds[STDOUT_FILENO].sysFd = STDOUT_FILENO; 669 fdt->ft_fds[STDERR_FILENO].sysFd = STDERR_FILENO; 670 FD_SET(STDIN_FILENO, fdt->proc_fds); 671 FD_SET(STDOUT_FILENO, fdt->proc_fds); 672 FD_SET(STDERR_FILENO, fdt->proc_fds); 673} 674 675static void copy_fds(const struct fd_table_s *new_fdt, const struct fd_table_s *old_fdt) 676{ 677 unsigned int sz; 678 679 sz = new_fdt->max_fds * sizeof(struct file_table_s); 680 if (sz) 681 { 682 (void)memcpy_s(new_fdt->ft_fds, sz, old_fdt->ft_fds, sz); 683 } 684 (void)memcpy_s(new_fdt->proc_fds, sizeof(fd_set), old_fdt->proc_fds, sizeof(fd_set)); 685 (void)memcpy_s(new_fdt->cloexec_fds, sizeof(fd_set), old_fdt->cloexec_fds, sizeof(fd_set)); 686} 687 688static void copy_fd_table(struct fd_table_s *new_fdt, struct fd_table_s *old_fdt) 689{ 690 copy_fds((const struct fd_table_s *)new_fdt, (const struct fd_table_s *)old_fdt); 691 for (int i = 0; i < new_fdt->max_fds; i++) 692 { 693 if (FD_ISSET(i, new_fdt->proc_fds)) 694 { 695 int sysFd = GetAssociatedSystemFd(i); 696 if ((sysFd >= 0) && (sysFd < CONFIG_NFILE_DESCRIPTORS)) 697 { 698 files_refer(sysFd); 699 } 700#if defined(LOSCFG_NET_LWIP_SACK) 701 if ((sysFd >= CONFIG_NFILE_DESCRIPTORS) && (sysFd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS))) 702 { 703 socks_refer(sysFd); 704 } 705#endif 706#if defined(LOSCFG_COMPAT_POSIX) 707 if ((sysFd >= MQUEUE_FD_OFFSET) && (sysFd < (MQUEUE_FD_OFFSET + CONFIG_NQUEUE_DESCRIPTORS))) 708 { 709#if defined(LOSCFG_IPC_CONTAINER) 710 if (OsCurrTaskGet()->cloneIpc) 711 { 712 FD_CLR(i, new_fdt->proc_fds); 713 new_fdt->ft_fds[i].sysFd = -1; 714 continue; 715 } 716#endif 717 MqueueRefer(sysFd); 718 } 719#endif 720 721 } 722 } 723} 724 725static struct fd_table_s * alloc_fd_table(unsigned int numbers) 726{ 727 struct fd_table_s *fdt; 728 void *data; 729 730 fdt = LOS_MemAlloc(m_aucSysMem0, sizeof(struct fd_table_s)); 731 if (!fdt) 732 { 733 goto out; 734 } 735 fdt->max_fds = numbers; 736 if (!numbers) 737 { 738 fdt->ft_fds = NULL; 739 fdt->proc_fds = NULL; 740 fdt->cloexec_fds = NULL; 741 return fdt; 742 } 743 data = LOS_MemAlloc(m_aucSysMem0, numbers * sizeof(struct file_table_s)); 744 if (!data) 745 { 746 goto out_fdt; 747 } 748 fdt->ft_fds = data; 749 750 for (int i = STDERR_FILENO + 1; i < numbers; i++) 751 { 752 fdt->ft_fds[i].sysFd = -1; 753 } 754 755 data = LOS_MemAlloc(m_aucSysMem0, 2 * sizeof(fd_set)); /* 2: proc_fds, cloexec_fds */ 756 if (!data) 757 { 758 goto out_arr; 759 } 760 (VOID)memset_s(data, 2 * sizeof(fd_set), 0, 2 * sizeof(fd_set)); 761 fdt->proc_fds = (fd_set *)data; 762 fdt->cloexec_fds = (fd_set *)((uintptr_t)data + sizeof(fd_set)); 763 764 alloc_std_fd(fdt); 765 766 (void)sem_init(&fdt->ft_sem, 0, 1); 767 768 return fdt; 769 770out_arr: 771 (VOID)LOS_MemFree(m_aucSysMem0, fdt->ft_fds); 772out_fdt: 773 (VOID)LOS_MemFree(m_aucSysMem0, fdt); 774out: 775 return NULL; 776} 777 778struct files_struct *alloc_files(void) 779{ 780 struct files_struct *files = LOS_MemAlloc(m_aucSysMem0, sizeof(struct files_struct)); 781 if (!files) 782 { 783 ferr("malloc file_struct error\n"); 784 return NULL; 785 } 786 files->count = 1; 787 files->file_lock = 0; 788 files->next_fd = 3; 789#ifdef VFS_USING_WORKDIR 790 spin_lock_init(&files->workdir_lock); 791 memset_s(files->workdir, PATH_MAX, 0, PATH_MAX); 792 files->workdir[0] = '/'; 793#endif 794 files->fdt = alloc_fd_table(NR_OPEN_DEFAULT); 795 if (!files->fdt) 796 { 797 ferr("malloc fdt error\n"); 798 (VOID)LOS_MemFree(m_aucSysMem0, files); 799 return NULL; 800 } 801#ifdef LOSCFG_CHROOT 802 if (VnodeGetRoot() != NULL) 803 { 804 VnodeGetRoot()->useCount++; 805 } 806 files->rootVnode = VnodeGetRoot(); 807#endif 808 809 return files; 810} 811 812struct files_struct *dup_fd(struct files_struct *old_files) 813{ 814 struct fd_table_s *old_fdt = NULL; 815 struct fd_table_s *new_fdt = NULL; 816 struct files_struct *files = NULL; 817 if((old_files == NULL) || (old_files->fdt == NULL) || (old_files->fdt->max_fds == 0)) 818 { 819 return alloc_files(); 820 } 821 files = LOS_MemAlloc(m_aucSysMem0, sizeof(struct files_struct)); 822 if(!files) 823 { 824 ferr("malloc file_struct error\n"); 825 return NULL; 826 } 827 files->count = 1; 828 files->file_lock = 0; 829 files->next_fd = old_files->next_fd; 830#ifdef VFS_USING_WORKDIR 831 spin_lock_init(&files->workdir_lock); 832 memset_s(files->workdir, PATH_MAX, 0, PATH_MAX); 833 strncpy_s(files->workdir, PATH_MAX - 1, old_files->workdir, PATH_MAX - 1); 834#endif 835 old_fdt = old_files->fdt; 836 new_fdt = alloc_fd_table(old_fdt->max_fds); 837 if(new_fdt == NULL) 838 { 839 PRINT_ERR("alloc fd_table failed\n"); 840 (VOID)LOS_MemFree(m_aucSysMem0, files); 841 return NULL; 842 } 843 copy_fd_table(new_fdt, old_fdt); 844 files->fdt = new_fdt; 845#ifdef LOSCFG_CHROOT 846 if (old_files->rootVnode != NULL) 847 { 848 old_files->rootVnode->useCount++; 849 } 850 files->rootVnode = old_files->rootVnode; 851#endif 852 853 return files; 854} 855 856/**************************************************************************** 857 * Name: delete_files 858 * 859 * Description: 860 * Close a current process's fd specified by struct files. 861 * And delete files struct. 862 * 863 ****************************************************************************/ 864void delete_files(struct files_struct *files) 865{ 866 if (files == NULL) 867 { 868 return; 869 } 870 871#ifdef LOSCFG_CHROOT 872 if ((files->rootVnode != NULL) && (files->rootVnode->useCount > 0)) 873 { 874 files->rootVnode->useCount--; 875 } 876#endif 877 878 if (files->fdt == NULL) 879 { 880 goto out_file; 881 } 882 883 for (int i = 0; i < files->fdt->max_fds; i++) 884 { 885 if (FD_ISSET(i, files->fdt->proc_fds)) 886 { 887 int sysFd = DisassociateProcessFd(i); 888 close(sysFd); 889 FreeProcessFd(i); 890 } 891 } 892 893 (VOID)sem_destroy(&files->fdt->ft_sem); 894 (VOID)LOS_MemFree(m_aucSysMem0, files->fdt->ft_fds); 895 (VOID)LOS_MemFree(m_aucSysMem0, files->fdt->proc_fds); 896 (VOID)LOS_MemFree(m_aucSysMem0, files->fdt); 897out_file: 898 (VOID)LOS_MemFree(m_aucSysMem0, files); 899 return; 900} 901 902struct files_struct *create_files_snapshot(const struct files_struct *old_files) 903{ 904 struct fd_table_s *old_fdt = NULL; 905 struct fd_table_s *new_fdt = NULL; 906 struct files_struct *files = NULL; 907 if ((old_files == NULL) || (old_files->fdt == NULL) || (old_files->fdt->max_fds == 0)) 908 { 909 return NULL; 910 } 911 files = LOS_MemAlloc(m_aucSysMem0, sizeof(struct files_struct)); 912 if (!files) 913 { 914 PRINT_ERR("malloc file_struct error\n"); 915 return NULL; 916 } 917 files->count = 1; 918 files->file_lock = 0; 919 files->next_fd = old_files->next_fd; 920#ifdef VFS_USING_WORKDIR 921 spin_lock_init(&files->workdir_lock); 922 memset_s(files->workdir, PATH_MAX, 0, PATH_MAX); 923 strncpy_s(files->workdir, PATH_MAX - 1, old_files->workdir, PATH_MAX - 1); 924#endif 925 old_fdt = old_files->fdt; 926 new_fdt = alloc_fd_table(old_fdt->max_fds); 927 if (new_fdt == NULL) 928 { 929 PRINT_ERR("alloc fd_table failed\n"); 930 (VOID)LOS_MemFree(m_aucSysMem0, files); 931 return NULL; 932 } 933 copy_fds((const struct fd_table_s *)new_fdt, (const struct fd_table_s *)old_fdt); 934 files->fdt = new_fdt; 935#ifdef LOSCFG_CHROOT 936 if (old_files->rootVnode != NULL) 937 { 938 old_files->rootVnode->useCount++; 939 } 940 files->rootVnode = old_files->rootVnode; 941#endif 942 943 return files; 944 945} 946 947void delete_files_snapshot(struct files_struct *files) 948{ 949 if (files == NULL) 950 { 951 return; 952 } 953 if (files->fdt == NULL) 954 { 955 goto out_file; 956 } 957 958 (VOID)sem_destroy(&files->fdt->ft_sem); 959 (VOID)LOS_MemFree(m_aucSysMem0, files->fdt->ft_fds); 960 (VOID)LOS_MemFree(m_aucSysMem0, files->fdt->proc_fds); 961 (VOID)LOS_MemFree(m_aucSysMem0, files->fdt); 962out_file: 963 (VOID)LOS_MemFree(m_aucSysMem0, files); 964 return; 965} 966