source: mainline/uspace/lib/c/generic/vfs/inbox.c@ 3bbd921

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 3bbd921 was bb9ec2d, checked in by Jakub Jermar <jakub@…>, 8 years ago

Merge from lp:~zarevucky-jiri/helenos/vfs-2.5/ revision 1941-1944

Original commit messages:

1944: Jiri Zarevucky 2013-08-06 Replace legacy file descriptor presetting with inbox.
1943: Jiri Zarevucky 2013-08-06 Do not preserve open state when passing file descriptor to another task. Allow receiver to specify, whether the descriptor is low or high.
1942: Jiri Zarevucky 2013-08-06 C style.
1941: Jiri Zarevucky 2013-08-06 Make loader accept file reference instead of a pathname.

Modifications:

  • Keep version of elf_load_file() that accepts file name
  • Changes required for loading dynamically linked executables
  • Update to newer list_foreach
  • Property mode set to 100644
File size: 3.1 KB
Line 
1
2#include <vfs/inbox.h>
3
4#include <adt/list.h>
5#include <str.h>
6#include <stdlib.h>
7#include <loader/pcb.h>
8#include "../private/io.h"
9#include <errno.h>
10
11/* This is an attempt at generalization of the "standard files" concept to arbitrary names.
12 * When loading a task, the parent can put arbitrary files to an "inbox" through IPC calls,
13 * every file in an inbox has a name assigned (e.g. "stdin", "stdout", "stderr", "data", "logfile",
14 * etc.). The client then retrieves those files from inbox by name. "stdin", "stdout" and "stderr"
15 * are handled automatically by libc to initialize standard <stdio.h> streams and legacy file
16 * descriptors 0, 1, 2. Other names are subject to conventions and application-specific rules.
17 */
18
19typedef struct {
20 link_t link;
21 char *name;
22 int file;
23} inbox_entry;
24
25static LIST_INITIALIZE(inb_list);
26
27/* Inserts a named file into the inbox.
28 * If a file with the same name is already present, it overwrites it and returns the original
29 * value. Otherwise, it returns -1.
30 * If the argument 'file' is -1, nothing is inserted and the file with specified name is
31 * removed and returned if present.
32 *
33 * @param name Name of the inbox entry.
34 * @param file File to insert or -1.
35 * @return Original value of the entry or -1 if not originally present.
36 */
37int inbox_set(const char *name, int file)
38{
39 inbox_entry *next = NULL;
40
41 list_foreach(inb_list, link, inbox_entry, e) {
42 int cmp = str_cmp(e->name, name);
43 switch (cmp) {
44 case -1:
45 continue;
46 case 0:;
47 int result = e->file;
48 if (file == -1) {
49 free(e->name);
50 /* Safe because we exit immediately. */
51 list_remove(&e->link);
52 } else {
53 e->file = file;
54 }
55 return result;
56 case 1:
57 next = e;
58 goto out;
59 }
60 }
61
62out:
63 if (file == -1) {
64 return -1;
65 }
66
67 inbox_entry *entry = calloc(sizeof(inbox_entry), 1);
68 entry->name = str_dup(name);
69 entry->file = file;
70
71 if (next == NULL) {
72 list_append((link_t *)entry, &inb_list);
73 } else {
74 list_insert_before((link_t *)entry, (link_t *)next);
75 }
76 return -1;
77}
78
79/* Retrieve a file with this name.
80 *
81 * @param name Name of the entry.
82 * @return Requested file or ENOENT if not set.
83 */
84int inbox_get(const char *name)
85{
86 list_foreach(inb_list, link, inbox_entry, e) {
87 int cmp = str_cmp(e->name, name);
88 switch (cmp) {
89 case 0:
90 return e->file;
91 case 1:
92 return ENOENT;
93 }
94 }
95
96 return ENOENT;
97}
98
99/* Writes names of entries that are currently set into and array provided by the user.
100 *
101 * @param names Array in which names are stored.
102 * @param capacity Capacity of the array.
103 * @return Number of entries written. If capacity == 0, return the total number of entries.
104 */
105int inbox_list(const char **names, int capacity)
106{
107 if (capacity == 0) {
108 return list_count(&inb_list);
109 }
110
111 int used = 0;
112
113 list_foreach(inb_list, link, inbox_entry, e) {
114 if (used == capacity) {
115 return used;
116 }
117 names[used] = e->name;
118 used++;
119 }
120
121 return used;
122}
123
124void __inbox_init(struct pcb_inbox_entry *entries, int count) {
125 for (int i = 0; i < count; i++) {
126 int original = inbox_set(entries[i].name, entries[i].file);
127 if (original >= 0) {
128 close(original);
129 }
130 }
131}
Note: See TracBrowser for help on using the repository browser.