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(&reg_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