1 /*
2 * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3 * Alexander Warg <warg@os.inf.tu-dresden.de>
4 * economic rights: Technische Universität Dresden (Germany)
5 *
6 * This file is part of TUD:OS and distributed under the terms of the
7 * GNU General Public License 2.
8 * Please see the COPYING-GPL-2 file for details.
9 *
10 * As a special exception, you may use this file as part of a free software
11 * library without restriction. Specifically, if other files instantiate
12 * templates or use macros or inline functions from this file, or you compile
13 * this file and link it with other files to produce an executable, this
14 * file does not by itself cause the resulting executable to be covered by
15 * the GNU General Public License. This exception does not however
16 * invalidate any other reasons why the executable file might be covered by
17 * the GNU General Public License.
18 */
19 #include <l4/re/util/name_space_svr>
20 #include <l4/re/util/debug>
21
22 #include <l4/re/namespace>
23
24 #include <cassert>
25 #include <cstring>
26
27 namespace L4Re { namespace Util { namespace Names {
28
29 bool
operator <(Name const & r) const30 Name::operator < (Name const &r) const
31 {
32 unsigned long l = cxx::min(len(), r.len());
33 int v = memcmp(start(), r.start(), l);
34 return v < 0 || (v == 0 && len() < r.len());
35 }
36
37 void
set(Obj const & o)38 Entry::set(Obj const &o)
39 {
40 obj()->set(o, obj()->flags());
41 }
42
43 Entry *
find_iter(Name const & pname) const44 Name_space::find_iter(Name const &pname) const
45 {
46 Name name = pname;
47 _dbg.printf("resolve '%.*s': ", name.len(), name.start());
48 Name_space const *ns = this;
49 while (ns)
50 {
51 cxx::String::Index sep = name.find("/");
52 cxx::String part;
53 if (!name.eof(sep))
54 part = name.head(sep);
55 else
56 part = name;
57
58 _dbg.cprintf(" '%.*s'", part.len(), part.start());
59 Entry *o = ns->find(Name(part.start(), part.len()));
60
61 if (!o)
62 {
63 _dbg.cprintf(": resolution failed: '%.*s' remaining\n",
64 name.len(), name.start());
65 return 0;
66 }
67
68 ns = dynamic_cast<Name_space const *>(o->obj()->obj());
69 if (ns)
70 {
71 if (!name.eof(sep))
72 {
73 name = name.substr(sep + 1);
74 continue;
75 }
76 }
77
78 _dbg.cprintf(": found object: %p (%s)\n", o->obj()->obj(), o->obj()->obj()?typeid(*(o->obj()->obj())).name():"");
79
80 return o;
81 }
82
83 return 0;
84 }
85
86
87 int
op_query(L4Re::Namespace::Rights,L4::Ipc::Array_in_buf<char,unsigned long> const & name,L4::Ipc::Snd_fpage & snd_cap,L4::Ipc::Opt<L4::Opcode> & dummy,L4::Ipc::Opt<L4::Ipc::Array_ref<char,unsigned long>> & out_name)88 Name_space::op_query(L4Re::Namespace::Rights,
89 L4::Ipc::Array_in_buf<char, unsigned long> const &name,
90 L4::Ipc::Snd_fpage &snd_cap, L4::Ipc::Opt<L4::Opcode> &dummy,
91 L4::Ipc::Opt<L4::Ipc::Array_ref<char, unsigned long> > &out_name)
92 {
93 #if 1
94 _dbg.printf("query: [%ld] '%.*s'\n", name.length, (int)name.length, name.data);
95 #endif
96
97 char const *sep = (char const*)memchr(name.data, '/', name.length);
98 unsigned long part;
99 if (sep)
100 part = sep - name.data;
101 else
102 part = name.length;
103
104 Entry *n = find(Name(name.data, part));
105 if (!n)
106 return -L4_ENOENT;
107 else if (!n->obj()->is_valid())
108 return -L4_EAGAIN;
109 else
110 {
111 if (n->obj()->cap().validate(L4_BASE_TASK_CAP).label() <= 0)
112 {
113 if (n->obj()->is_local())
114 free_epiface(n->obj()->obj());
115 else
116 free_capability(n->obj()->cap());
117
118 if (n->is_dynamic())
119 {
120 remove(n->name());
121 free_dynamic_entry(n);
122 }
123 return -L4_ENOENT;
124 }
125
126 // make picky clients happy
127 dummy.set_valid();
128
129 l4_umword_t result = 0;
130
131 out_name.set_valid();
132 if (part < name.length)
133 {
134 result |= L4Re::Namespace::Partly_resolved;
135 memcpy(out_name->data, name.data + part + 1, name.length - part - 1);
136 out_name->length = name.length - part - 1;
137 }
138 else
139 out_name->length = 0;
140
141 unsigned flags = L4_CAP_FPAGE_R;
142 if (n->obj()->is_rw()) flags |= L4_CAP_FPAGE_W;
143 if (n->obj()->is_strong()) flags |= L4_CAP_FPAGE_S;
144
145 snd_cap = L4::Ipc::Snd_fpage(n->obj()->cap(), flags);
146 _dbg.printf(" result = %lx flgs=%x strg=%d\n",
147 result, flags, (int)n->obj()->is_strong());
148 return result;
149 }
150 }
151
152 int
insert_entry(Name const & name,unsigned flags,Entry ** e)153 Name_space::insert_entry(Name const &name, unsigned flags, Entry **e)
154 {
155 Entry *n = find(name);
156 if (n && n->obj()->is_valid())
157 {
158 if (!(flags & L4Re::Namespace::Overwrite)
159 && n->obj()->cap().validate(L4_BASE_TASK_CAP).label() > 0)
160 return -L4_EEXIST;
161
162 if (n->obj()->is_local())
163 free_epiface(n->obj()->obj());
164 else
165 free_capability(n->obj()->cap());
166
167 if (n->is_dynamic())
168 {
169 remove(n->name());
170 free_dynamic_entry(n);
171 n = 0;
172 }
173 else
174 {
175 if (!n->obj()->is_replacable())
176 return -L4_EEXIST;
177 n->obj()->reset(Obj::F_rw);
178 }
179 }
180
181 flags &= L4Re::Namespace::Cap_flags;
182 if (!n)
183 {
184 if (!(n = alloc_dynamic_entry(name, flags)))
185 return -L4_ENOMEM;
186 else
187 {
188 int err = insert(n);
189 if (err < 0)
190 {
191 free_dynamic_entry(n);
192 return err;
193 }
194 }
195 }
196
197 *e = n;
198 return 0;
199 }
200
201 int
op_register_obj(L4Re::Namespace::Rights,unsigned flags,L4::Ipc::Array_in_buf<char,unsigned long> const & name,L4::Ipc::Snd_fpage & cap)202 Name_space::op_register_obj(L4Re::Namespace::Rights, unsigned flags,
203 L4::Ipc::Array_in_buf<char, unsigned long> const &name,
204 L4::Ipc::Snd_fpage &cap)
205 {
206 if (name.length == 0 || memchr(name.data, '/', name.length))
207 return -L4_EINVAL;
208
209 L4::Cap<void> reg_cap(L4_INVALID_CAP);
210 L4::Epiface *src_o = 0;
211
212 // Did we receive something we have handed out ourselves? If yes,
213 // register the object under the given name but do not allocate
214 // anything more.
215 if (cap.id_received() || cap.local_id_received())
216 {
217 if (int ret = get_epiface(cap.data(), cap.local_id_received(), &src_o))
218 return ret;
219
220 // Make sure rights are restricted to the mapped rights.
221 flags &= (cap.data() & 0x3UL) | ~0x3UL;
222 }
223 else if (cap.cap_received())
224 {
225 if (int ret = copy_receive_cap(®_cap))
226 return ret;
227 }
228 else if (!cap.is_valid())
229 {
230 reg_cap = L4::Cap<void>::Invalid;
231 }
232 else
233 return -L4_EINVAL;
234
235 // got a valid entry to register
236 _dbg.printf("register: '%.*s' flags=%x\n", (int)name.length, name.data, flags);
237
238 Name _name(name.data, name.length);
239
240 Entry *n;
241 if (int r = insert_entry(_name, flags, &n))
242 {
243 if (cap.cap_received())
244 free_capability(reg_cap);
245 if (src_o)
246 free_epiface(src_o);
247
248 return r;
249 }
250
251 if (src_o)
252 n->set(Names::Obj(flags & L4Re::Namespace::Cap_flags, src_o));
253 else if (reg_cap.is_valid())
254 n->set(Names::Obj(flags & L4Re::Namespace::Cap_flags, reg_cap));
255
256 return 0;
257 }
258
259 int
op_unlink(L4Re::Namespace::Rights,L4::Ipc::Array_in_buf<char,unsigned long> const & name)260 Name_space::op_unlink(L4Re::Namespace::Rights,
261 L4::Ipc::Array_in_buf<char, unsigned long> const &name)
262
263 {
264 #if 1
265 _dbg.printf("unlink: [%ld] '%.*s'\n", name.length, (int)name.length, name.data);
266 #endif
267
268 char const *sep = (char const*)memchr(name.data, '/', name.length);
269 unsigned long part;
270 if (sep)
271 part = sep - name.data;
272 else
273 part = name.length;
274
275 Entry *n = find(Name(name.data, part));
276 if (!n || !n->obj()->is_valid())
277 return -L4_ENOENT;
278
279 if (n->obj()->is_local())
280 free_epiface(n->obj()->obj());
281 else
282 free_capability(n->obj()->cap());
283
284 if (n->is_dynamic())
285 {
286 remove(n->name());
287 free_dynamic_entry(n);
288 }
289 else
290 return -L4_EACCESS;
291
292 return 0;
293 }
294
295
296
297
298 }}}
299