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