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