• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
66 struct filelist tg_filelist = { 0 };
67 #endif
68 
69 /****************************************************************************
70  * Pre-processor Definitions
71  ****************************************************************************/
72 
sched_getfiles(void)73 struct 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 
84 static unsigned int bitmap[CONFIG_NFILE_DESCRIPTORS / 32 + 1] = {0};
85 
set_bit(int i,void * addr)86 static 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 
clear_bit(int i,void * addr)95 static 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 
get_bit(int i)104 bool 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 
_files_semtake(struct filelist * list)125 static 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 
file_hold(struct file * filep)145 void 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 
file_release(struct file * filep)162 void 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 
_files_close(struct file * filep)190 static 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 
files_initialize(void)251 void 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 
files_initlist(struct filelist * list)262 void 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 
files_releaselist(struct filelist * list)279 void 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 
file_dup2(struct file * filep1,struct file * filep2)317 int 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 
409 errout_with_vnode:
410   memset(filep2, 0, sizeof(struct file));
411   filep2->fd = -1;
412 
413 errout_with_ret:
414   err               = -ret;
415   _files_semgive(list);
416 
417 errout:
418   set_errno(err);
419   return VFS_ERROR;
420 }
421 
files_allocate(const struct Vnode * vnode_ptr,int oflags,off_t pos,const void * priv,int minfd)422 struct 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 
files_close_internal(int fd,LosProcessCB * processCB)469 int 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 
files_close(int fd)531 int 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 
files_release(int fd)545 void 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 
files_get_openfile(int fd)564 struct 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 
alloc_fd(int minfd)583 int 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 
clear_fd(int fd)619 void clear_fd(int fd)
620 {
621   clear_bit(fd, bitmap);
622 }
623 
close_files(struct Vnode * vnode)624 int 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 
files_refer(int fd)646 void 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 
alloc_std_fd(struct fd_table_s * fdt)665 void 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 
copy_fds(const struct fd_table_s * new_fdt,const struct fd_table_s * old_fdt)675 static 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 
copy_fd_table(struct fd_table_s * new_fdt,struct fd_table_s * old_fdt)688 static 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 
alloc_fd_table(unsigned int numbers)725 static 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 
770 out_arr:
771   (VOID)LOS_MemFree(m_aucSysMem0, fdt->ft_fds);
772 out_fdt:
773   (VOID)LOS_MemFree(m_aucSysMem0, fdt);
774 out:
775   return NULL;
776 }
777 
alloc_files(void)778 struct 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 
dup_fd(struct files_struct * old_files)812 struct 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  ****************************************************************************/
delete_files(struct files_struct * files)864 void 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);
897 out_file:
898   (VOID)LOS_MemFree(m_aucSysMem0, files);
899   return;
900 }
901 
create_files_snapshot(const struct files_struct * old_files)902 struct 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 
delete_files_snapshot(struct files_struct * files)947 void 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);
962 out_file:
963   (VOID)LOS_MemFree(m_aucSysMem0, files);
964   return;
965 }
966