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