1 /*
2  * (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de>
3  *     economic rights: Technische Universität Dresden (Germany)
4  *
5  * This file is part of TUD:OS and distributed under the terms of the
6  * GNU General Public License 2.
7  * Please see the COPYING-GPL-2 file for details.
8  */
9 #pragma once
10 
11 #include <l4/cxx/avl_tree>
12 #include <l4/cxx/std_ops>
13 #include <l4/cxx/unique_ptr>
14 #include <l4/sys/cxx/ipc_epiface>
15 
16 #include <l4/sys/capability>
17 #include <l4/re/namespace>
18 
19 #include "server_obj.h"
20 #include "quota.h"
21 #include "obj_reg.h"
22 #include <l4/cxx/string>
23 
24 #include <cstring>
25 #include <cstdlib>
26 
27 
28 namespace Moe {
29 
30 class Name_space;
31 
32 class Entry
33 : public cxx::Avl_tree_node,
34   public Q_object
35 {
36 public:
37   friend class Name_space;
38   typedef cxx::String Name;
39 
40   enum Flags
41   {
42     F_rw        = L4Re::Namespace::Rw,
43     F_strong    = L4Re::Namespace::Strong,
44 
45     F_trusted   = L4Re::Namespace::Trusted,
46 
47     F_rights_mask = F_rw | F_strong | F_trusted,
48 
49     F_cap        = 0x100,
50     F_local      = 0x200,
51     F_allocated  = 0x400,
52     F_static     = 0x800,
53     F_base_mask  = 0xf00,
54   };
55 
56 private:
57   typedef cxx::Weak_ref<Moe::Server_object> Weak_ref;
58   Name _name;
59   unsigned _flags;
60   union
61   {
62     l4_cap_idx_t _cap;
63     Weak_ref _obj;
64   };
65 
66   void set(L4::Cap<void> cap);
67   void set(Moe::Server_object *o);
68 
69 public:
Entry(char const * name,unsigned flags)70   Entry(char const *name, unsigned flags)
71   : Entry(name, strlen(name), flags)
72   {}
73 
Entry(char const * name,unsigned long len,unsigned flags)74   Entry(char const *name, unsigned long len, unsigned flags)
75   : _flags(flags)
76   {
77     auto namecpy = qalloc()->alloc<char>(len + 1);
78     memcpy(namecpy, name, len);
79     namecpy[len] = 0;
80     _name = Name(namecpy, len);
81   }
82 
83   ~Entry();
84 
name()85   Name const &name() const
86   { return _name; }
87 
is_dynamic()88   bool is_dynamic() const
89   { return !(_flags & F_static); }
90 
is_valid()91   bool is_valid() const
92   { return (_flags & F_cap) && !(is_local() && !_obj); }
93 
is_local()94   bool is_local() const
95   { return _flags & F_local; }
96 
is_rw()97   bool is_rw() const
98   { return (_flags & F_rw) == F_rw; }
99 
is_strong()100   bool is_strong() const
101   { return _flags & F_strong; }
102 
flags()103   unsigned flags() const
104   { return _flags; }
105 
cap()106   L4::Cap<void> cap() const
107   {
108     if (!is_local())
109       return L4::Cap<void>(_cap);
110     if (!_obj)
111       return L4::Cap<void>::Invalid;
112     return _obj.get()->obj_cap();
113   }
114 
obj()115   L4::Epiface *obj() const
116   { return _obj.get(); }
117 
118   void set_epiface(l4_umword_t data);
119   void set_cap_copy(L4::Cap<L4::Kobject> cap);
120 };
121 
122 struct Entry_get_key
123 {
124   typedef Entry::Name Key_type;
key_ofEntry_get_key125   static Key_type const &key_of(Entry const *e)
126   { return e->name(); }
127 };
128 
129 struct Entry_key_compare
130 {
operatorEntry_key_compare131   bool operator () (Entry::Name const &l, Entry::Name const &r) const
132     {
133       unsigned long len = cxx::min(l.len(), r.len());
134       int v = memcmp(l.start(), r.start(), len);
135       return v < 0 || (v == 0 && l.len() < r.len());
136   }
137 };
138 
139 
140 class Name_space :
141   public L4::Epiface_t<Name_space, L4Re::Namespace, Moe::Server_object>,
142   public Q_object
143 {
144   friend class Entry;
145   typedef cxx::Avl_tree<Entry, Entry_get_key, Entry_key_compare> Tree;
146   typedef L4::Ipc::Array_in_buf<char, unsigned long> Name_buffer;
147   Tree _tree;
148 
find(Entry::Name const & name)149   Entry *find(Entry::Name const &name) const
150   { return _tree.find_node(name); }
151 
remove(Entry::Name const & name)152   Entry *remove(Entry::Name const &name)
153   { return _tree.remove(name); }
154 
insert(Entry * e)155   bool insert(Entry *e)
156   { return _tree.insert(e).second; }
157 
158   Entry *check_existing(Name_buffer const &name, unsigned flags);
159 
create_entry(Name_buffer const & name,unsigned flags)160   Entry *create_entry(Name_buffer const &name, unsigned flags)
161   {
162     return qalloc()->make_obj<Entry>(name.data, name.length,
163                                      flags & Entry::F_rights_mask);
164   }
165 public:
166   typedef Tree::Const_iterator Const_iterator;
167 
168   virtual ~Name_space();
169 
begin()170   Const_iterator begin() const { return _tree.begin(); }
end()171   Const_iterator end() const { return _tree.end(); }
172 
173   // server interface ------------------------------------------
174   int op_query(L4Re::Namespace::Rights,
175                Name_buffer const &name,
176                L4::Ipc::Snd_fpage &snd_cap, L4::Ipc::Opt<L4::Opcode> &,
177                L4::Ipc::Opt<L4::Ipc::Array_ref<char, unsigned long> > &out_name);
178 
179   int op_register_obj(L4Re::Namespace::Rights, unsigned flags,
180                       Name_buffer const &name, L4::Ipc::Snd_fpage &cap);
181 
182   int op_unlink(L4Re::Namespace::Rights r, Name_buffer const &name);
183 
184   // internally used to register bootfs files, name spaces...
185   template <typename T>
register_obj(Entry::Name const & name,unsigned long flags,T cap)186   int register_obj(Entry::Name const &name, unsigned long flags, T cap)
187   {
188     cxx::unique_ptr<Entry> n(qalloc()->make_obj<Entry>(name.start(), name.len(),
189                                                        flags | Entry::F_static));
190     n->set(cap);
191     if (!insert(n.get()))
192       return -L4_EEXIST;
193 
194     n.release();
195     return 0;
196   }
197 
198   Entry *find_iter(Entry::Name const &name) const;
199 
200   void dump(bool rec = false, int indent = 0) const;
201 };
202 
203 }
204 
205 Moe::Name_space *root_name_space();
206 
207