SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Article:1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 6.5 ] [ 7 ] [ 7.5 ] [ 8 ] [ 9 ] [ 9.5 ]

Diff markup

Differences between /sos/fs.c (Article 9.5) and /sos/fs.c (Article 9)


001 /* Copyright (C) 2005,2006 David Decotigny     !! 001 /* Copyright (C) 2005      David Decotigny
002    Copyright (C) 2000-2005 The KOS Team (Thoma    002    Copyright (C) 2000-2005 The KOS Team (Thomas Petazzoni, David
003                            Decotigny, Julien M    003                            Decotigny, Julien Munier)
004                                                   004 
005    This program is free software; you can redi    005    This program is free software; you can redistribute it and/or
006    modify it under the terms of the GNU Genera    006    modify it under the terms of the GNU General Public License
007    as published by the Free Software Foundatio    007    as published by the Free Software Foundation; either version 2
008    of the License, or (at your option) any lat    008    of the License, or (at your option) any later version.
009                                                   009    
010    This program is distributed in the hope tha    010    This program is distributed in the hope that it will be useful,
011    but WITHOUT ANY WARRANTY; without even the     011    but WITHOUT ANY WARRANTY; without even the implied warranty of
012    MERCHANTABILITY or FITNESS FOR A PARTICULAR    012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013    GNU General Public License for more details    013    GNU General Public License for more details.
014                                                   014    
015    You should have received a copy of the GNU     015    You should have received a copy of the GNU General Public License
016    along with this program; if not, write to t    016    along with this program; if not, write to the Free Software
017    Foundation, Inc., 59 Temple Place - Suite 3    017    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
018    USA.                                           018    USA. 
019 */                                                019 */
020                                                   020 
021 #include <sos/assert.h>                           021 #include <sos/assert.h>
022 #include <sos/list.h>                             022 #include <sos/list.h>
023 #include <sos/kmem_slab.h>                        023 #include <sos/kmem_slab.h>
024 #include <sos/kmalloc.h>                          024 #include <sos/kmalloc.h>
025 #include "chardev.h"                              025 #include "chardev.h"
026                                                   026 
027 #include "fs.h"                                   027 #include "fs.h"
028                                                   028 
029                                                   029 
030 /** List of available filesystems registered i    030 /** List of available filesystems registered in the system */
031 static struct sos_fs_manager_type * fs_list =     031 static struct sos_fs_manager_type * fs_list = NULL;
032                                                   032 
033 /** Last UID delivered for the FS instances */    033 /** Last UID delivered for the FS instances */
034 static sos_ui64_t last_fs_instance_uid;           034 static sos_ui64_t last_fs_instance_uid;
035                                                   035 
036                                                   036 
037 /* *******************************************    037 /* **********************************************************
038  * Forward declarations                           038  * Forward declarations
039  */                                               039  */
040 static sos_ret_t fs_fetch_node(struct sos_fs_m    040 static sos_ret_t fs_fetch_node(struct sos_fs_manager_instance *fs,
041                                sos_ui64_t stor    041                                sos_ui64_t storage_location,
042                                struct sos_fs_n    042                                struct sos_fs_node ** result_fsnode);
043                                                   043 
044 static sos_ret_t                                  044 static sos_ret_t
045 fs_allocate_node(struct sos_fs_manager_instanc    045 fs_allocate_node(struct sos_fs_manager_instance * fs,
046                  sos_fs_node_type_t type,         046                  sos_fs_node_type_t type,
047                  sos_ui32_t flags,                047                  sos_ui32_t flags,
048                  const struct sos_process * cr    048                  const struct sos_process * creator,
049                  sos_ui32_t access_rights,        049                  sos_ui32_t access_rights,
050                  struct sos_fs_node ** result_    050                  struct sos_fs_node ** result_fsnode);
051                                                   051 
052 static sos_ret_t mark_dirty_fsnode(struct sos_    052 static sos_ret_t mark_dirty_fsnode(struct sos_fs_node * fsnode,
053                                    sos_bool_t     053                                    sos_bool_t force_sync);
054                                                   054 
055 static sos_ret_t sos_fs_sync_node(struct sos_f    055 static sos_ret_t sos_fs_sync_node(struct sos_fs_node * fsnode);
056                                                   056 
057 static sos_ret_t sos_fs_sync_fs(struct sos_fs_    057 static sos_ret_t sos_fs_sync_fs(struct sos_fs_manager_instance * fs);
058                                                   058 
059 static sos_ret_t                                  059 static sos_ret_t
060 fs_lookup_node(const struct sos_fs_pathname *     060 fs_lookup_node(const struct sos_fs_pathname * path,
061                sos_bool_t follow_symlinks,        061                sos_bool_t follow_symlinks,
062                const struct sos_fs_nscache_nod    062                const struct sos_fs_nscache_node * root_nsnode,
063                const struct sos_fs_nscache_nod    063                const struct sos_fs_nscache_node * start_nsnode,
064                struct sos_fs_nscache_node ** r    064                struct sos_fs_nscache_node ** result_nsnode,
065                struct sos_fs_pathname * result    065                struct sos_fs_pathname * result_remaining_path,
066                int lookup_recursion_level);       066                int lookup_recursion_level);
067                                                   067 
068 static sos_ret_t                                  068 static sos_ret_t
069 fs_resolve_symlink(const struct sos_fs_nscache    069 fs_resolve_symlink(const struct sos_fs_nscache_node * root_nsnode,
070                    const struct sos_fs_nscache    070                    const struct sos_fs_nscache_node * symlink_nsnode,
071                    struct sos_fs_nscache_node     071                    struct sos_fs_nscache_node ** target_nsnode,
072                    int lookup_recursion_level)    072                    int lookup_recursion_level);
073                                                   073 
074 static sos_ret_t                                  074 static sos_ret_t
075 fs_register_child_node(const struct sos_proces    075 fs_register_child_node(const struct sos_process * creator,
076                        struct sos_fs_nscache_n    076                        struct sos_fs_nscache_node * parent_nsnode,
077                        const struct sos_fs_pat    077                        const struct sos_fs_pathname * name,
078                        struct sos_fs_node * fs    078                        struct sos_fs_node * fsnode,
079                        sos_ui32_t flags,          079                        sos_ui32_t flags,
080                        struct sos_fs_nscache_n    080                        struct sos_fs_nscache_node ** result_nsnode);
081                                                   081 
082 static sos_ret_t                                  082 static sos_ret_t
083 fs_create_child_node(struct sos_fs_nscache_nod    083 fs_create_child_node(struct sos_fs_nscache_node * parent_nsnode,
084                      const struct sos_fs_pathn    084                      const struct sos_fs_pathname * name,
085                      sos_fs_node_type_t type,     085                      sos_fs_node_type_t type,
086                      sos_ui32_t flags,            086                      sos_ui32_t flags,
087                      const struct sos_process     087                      const struct sos_process * creator,
088                      sos_ui32_t access_rights,    088                      sos_ui32_t access_rights,
089                      struct sos_fs_nscache_nod    089                      struct sos_fs_nscache_node ** result_nsnode);
090                                                   090 
091 static sos_ret_t                                  091 static sos_ret_t
092 fs_connect_existing_child_node(const struct so    092 fs_connect_existing_child_node(const struct sos_process * creator,
093                                struct sos_fs_n    093                                struct sos_fs_nscache_node * parent_nsnode,
094                                const struct so    094                                const struct sos_fs_pathname * name,
095                                struct sos_fs_n    095                                struct sos_fs_nscache_node * nsnode);
096                                                   096 
097 static sos_ret_t                                  097 static sos_ret_t
098 fs_create_node(const struct sos_fs_pathname *     098 fs_create_node(const struct sos_fs_pathname * _path,
099                const struct sos_process * crea    099                const struct sos_process * creator,
100                sos_ui32_t access_rights,          100                sos_ui32_t access_rights,
101                sos_fs_node_type_t type,           101                sos_fs_node_type_t type,
102                struct sos_fs_nscache_node ** r    102                struct sos_fs_nscache_node ** result_nsnode);
103                                                   103 
104 static sos_ret_t                                  104 static sos_ret_t
105 fs_remove_node(const struct sos_process * acto    105 fs_remove_node(const struct sos_process * actor,
106                struct sos_fs_nscache_node * ns    106                struct sos_fs_nscache_node * nsnode);
107                                                   107 
108                                                   108 
109 /* *******************************************    109 /* **********************************************************
110  * Basic low-level memory & co related functio    110  * Basic low-level memory & co related functions
111  */                                               111  */
112                                                   112 
113 sos_ret_t                                         113 sos_ret_t
114 sos_fs_subsystem_setup(const char * root_devic    114 sos_fs_subsystem_setup(const char * root_device,
115                        const char * fsname,       115                        const char * fsname,
116                        const char * mount_args    116                        const char * mount_args,
117                        struct sos_fs_manager_i    117                        struct sos_fs_manager_instance ** result_rootfs)
118 {                                                 118 {
119   sos_ret_t retval;                               119   sos_ret_t retval;
120   struct sos_fs_manager_type * fs_type;           120   struct sos_fs_manager_type * fs_type;
121   struct sos_fs_manager_instance * new_fs;        121   struct sos_fs_manager_instance * new_fs;
122   struct sos_fs_node * rdev_fsnode;               122   struct sos_fs_node * rdev_fsnode;
123   int nb_fstypes;                                 123   int nb_fstypes;
124                                                   124 
125   /* root_device is ignored for now */            125   /* root_device is ignored for now */
126   rdev_fsnode    = NULL;                          126   rdev_fsnode    = NULL;
127                                                   127 
128   last_fs_instance_uid = 0;                       128   last_fs_instance_uid = 0;
129   *result_rootfs = NULL;                          129   *result_rootfs = NULL;
130                                                   130 
131   retval = sos_fs_nscache_subsystem_setup();      131   retval = sos_fs_nscache_subsystem_setup();
132   if (SOS_OK != retval)                           132   if (SOS_OK != retval)
133     return retval;                                133     return retval;
134                                                   134 
135   /* Look for the FS manager type */              135   /* Look for the FS manager type */
136   list_foreach(fs_list, fs_type, nb_fstypes)      136   list_foreach(fs_list, fs_type, nb_fstypes)
137     {                                             137     {
138       if (! strcmp(fsname, fs_type->name))        138       if (! strcmp(fsname, fs_type->name))
139         break;                                    139         break;
140     }                                             140     }
141   if (! list_foreach_early_break(fs_list, fs_t    141   if (! list_foreach_early_break(fs_list, fs_type, nb_fstypes))
142     return -SOS_ENODEV;                           142     return -SOS_ENODEV;
143                                                   143 
144   retval = fs_type->mount(fs_type,                144   retval = fs_type->mount(fs_type,
145                           rdev_fsnode,            145                           rdev_fsnode,
146                           mount_args, & new_fs    146                           mount_args, & new_fs);
147   if (SOS_OK != retval)                           147   if (SOS_OK != retval)
148     {                                             148     {
149       if (rdev_fsnode)                            149       if (rdev_fsnode)
150         sos_fs_unref_fsnode(rdev_fsnode);         150         sos_fs_unref_fsnode(rdev_fsnode);
151       return retval;                              151       return retval;
152     }                                             152     }
153                                                   153 
154   /* Update some reserved fields */               154   /* Update some reserved fields */
155   sos_fs_nscache_get_fs_node(new_fs->root)->fs    155   sos_fs_nscache_get_fs_node(new_fs->root)->fs = new_fs;
156                                                   156 
157   *result_rootfs = new_fs;                        157   *result_rootfs = new_fs;
158   return SOS_OK;                                  158   return SOS_OK;
159 }                                                 159 }
160                                                   160 
161                                                   161 
162 sos_ret_t sos_fs_ref_fsnode(struct sos_fs_node    162 sos_ret_t sos_fs_ref_fsnode(struct sos_fs_node * fsnode)
163 {                                                 163 {
164   fsnode->inmem_ref_cnt ++;                       164   fsnode->inmem_ref_cnt ++;
165   return SOS_OK;                                  165   return SOS_OK;
166 }                                                 166 }
167                                                   167 
168                                                   168 
169 sos_ret_t _sos_fs_unref_fsnode(struct sos_fs_n    169 sos_ret_t _sos_fs_unref_fsnode(struct sos_fs_node * node)
170 {                                                 170 {
171   SOS_ASSERT_FATAL(node->inmem_ref_cnt > 0);      171   SOS_ASSERT_FATAL(node->inmem_ref_cnt > 0);
172                                                   172 
173   /* Commit the changes the the FS when the la    173   /* Commit the changes the the FS when the last reference is being
174      removed */                                   174      removed */
175   if ((node->inmem_ref_cnt == 1) && (node->dir    175   if ((node->inmem_ref_cnt == 1) && (node->dirty))
176     {                                             176     {
177       SOS_ASSERT_FATAL(SOS_OK == sos_fs_sync_n    177       SOS_ASSERT_FATAL(SOS_OK == sos_fs_sync_node(node));
178     }                                             178     }
179                                                   179       
180   node->inmem_ref_cnt --;                         180   node->inmem_ref_cnt --;
181                                                   181 
182   if (node->inmem_ref_cnt == 0)                   182   if (node->inmem_ref_cnt == 0)
183     {                                             183     {
184       if (SOS_FS_NODE_DEVICE_CHAR == node->typ    184       if (SOS_FS_NODE_DEVICE_CHAR == node->type)
185         sos_chardev_helper_release_fsnode(node    185         sos_chardev_helper_release_fsnode(node);
186       else if (SOS_FS_NODE_DEVICE_BLOCK == nod << 
187         sos_blockdev_helper_release_fsnode(nod << 
188       sos_hash_remove(node->fs->nodecache, nod    186       sos_hash_remove(node->fs->nodecache, node);
189       node->destructor(node);                     187       node->destructor(node);
190     }                                             188     }
191                                                   189 
192   return SOS_OK;                                  190   return SOS_OK;
193 }                                                 191 }
194                                                   192 
195                                                   193 
196 sos_ret_t sos_fs_ref_opened_file(struct sos_fs    194 sos_ret_t sos_fs_ref_opened_file(struct sos_fs_opened_file * of)
197 {                                                 195 {
198   of->ref_cnt ++;                                 196   of->ref_cnt ++;
199   return SOS_OK;                                  197   return SOS_OK;
200 }                                                 198 }
201                                                   199 
202                                                   200 
203 sos_ret_t _sos_fs_unref_opened_file(struct sos    201 sos_ret_t _sos_fs_unref_opened_file(struct sos_fs_opened_file ** _of)
204 {                                                 202 {
205   struct sos_fs_opened_file * of = *_of;          203   struct sos_fs_opened_file * of = *_of;
206   *_of = NULL;                                    204   *_of = NULL;
207                                                   205 
208   SOS_ASSERT_FATAL(of->ref_cnt > 0);              206   SOS_ASSERT_FATAL(of->ref_cnt > 0);
209   of->ref_cnt --;                                 207   of->ref_cnt --;
210                                                   208 
211   if (0 == of->ref_cnt)                           209   if (0 == of->ref_cnt)
212     {                                             210     {
213       sos_ret_t retval;                           211       sos_ret_t retval;
214       struct sos_fs_nscache_node * nsnode = of    212       struct sos_fs_nscache_node * nsnode = of->direntry;
215       struct sos_fs_node * fsnode = sos_fs_nsc    213       struct sos_fs_node * fsnode = sos_fs_nscache_get_fs_node(nsnode);
216                                                   214 
217       retval = fsnode->close_opened_file(fsnod    215       retval = fsnode->close_opened_file(fsnode, of);
218       if (SOS_OK != retval)                       216       if (SOS_OK != retval)
219         return retval;                            217         return retval;
220                                                   218       
221       return sos_fs_nscache_unref_node(nsnode)    219       return sos_fs_nscache_unref_node(nsnode);
222     }                                             220     }
223                                                   221 
224   return SOS_OK;                                  222   return SOS_OK;
225 }                                                 223 }
226                                                   224 
227                                                   225 
228 /* *******************************************    226 /* **********************************************************
229  * Some helper functions                          227  * Some helper functions
230  */                                               228  */
231                                                   229 
232 /** Fetch the given fsnode from hash first, or    230 /** Fetch the given fsnode from hash first, or from disk when not in
233     hash */                                       231     hash */
234 static sos_ret_t fs_fetch_node(struct sos_fs_m    232 static sos_ret_t fs_fetch_node(struct sos_fs_manager_instance *fs,
235                                sos_ui64_t stor    233                                sos_ui64_t storage_location,
236                                struct sos_fs_n    234                                struct sos_fs_node ** result_fsnode)
237 {                                                 235 {
238   sos_ret_t retval;                               236   sos_ret_t retval;
239                                                   237 
240   /* If it is already loaded in memory, no nee    238   /* If it is already loaded in memory, no need to look further */
241   *result_fsnode = (struct sos_fs_node*)          239   *result_fsnode = (struct sos_fs_node*)
242     sos_hash_lookup(fs->nodecache,                240     sos_hash_lookup(fs->nodecache,
243                     & storage_location);          241                     & storage_location);
244   if (*result_fsnode)                             242   if (*result_fsnode)
245     return SOS_OK;                                243     return SOS_OK;
246                                                   244 
247   /* Otherwise, call the appropriate method of    245   /* Otherwise, call the appropriate method of the FS */
248   retval = fs->fetch_node_from_disk(fs, storag    246   retval = fs->fetch_node_from_disk(fs, storage_location, result_fsnode);
249   if (SOS_OK != retval)                           247   if (SOS_OK != retval)
250     return retval;                                248     return retval;
251                                                   249 
252   (*result_fsnode)->generation    = 0;            250   (*result_fsnode)->generation    = 0;
253                                                   251 
254   /* Special case for device nodes */             252   /* Special case for device nodes */
255   if (SOS_FS_NODE_DEVICE_CHAR == (*result_fsno    253   if (SOS_FS_NODE_DEVICE_CHAR == (*result_fsnode)->type)
256     SOS_ASSERT_FATAL(SOS_OK                       254     SOS_ASSERT_FATAL(SOS_OK
257                      == sos_chardev_helper_ref    255                      == sos_chardev_helper_ref_new_fsnode(*result_fsnode));
258   else if (SOS_FS_NODE_DEVICE_BLOCK == (*resul << 
259     SOS_ASSERT_FATAL(SOS_OK                    << 
260                      == sos_blockdev_helper_re << 
261                                                << 
262   sos_hash_insert(fs->nodecache, *result_fsnod    256   sos_hash_insert(fs->nodecache, *result_fsnode);
263   return SOS_OK;                                  257   return SOS_OK;
264 }                                                 258 }
265                                                   259 
266                                                   260 
267 /**                                               261 /**
268  * Helper function to allocate a new on-disk n    262  * Helper function to allocate a new on-disk node
269  */                                               263  */
270 static sos_ret_t                                  264 static sos_ret_t
271 fs_allocate_node(struct sos_fs_manager_instanc    265 fs_allocate_node(struct sos_fs_manager_instance * fs,
272                  sos_fs_node_type_t type,         266                  sos_fs_node_type_t type,
273                  sos_ui32_t flags,                267                  sos_ui32_t flags,
274                  const struct sos_process * cr    268                  const struct sos_process * creator,
275                  sos_ui32_t access_rights,        269                  sos_ui32_t access_rights,
276                  struct sos_fs_node ** result_    270                  struct sos_fs_node ** result_fsnode)
277 {                                                 271 {
278   sos_ret_t retval;                               272   sos_ret_t retval;
279                                                   273 
280   /* Make sure FS is writable ! */                274   /* Make sure FS is writable ! */
281   if (fs->flags & SOS_FS_MOUNT_READONLY)          275   if (fs->flags & SOS_FS_MOUNT_READONLY)
282     return -SOS_EPERM;                            276     return -SOS_EPERM;
283                                                   277 
284   /* Allocate the node on disk */                 278   /* Allocate the node on disk */
285   retval = fs->allocate_new_node(fs, type,        279   retval = fs->allocate_new_node(fs, type,
286                                  creator, acce    280                                  creator, access_rights,
287                                  flags,           281                                  flags,
288                                  result_fsnode    282                                  result_fsnode);
289   if (SOS_OK != retval)                           283   if (SOS_OK != retval)
290     return retval;                                284     return retval;
291                                                   285 
292   /* Update some resrved fields */                286   /* Update some resrved fields */
293   (*result_fsnode)->fs = fs;                      287   (*result_fsnode)->fs = fs;
294                                                   288 
295   /* Special case for device nodes */             289   /* Special case for device nodes */
296   if (SOS_FS_NODE_DEVICE_CHAR == (*result_fsno    290   if (SOS_FS_NODE_DEVICE_CHAR == (*result_fsnode)->type)
297     {                                             291     {
298       SOS_ASSERT_FATAL(SOS_OK                     292       SOS_ASSERT_FATAL(SOS_OK
299                        == sos_chardev_helper_r    293                        == sos_chardev_helper_ref_new_fsnode(*result_fsnode));
300     }                                             294     }
301   else if (SOS_FS_NODE_DEVICE_BLOCK == (*resul << 
302     {                                          << 
303       SOS_ASSERT_FATAL(SOS_OK                  << 
304                        == sos_blockdev_helper_ << 
305     }                                          << 
306                                                << 
307                                                   295 
308   /* insert it in the node cache */               296   /* insert it in the node cache */
309   retval = sos_hash_insert(fs->nodecache, *res    297   retval = sos_hash_insert(fs->nodecache, *result_fsnode);
310   if (SOS_OK != retval)                           298   if (SOS_OK != retval)
311     {                                             299     {
312       sos_fs_unref_fsnode(*result_fsnode);        300       sos_fs_unref_fsnode(*result_fsnode);
313       return retval;                              301       return retval;
314     }                                             302     }
315                                                   303 
316   /* Success: Consider the node as dirty */       304   /* Success: Consider the node as dirty */
317   mark_dirty_fsnode(*result_fsnode, FALSE);       305   mark_dirty_fsnode(*result_fsnode, FALSE);
318   return retval;                                  306   return retval;
319 }                                                 307 }
320                                                   308 
321                                                   309 
322 /** Helper function to add the given node in t    310 /** Helper function to add the given node in the dirty list, or to
323     write it directly to the disk if the syste    311     write it directly to the disk if the system is mounted in SYNC
324     mode */                                       312     mode */
325 static sos_ret_t mark_dirty_fsnode(struct sos_    313 static sos_ret_t mark_dirty_fsnode(struct sos_fs_node * fsnode,
326                                    sos_bool_t     314                                    sos_bool_t force_sync)
327 {                                                 315 {
328   sos_ret_t retval;                               316   sos_ret_t retval;
329   sos_bool_t was_dirty = fsnode->dirty;           317   sos_bool_t was_dirty = fsnode->dirty;
330                                                   318 
331   fsnode->dirty = TRUE;                           319   fsnode->dirty = TRUE;
332   fsnode->generation ++;                          320   fsnode->generation ++;
333   retval = SOS_OK;                                321   retval = SOS_OK;
334                                                   322 
335   /* If the fsnode is newly dirty, add it to t    323   /* If the fsnode is newly dirty, add it to the dirty list of the
336      FS */                                        324      FS */
337   if (!was_dirty && fsnode->dirty)                325   if (!was_dirty && fsnode->dirty)
338     list_add_tail_named(fsnode->fs->dirty_node    326     list_add_tail_named(fsnode->fs->dirty_nodes, fsnode,
339                         prev_dirty, next_dirty    327                         prev_dirty, next_dirty);
340                                                   328 
341   if (force_sync || (fsnode->fs->flags & SOS_F    329   if (force_sync || (fsnode->fs->flags & SOS_FS_MOUNT_SYNC))
342     return sos_fs_sync_node(fsnode);           !! 330     {
                                                   >> 331       /* Commit the node changes to the FS */
                                                   >> 332       if (SOS_OK == sos_fs_sync_node(fsnode))
                                                   >> 333         {
                                                   >> 334           /* Commit the FS changes to the device */
                                                   >> 335           if (SOS_OK
                                                   >> 336               == fsnode->fs->device->sync(fsnode->fs->device))
                                                   >> 337             return SOS_OK;
                                                   >> 338 
                                                   >> 339           /* We got a problem: FORCE re-add the node to the dirty list */
                                                   >> 340           was_dirty = FALSE;
                                                   >> 341           fsnode->dirty = TRUE;
                                                   >> 342           retval = -SOS_EBUSY;
                                                   >> 343         }
                                                   >> 344     }
343                                                   345 
344   return retval;                                  346   return retval;
345 }                                                 347 }
346                                                   348 
347                                                   349 
348 /** Remove the given node from the dirty list     350 /** Remove the given node from the dirty list of the FS */
349 static sos_ret_t sos_fs_sync_node(struct sos_f    351 static sos_ret_t sos_fs_sync_node(struct sos_fs_node * fsnode)
350 {                                                 352 {
351   sos_ret_t retval;                               353   sos_ret_t retval;
352                                                   354 
353   if (! fsnode->dirty)                            355   if (! fsnode->dirty)
354     return SOS_OK;                                356     return SOS_OK;
355                                                   357 
356   retval = fsnode->ops_file->sync(fsnode);     !! 358   retval = fsnode->sync(fsnode);
357   if (SOS_OK != retval)                           359   if (SOS_OK != retval)
358     return retval;                                360     return retval;
359                                                   361 
360   /* Remove it from the dirty list */             362   /* Remove it from the dirty list */
361   list_delete_named(fsnode->fs->dirty_nodes, f    363   list_delete_named(fsnode->fs->dirty_nodes, fsnode,
362                     prev_dirty, next_dirty);      364                     prev_dirty, next_dirty);
363   fsnode->dirty = FALSE;                          365   fsnode->dirty = FALSE;
364                                                   366 
365   /* Commit the FS changes to the device */    << 
366   if (fsnode->fs->device)                      << 
367     {                                          << 
368       retval = sos_blockdev_helper_sync_fsnode << 
369       if (SOS_OK != retval)                    << 
370         {                                      << 
371           /* We got a problem ! Mark the node  << 
372           list_add_tail_named(fsnode->fs->dirt << 
373                               prev_dirty, next << 
374           fsnode->dirty = TRUE;                << 
375           return retval;                       << 
376         }                                      << 
377     }                                          << 
378                                                << 
379   return SOS_OK;                                  367   return SOS_OK;
380 }                                                 368 }
381                                                   369 
382                                                   370 
383 /** Collapse the whole dirty list of the FS an    371 /** Collapse the whole dirty list of the FS and commit the changes to
384     the underlying device */                      372     the underlying device */
385 static sos_ret_t sos_fs_sync_fs(struct sos_fs_    373 static sos_ret_t sos_fs_sync_fs(struct sos_fs_manager_instance * fs)
386 {                                                 374 {
387   struct sos_fs_node * fsnode;                    375   struct sos_fs_node * fsnode;
388   while (NULL != (fsnode = list_get_head_named    376   while (NULL != (fsnode = list_get_head_named(fs->dirty_nodes,
389                                                   377                                                prev_dirty, next_dirty)))
390     {                                             378     {
391       sos_ret_t retval = sos_fs_sync_node(fsno    379       sos_ret_t retval = sos_fs_sync_node(fsnode);
392       if (SOS_OK != retval)                       380       if (SOS_OK != retval)
393         return retval;                            381         return retval;
394     }                                             382     }
                                                   >> 383   
                                                   >> 384   if (NULL != fs->device)
                                                   >> 385       return fs->device->sync(fs->device);
395                                                   386 
396   return SOS_OK;                                  387   return SOS_OK;
397 }                                                 388 }
398                                                   389 
399                                                   390 
400 /**                                               391 /**
401  * Resolve the given symlink: return the nsnod    392  * Resolve the given symlink: return the nsnode for the destination
402  * of the symlink, or error status for danglin    393  * of the symlink, or error status for dangling symlinks
403  *                                                394  *
404  * @note result_nsnode is a NEW reference to t    395  * @note result_nsnode is a NEW reference to the node. It should be
405  * unreferenced when unused                       396  * unreferenced when unused
406  */                                               397  */
407 static sos_ret_t                                  398 static sos_ret_t
408 fs_resolve_symlink(const struct sos_fs_nscache    399 fs_resolve_symlink(const struct sos_fs_nscache_node * root_nsnode,
409                    const struct sos_fs_nscache    400                    const struct sos_fs_nscache_node * symlink_nsnode,
410                    struct sos_fs_nscache_node     401                    struct sos_fs_nscache_node ** target_nsnode,
411                    int lookup_recursion_level)    402                    int lookup_recursion_level)
412 {                                                 403 {
413   sos_ret_t retval;                               404   sos_ret_t retval;
414   const struct sos_fs_nscache_node * start_nsn    405   const struct sos_fs_nscache_node * start_nsnode;
415   struct sos_fs_node * symlink_fsnode;            406   struct sos_fs_node * symlink_fsnode;
416   struct sos_fs_pathname path;                    407   struct sos_fs_pathname path;
417   struct sos_fs_pathname remaining;               408   struct sos_fs_pathname remaining;
418                                                   409 
419   symlink_fsnode = sos_fs_nscache_get_fs_node(    410   symlink_fsnode = sos_fs_nscache_get_fs_node(symlink_nsnode);
420   retval = symlink_fsnode->ops_symlink->expand    411   retval = symlink_fsnode->ops_symlink->expand(symlink_fsnode,
421                                                   412                                                & path.contents,
422                                                   413                                                & path.length);
423   if (SOS_OK != retval)                           414   if (SOS_OK != retval)
424     return retval;                                415     return retval;
425   if (path.length <= 0)                           416   if (path.length <= 0)
426     return -SOS_ENOENT;                           417     return -SOS_ENOENT;
427                                                   418 
428   /* Absolute path for target ? */                419   /* Absolute path for target ? */
429   if (path.contents[0] == '/')                    420   if (path.contents[0] == '/')
430     start_nsnode = root_nsnode;                   421     start_nsnode = root_nsnode;
431   else                                            422   else
432     {                                             423     {
433       retval = sos_fs_nscache_get_parent(symli    424       retval = sos_fs_nscache_get_parent(symlink_nsnode,
434                                          (stru    425                                          (struct sos_fs_nscache_node**)& start_nsnode);
435       if (SOS_OK != retval)                       426       if (SOS_OK != retval)
436         return retval;                            427         return retval;
437     }                                             428     }
438                                                   429 
439   retval = fs_lookup_node(& path, TRUE, root_n    430   retval = fs_lookup_node(& path, TRUE, root_nsnode, start_nsnode,
440                           target_nsnode,          431                           target_nsnode,
441                           & remaining, lookup_    432                           & remaining, lookup_recursion_level);
442   if (SOS_OK != retval)                           433   if (SOS_OK != retval)
443     return retval;                                434     return retval;
444                                                   435 
445   /* The target of the symlink could not be co    436   /* The target of the symlink could not be completely opened ! */
446   if (remaining.length != 0)                      437   if (remaining.length != 0)
447     {                                             438     {
448       sos_fs_nscache_unref_node(*target_nsnode    439       sos_fs_nscache_unref_node(*target_nsnode);
449       return -SOS_ENOENT;                         440       return -SOS_ENOENT;
450     }                                             441     }
451                                                   442 
452   return SOS_OK;                                  443   return SOS_OK;
453 }                                                 444 }
454                                                   445 
455                                                   446 
456 #define MAX_LOOKUP_RECURSION_LEVEL 5              447 #define MAX_LOOKUP_RECURSION_LEVEL 5
457                                                   448 
458                                                   449 
459 /**                                               450 /**
460  * @return OK in any case, except if 1/ a syml    451  * @return OK in any case, except if 1/ a symlink could not be
461  * resolved, or 2/ a path "a/b" is given where    452  * resolved, or 2/ a path "a/b" is given where "a" is not a directory,
462  * or 3/ a fsnode that should exist could not     453  * or 3/ a fsnode that should exist could not be retrieved from disk.
463  *                                                454  *
464  * @param result_remaining_path contains the p    455  * @param result_remaining_path contains the path that could not be resolved
465  *                                                456  *
466  * @param result_nsnode a NEW reference to the    457  * @param result_nsnode a NEW reference to the farthest node that
467  * could be resolved. It should be unreference    458  * could be resolved. It should be unreferenced when unused
468  */                                               459  */
469 static sos_ret_t                                  460 static sos_ret_t
470 fs_lookup_node(const struct sos_fs_pathname *     461 fs_lookup_node(const struct sos_fs_pathname * path,
471                sos_bool_t follow_symlinks,        462                sos_bool_t follow_symlinks,
472                const struct sos_fs_nscache_nod    463                const struct sos_fs_nscache_node * root_nsnode,
473                const struct sos_fs_nscache_nod    464                const struct sos_fs_nscache_node * start_nsnode,
474                struct sos_fs_nscache_node ** r    465                struct sos_fs_nscache_node ** result_nsnode,
475                struct sos_fs_pathname * result    466                struct sos_fs_pathname * result_remaining_path,
476                int lookup_recursion_level)        467                int lookup_recursion_level)
477 {                                                 468 {
478   sos_ret_t retval;                               469   sos_ret_t retval;
479   struct sos_fs_nscache_node * current_nsnode;    470   struct sos_fs_nscache_node * current_nsnode;
480                                                   471 
481   /* Make sure we did not go too deep while re    472   /* Make sure we did not go too deep while resolving symlinks */
482   lookup_recursion_level ++;                      473   lookup_recursion_level ++;
483   if (lookup_recursion_level > MAX_LOOKUP_RECU    474   if (lookup_recursion_level > MAX_LOOKUP_RECURSION_LEVEL)
484     {                                             475     {
485       return -SOS_ELOOP;                          476       return -SOS_ELOOP;
486     }                                             477     }
487                                                   478 
488   if (path->length <= 0)                          479   if (path->length <= 0)
489     return -SOS_ENOENT;                           480     return -SOS_ENOENT;
490                                                   481 
491   *result_nsnode = NULL;                          482   *result_nsnode = NULL;
492   memcpy(result_remaining_path, path, sizeof(*    483   memcpy(result_remaining_path, path, sizeof(*path));
493                                                   484 
494   current_nsnode = (struct sos_fs_nscache_node    485   current_nsnode = (struct sos_fs_nscache_node *)start_nsnode;
495   sos_fs_nscache_ref_node(current_nsnode);        486   sos_fs_nscache_ref_node(current_nsnode);
496   while (1)                                       487   while (1)
497     {                                             488     {
498       struct sos_fs_pathname current_component    489       struct sos_fs_pathname current_component, remaining;
499       struct sos_fs_nscache_node * next_nsnode    490       struct sos_fs_nscache_node * next_nsnode = NULL;
500       sos_bool_t slashes_after_first_component    491       sos_bool_t slashes_after_first_component;
501                                                   492 
502 /*       dbg_dump_pathname("Before", result_re    493 /*       dbg_dump_pathname("Before", result_remaining_path); */
503                                                   494 
504       /* Extract the next component of the pat    495       /* Extract the next component of the path */
505       slashes_after_first_component               496       slashes_after_first_component
506         = sos_fs_pathname_split_path(result_re    497         = sos_fs_pathname_split_path(result_remaining_path,
507                                      & current    498                                      & current_component, & remaining);
508 /*       dbg_dump_pathname("After", result_rem    499 /*       dbg_dump_pathname("After", result_remaining_path); */
509 /*       dbg_dump_pathname("Cur", & current_co    500 /*       dbg_dump_pathname("Cur", & current_component); */
510 /*       dbg_dump_pathname("Rem", & remaining)    501 /*       dbg_dump_pathname("Rem", & remaining); */
511 /*       sos_bochs_printf("Slash after=%d\n",     502 /*       sos_bochs_printf("Slash after=%d\n", slashes_after_first_component); */
512                                                   503 
513       /* Could resolve the whole path ? */        504       /* Could resolve the whole path ? */
514       if (current_component.length == 0)          505       if (current_component.length == 0)
515         {                                         506         {
516           /* Ok, fine, we got it ! */             507           /* Ok, fine, we got it ! */
517           memcpy(result_remaining_path, & rema    508           memcpy(result_remaining_path, & remaining, sizeof(remaining));
518           *result_nsnode = current_nsnode;        509           *result_nsnode = current_nsnode;        
519           return SOS_OK;                          510           return SOS_OK;
520         }                                         511         }
521                                                   512 
522       /* Otherwise: make sure we reached a DIR    513       /* Otherwise: make sure we reached a DIR node */
523       if (sos_fs_nscache_get_fs_node(current_n    514       if (sos_fs_nscache_get_fs_node(current_nsnode)->type
524           != SOS_FS_NODE_DIRECTORY)               515           != SOS_FS_NODE_DIRECTORY)
525         {                                         516         {
526           sos_fs_nscache_unref_node(current_ns    517           sos_fs_nscache_unref_node(current_nsnode);
527           return -SOS_ENOENT;                     518           return -SOS_ENOENT;
528         }                                         519         }
529                                                   520       
530       /* Make sure this directory is "executab    521       /* Make sure this directory is "executable" */
531       if (! (sos_fs_nscache_get_fs_node(curren    522       if (! (sos_fs_nscache_get_fs_node(current_nsnode)->access_rights
532              & SOS_FS_EXECUTABLE) )               523              & SOS_FS_EXECUTABLE) )
533         {                                         524         {
534           sos_fs_nscache_unref_node(current_ns    525           sos_fs_nscache_unref_node(current_nsnode);
535           return -SOS_EACCES;                     526           return -SOS_EACCES;
536         }                                         527         }
537                                                   528 
538       /* If we can find the entry in the names    529       /* If we can find the entry in the namespace cache, it is really
539          fine ! */                                530          fine ! */
540       retval = sos_fs_nscache_lookup(current_n    531       retval = sos_fs_nscache_lookup(current_nsnode,
541                                      & current    532                                      & current_component,
542                                      root_nsno    533                                      root_nsnode,
543                                      & next_ns    534                                      & next_nsnode);
544       if (SOS_OK != retval)                       535       if (SOS_OK != retval)
545         {                                         536         {
546           struct sos_fs_node * current_fsnode,    537           struct sos_fs_node * current_fsnode, * next_fsnode;
547           sos_ui64_t storage_location;            538           sos_ui64_t storage_location;
548                                                   539 
549           /*                                      540           /*
550            * Not found in the namespace cache.    541            * Not found in the namespace cache. Must read from the
551            * disk...                              542            * disk...
552            */                                     543            */
553           current_fsnode = sos_fs_nscache_get_    544           current_fsnode = sos_fs_nscache_get_fs_node(current_nsnode);
554                                                   545 
555           retval = current_fsnode->ops_dir        546           retval = current_fsnode->ops_dir
556             ->lookup(current_fsnode,              547             ->lookup(current_fsnode,
557                      current_component.content    548                      current_component.contents,
558                      current_component.length,    549                      current_component.length,
559                      & storage_location);         550                      & storage_location);
560           if (SOS_OK != retval)                   551           if (SOS_OK != retval)
561             {                                     552             {
562               /* Well, we cannot go further, s    553               /* Well, we cannot go further, stop here */
563               *result_nsnode = current_nsnode;    554               *result_nsnode = current_nsnode;
564               return SOS_OK;                      555               return SOS_OK;
565             }                                     556             }
566                                                   557 
567           /* Now retrieve this node from disk     558           /* Now retrieve this node from disk or from the cache into
568              memory */                            559              memory */
569           retval = fs_fetch_node(current_fsnod    560           retval = fs_fetch_node(current_fsnode->fs,
570                                  storage_locat    561                                  storage_location, & next_fsnode);
571           if (SOS_OK != retval)                   562           if (SOS_OK != retval)
572             {                                     563             {
573               sos_fs_nscache_unref_node(curren    564               sos_fs_nscache_unref_node(current_nsnode);
574               return retval;                      565               return retval;
575             }                                     566             }
576                                                   567       
577           /* Integrate it in the nscache */       568           /* Integrate it in the nscache */
578           retval = sos_fs_nscache_add_new_chil    569           retval = sos_fs_nscache_add_new_child_node(current_nsnode,
579                                                   570                                                      & current_component,
580                                                   571                                                      next_fsnode,
581                                                   572                                                      & next_nsnode);
582           sos_fs_nscache_unref_node(current_ns    573           sos_fs_nscache_unref_node(current_nsnode);
583           if (SOS_OK != retval)                   574           if (SOS_OK != retval)
584             return retval;                        575             return retval;
585         }                                         576         }
586       else                                        577       else
587         sos_fs_nscache_unref_node(current_nsno    578         sos_fs_nscache_unref_node(current_nsnode);
588                                                   579 
589       /* Reaching a symlink ? */                  580       /* Reaching a symlink ? */
590       if (sos_fs_nscache_get_fs_node(next_nsno    581       if (sos_fs_nscache_get_fs_node(next_nsnode)->type
591           == SOS_FS_NODE_SYMLINK)                 582           == SOS_FS_NODE_SYMLINK)
592         {                                         583         {
593           /* Expand the link only for non-term    584           /* Expand the link only for non-terminal nodes, or for the
594              terminal node only if follow_syml    585              terminal node only if follow_symlinks is TRUE */
595           if ( (remaining.length != 0)            586           if ( (remaining.length != 0)
596                || follow_symlinks )               587                || follow_symlinks )
597             {                                     588             {
598               struct sos_fs_nscache_node * sym    589               struct sos_fs_nscache_node * symlink_target;
599                                                   590 
600               retval = fs_resolve_symlink(root    591               retval = fs_resolve_symlink(root_nsnode, next_nsnode,
601                                           & sy    592                                           & symlink_target,
602                                           look    593                                           lookup_recursion_level);
603               sos_fs_nscache_unref_node(next_n    594               sos_fs_nscache_unref_node(next_nsnode);
604               if (SOS_OK != retval)               595               if (SOS_OK != retval)
605                 return retval; /* Dangling sym    596                 return retval; /* Dangling symlink */
606                                                   597 
607               next_nsnode = symlink_target;       598               next_nsnode = symlink_target;
608             }                                     599             }
609         }                                         600         }
610                                                   601       
611       /* Make sure there was no slash after th    602       /* Make sure there was no slash after this component, unless
612          this component is a directory */         603          this component is a directory */
613       if (slashes_after_first_component           604       if (slashes_after_first_component
614           &&                                      605           &&
615           ( sos_fs_nscache_get_fs_node(next_ns    606           ( sos_fs_nscache_get_fs_node(next_nsnode)->type
616             != SOS_FS_NODE_DIRECTORY) )           607             != SOS_FS_NODE_DIRECTORY) )
617         {                                         608         {
618           sos_fs_nscache_unref_node(next_nsnod    609           sos_fs_nscache_unref_node(next_nsnode);
619           return -SOS_ENOTDIR;                    610           return -SOS_ENOTDIR;
620         }                                         611         }
621                                                   612 
622       /* Ok, fine, we got it, update the path     613       /* Ok, fine, we got it, update the path we still have to explore */
623       memcpy(result_remaining_path, & remainin    614       memcpy(result_remaining_path, & remaining, sizeof(remaining));
624       current_nsnode = next_nsnode;               615       current_nsnode = next_nsnode;
625     }                                             616     }
626                                                   617 
627   sos_display_fatal_error("Should not get ther    618   sos_display_fatal_error("Should not get there");
628   return -SOS_EFATAL;                             619   return -SOS_EFATAL;
629 }                                                 620 }
630                                                   621 
631                                                   622 
632 /**                                               623 /**
633  * It is assumed that parent does not already     624  * It is assumed that parent does not already have a child with the
634  * given name. We make sure that the "path" is    625  * given name. We make sure that the "path" is a single entity (ie
635  * not "a/b")                                     626  * not "a/b")
636  * @return Error if fsnode is not on the same     627  * @return Error if fsnode is not on the same FS as parent_nsnode
637  */                                               628  */
638 static sos_ret_t                                  629 static sos_ret_t
639 fs_register_child_node(const struct sos_proces    630 fs_register_child_node(const struct sos_process * creator,
640                        struct sos_fs_nscache_n    631                        struct sos_fs_nscache_node * parent_nsnode,
641                        const struct sos_fs_pat    632                        const struct sos_fs_pathname * name,
642                        struct sos_fs_node * fs    633                        struct sos_fs_node * fsnode,
643                        sos_ui32_t flags,          634                        sos_ui32_t flags,
644                        struct sos_fs_nscache_n    635                        struct sos_fs_nscache_node ** result_nsnode)
645 {                                                 636 {
646   sos_ret_t retval;                               637   sos_ret_t retval;
647   struct sos_fs_node * parent_fsnode;             638   struct sos_fs_node * parent_fsnode;
648   struct sos_fs_pathname first_component, rema    639   struct sos_fs_pathname first_component, remaining;
649   sos_bool_t slashes_after_first_component = F    640   sos_bool_t slashes_after_first_component = FALSE;
650                                                   641 
651   parent_fsnode = sos_fs_nscache_get_fs_node(p    642   parent_fsnode = sos_fs_nscache_get_fs_node(parent_nsnode);
652   if (parent_fsnode->type != SOS_FS_NODE_DIREC    643   if (parent_fsnode->type != SOS_FS_NODE_DIRECTORY)
653     return -SOS_ENOTDIR;                          644     return -SOS_ENOTDIR;
654                                                   645 
655   if (name->length <= 0)                          646   if (name->length <= 0)
656     return -SOS_EINVAL;                           647     return -SOS_EINVAL;
657                                                   648 
658   slashes_after_first_component                   649   slashes_after_first_component
659     = sos_fs_pathname_split_path(name, & first    650     = sos_fs_pathname_split_path(name, & first_component, & remaining);
660                                                   651 
661   if (fsnode->type != SOS_FS_NODE_DIRECTORY)      652   if (fsnode->type != SOS_FS_NODE_DIRECTORY)
662     {                                             653     {
663       /* Make sure the given name is exactly a    654       /* Make sure the given name is exactly a single path component
664          (ie no '/') */                           655          (ie no '/') */
665       if (slashes_after_first_component)          656       if (slashes_after_first_component)
666         return -SOS_EINVAL;                       657         return -SOS_EINVAL;
667     }                                             658     }
668   else                                            659   else
669     {                                             660     {
670       /* Make sure there aren't any other comp    661       /* Make sure there aren't any other component behind the '/'s, if
671          any */                                   662          any */
672       if (remaining.length > 0)                   663       if (remaining.length > 0)
673         return -SOS_EINVAL;                       664         return -SOS_EINVAL;
674     }                                             665     }
675                                                   666 
676   /* Make sure the parent directory is writeab    667   /* Make sure the parent directory is writeable */
677   if (! (parent_fsnode->access_rights & SOS_FS    668   if (! (parent_fsnode->access_rights & SOS_FS_WRITABLE) )
678     return -SOS_EACCES;                           669     return -SOS_EACCES;
679                                                   670 
680   /* Make sure that the entries are located on    671   /* Make sure that the entries are located on the same FS */
681   if (fsnode->fs != parent_fsnode->fs)            672   if (fsnode->fs != parent_fsnode->fs)
682     return -SOS_EXDEV;                            673     return -SOS_EXDEV;
683                                                   674 
684   /* Make sure that the nsnode won't be destro    675   /* Make sure that the nsnode won't be destroyed */
685   sos_fs_nscache_ref_node(parent_nsnode);         676   sos_fs_nscache_ref_node(parent_nsnode);
686                                                   677 
687   /* Allocate the node in directory */            678   /* Allocate the node in directory */
688   retval = parent_fsnode->ops_dir->link(parent    679   retval = parent_fsnode->ops_dir->link(parent_fsnode,
689                                         creato    680                                         creator,
690                                         first_    681                                         first_component.contents,
691                                         first_    682                                         first_component.length,
692                                         fsnode    683                                         fsnode);
693   if (SOS_OK != retval)                           684   if (SOS_OK != retval)
694     {                                             685     {
695       sos_fs_nscache_unref_node(parent_nsnode)    686       sos_fs_nscache_unref_node(parent_nsnode);
696       return retval;                              687       return retval;
697     }                                             688     }
698                                                   689 
699   /* Success: Consider the directory as dirty     690   /* Success: Consider the directory as dirty */
700   mark_dirty_fsnode(parent_fsnode, FALSE);        691   mark_dirty_fsnode(parent_fsnode, FALSE);
701                                                   692 
702   /* Allocate the node in nscache cache */        693   /* Allocate the node in nscache cache */
703   retval = sos_fs_nscache_add_new_child_node(p    694   retval = sos_fs_nscache_add_new_child_node(parent_nsnode, & first_component,
704                                              f    695                                              fsnode, result_nsnode);
705                                                   696 
706   sos_fs_nscache_unref_node(parent_nsnode);       697   sos_fs_nscache_unref_node(parent_nsnode);
707   return retval;                                  698   return retval;
708 }                                                 699 }
709                                                   700 
710                                                   701 
711 /** It is assumed that parent does not already    702 /** It is assumed that parent does not already have a child with the
712     given name. We make sure that the "path" i    703     given name. We make sure that the "path" is a single entity (ie
713     not "a/b"). Return a NEW reference to the     704     not "a/b"). Return a NEW reference to the newly-created NS node */
714 static sos_ret_t                                  705 static sos_ret_t
715 fs_create_child_node(struct sos_fs_nscache_nod    706 fs_create_child_node(struct sos_fs_nscache_node * parent_nsnode,
716                      const struct sos_fs_pathn    707                      const struct sos_fs_pathname * name,
717                      sos_fs_node_type_t type,     708                      sos_fs_node_type_t type,
718                      sos_ui32_t flags,            709                      sos_ui32_t flags,
719                      const struct sos_process     710                      const struct sos_process * creator,
720                      sos_ui32_t access_rights,    711                      sos_ui32_t access_rights,
721                      struct sos_fs_nscache_nod    712                      struct sos_fs_nscache_node ** result_nsnode)
722 {                                                 713 {
723   sos_ret_t retval;                               714   sos_ret_t retval;
724   struct sos_fs_node * fsnode, * parent_fsnode    715   struct sos_fs_node * fsnode, * parent_fsnode;
725                                                   716 
726   parent_fsnode = sos_fs_nscache_get_fs_node(p    717   parent_fsnode = sos_fs_nscache_get_fs_node(parent_nsnode);
727   if (parent_fsnode->type != SOS_FS_NODE_DIREC    718   if (parent_fsnode->type != SOS_FS_NODE_DIRECTORY)
728     return -SOS_ENOTDIR;                          719     return -SOS_ENOTDIR;
729                                                   720 
730   /* Make sure that the nsnode won't be destro    721   /* Make sure that the nsnode won't be destroyed */
731   sos_fs_nscache_ref_node(parent_nsnode);         722   sos_fs_nscache_ref_node(parent_nsnode);
732                                                   723 
733   retval = fs_allocate_node(parent_fsnode->fs,    724   retval = fs_allocate_node(parent_fsnode->fs, type, flags, creator,
734                             access_rights, & f    725                             access_rights, & fsnode);
735   if (SOS_OK != retval)                           726   if (SOS_OK != retval)
736     {                                             727     {
737       sos_fs_nscache_unref_node(parent_nsnode)    728       sos_fs_nscache_unref_node(parent_nsnode);
738       return retval;                              729       return retval;
739     }                                             730     }
740                                                   731 
741   retval = fs_register_child_node(creator,        732   retval = fs_register_child_node(creator,
742                                   parent_nsnod    733                                   parent_nsnode, name, fsnode, flags,
743                                   result_nsnod    734                                   result_nsnode);
744   sos_fs_nscache_unref_node(parent_nsnode);       735   sos_fs_nscache_unref_node(parent_nsnode);
745                                                   736 
746   /* The function does not need it anymore */     737   /* The function does not need it anymore */
747   sos_fs_unref_fsnode(fsnode);                    738   sos_fs_unref_fsnode(fsnode);
748                                                   739 
749   return retval;                                  740   return retval;
750 }                                                 741 }
751                                                   742 
752                                                   743 
753 /**                                               744 /**
754  * It is assumed that parent does not already     745  * It is assumed that parent does not already have a child with the
755  * given name, and that the new child does not    746  * given name, and that the new child does not have a parent yet. We
756  * make sure that the "path" is a single entit    747  * make sure that the "path" is a single entity (ie not "a/b") @return
757  * Error if fsnode is not on the same FS as pa    748  * Error if fsnode is not on the same FS as parent_nsnode
758  */                                               749  */
759 static sos_ret_t                                  750 static sos_ret_t
760 fs_connect_existing_child_node(const struct so    751 fs_connect_existing_child_node(const struct sos_process * creator,
761                                struct sos_fs_n    752                                struct sos_fs_nscache_node * parent_nsnode,
762                                const struct so    753                                const struct sos_fs_pathname * name,
763                                struct sos_fs_n    754                                struct sos_fs_nscache_node * nsnode)
764 {                                                 755 {
765   sos_ret_t retval;                               756   sos_ret_t retval;
766   struct sos_fs_node * parent_fsnode, * fsnode    757   struct sos_fs_node * parent_fsnode, * fsnode;
767   struct sos_fs_pathname first_component, rema    758   struct sos_fs_pathname first_component, remaining;
768   sos_bool_t slashes_after_first_component = F    759   sos_bool_t slashes_after_first_component = FALSE;
769                                                   760 
770   fsnode = sos_fs_nscache_get_fs_node(nsnode);    761   fsnode = sos_fs_nscache_get_fs_node(nsnode);
771   parent_fsnode = sos_fs_nscache_get_fs_node(p    762   parent_fsnode = sos_fs_nscache_get_fs_node(parent_nsnode);
772   if (parent_fsnode->type != SOS_FS_NODE_DIREC    763   if (parent_fsnode->type != SOS_FS_NODE_DIRECTORY)
773     return -SOS_ENOTDIR;                          764     return -SOS_ENOTDIR;
774                                                   765 
775   if (name->length <= 0)                          766   if (name->length <= 0)
776     return -SOS_EINVAL;                           767     return -SOS_EINVAL;
777                                                   768 
778   slashes_after_first_component                   769   slashes_after_first_component
779     = sos_fs_pathname_split_path(name, & first    770     = sos_fs_pathname_split_path(name, & first_component, & remaining);
780                                                   771 
781   if (fsnode->type != SOS_FS_NODE_DIRECTORY)      772   if (fsnode->type != SOS_FS_NODE_DIRECTORY)
782     {                                             773     {
783       /* Make sure the given name is exactly a    774       /* Make sure the given name is exactly a single path component
784          (ie no '/') */                           775          (ie no '/') */
785       if (slashes_after_first_component)          776       if (slashes_after_first_component)
786         return -SOS_EINVAL;                       777         return -SOS_EINVAL;
787     }                                             778     }
788   else                                            779   else
789     {                                             780     {
790       /* Make sure there aren't any other comp    781       /* Make sure there aren't any other component behind the '/'s, if
791          any */                                   782          any */
792       if (remaining.length > 0)                   783       if (remaining.length > 0)
793         return -SOS_EINVAL;                       784         return -SOS_EINVAL;
794     }                                             785     }
795                                                   786 
796   /* Make sure the parent directory is writeab    787   /* Make sure the parent directory is writeable */
797   if (! (parent_fsnode->access_rights & SOS_FS    788   if (! (parent_fsnode->access_rights & SOS_FS_WRITABLE) )
798     return -SOS_EACCES;                           789     return -SOS_EACCES;
799                                                   790 
800   /* Make sure that the entries are located on    791   /* Make sure that the entries are located on the same FS */
801   if (fsnode->fs != parent_fsnode->fs)            792   if (fsnode->fs != parent_fsnode->fs)
802     return -SOS_EXDEV;                            793     return -SOS_EXDEV;
803                                                   794 
804   /* Make sure that the nsnode won't be destro    795   /* Make sure that the nsnode won't be destroyed */
805   sos_fs_nscache_ref_node(parent_nsnode);         796   sos_fs_nscache_ref_node(parent_nsnode);
806                                                   797 
807   /* Allocate the node in directory */            798   /* Allocate the node in directory */
808   retval = parent_fsnode->ops_dir->link(parent    799   retval = parent_fsnode->ops_dir->link(parent_fsnode,
809                                         creato    800                                         creator,
810                                         first_    801                                         first_component.contents,
811                                         first_    802                                         first_component.length,
812                                         fsnode    803                                         fsnode);
813   if (SOS_OK != retval)                           804   if (SOS_OK != retval)
814     {                                             805     {
815       sos_fs_nscache_unref_node(parent_nsnode)    806       sos_fs_nscache_unref_node(parent_nsnode);
816       return retval;                              807       return retval;
817     }                                             808     }
818                                                   809 
819   /* Success: Consider the directory as dirty     810   /* Success: Consider the directory as dirty */
820   mark_dirty_fsnode(parent_fsnode, FALSE);        811   mark_dirty_fsnode(parent_fsnode, FALSE);
821                                                   812 
822   /* Allocate the node in nscache cache */        813   /* Allocate the node in nscache cache */
823   retval = sos_fs_nscache_add_existing_child_n    814   retval = sos_fs_nscache_add_existing_child_node(parent_nsnode,
824                                                   815                                                   & first_component,
825                                                   816                                                   nsnode);
826   sos_fs_nscache_unref_node(parent_nsnode);       817   sos_fs_nscache_unref_node(parent_nsnode);
827   return retval;                                  818   return retval;
828 }                                                 819 }
829                                                   820 
830                                                   821 
831 /** Return a new reference to the new node ins    822 /** Return a new reference to the new node inserted unless
832     result_nsnode is NULL */                      823     result_nsnode is NULL */
833 static sos_ret_t                                  824 static sos_ret_t
834 fs_create_node(const struct sos_fs_pathname *     825 fs_create_node(const struct sos_fs_pathname * _path,
835                const struct sos_process * crea    826                const struct sos_process * creator,
836                sos_ui32_t access_rights,          827                sos_ui32_t access_rights,
837                sos_fs_node_type_t type,           828                sos_fs_node_type_t type,
838                struct sos_fs_nscache_node ** r    829                struct sos_fs_nscache_node ** result_nsnode)
839 {                                                 830 {
840   sos_ret_t retval;                               831   sos_ret_t retval;
841   struct sos_fs_pathname path;                    832   struct sos_fs_pathname path;
842   struct sos_fs_nscache_node *nsnode, *new_nsn    833   struct sos_fs_nscache_node *nsnode, *new_nsnode;
843                                                   834 
844   path.contents = _path->contents;                835   path.contents = _path->contents;
845   path.length   = _path->length;                  836   path.length   = _path->length;
846                                                   837 
847   if (path.length <= 0)                           838   if (path.length <= 0)
848     return -SOS_ENOENT;                           839     return -SOS_ENOENT;
849                                                   840 
850   if (path.contents[0] == '/')                    841   if (path.contents[0] == '/')
851     nsnode = sos_process_get_root(creator)->di    842     nsnode = sos_process_get_root(creator)->direntry;
852   else                                            843   else
853     nsnode = sos_process_get_cwd(creator)->dir    844     nsnode = sos_process_get_cwd(creator)->direntry;
854                                                   845 
855   retval = fs_lookup_node(& path,                 846   retval = fs_lookup_node(& path,
856                           TRUE,                   847                           TRUE,
857                           sos_process_get_root    848                           sos_process_get_root(creator)->direntry,
858                           nsnode,                 849                           nsnode,
859                           & nsnode,               850                           & nsnode,
860                           & path,                 851                           & path,
861                           0);                     852                           0);
862   if (SOS_OK != retval)                           853   if (SOS_OK != retval)
863     return retval;                                854     return retval;
864                                                   855 
865   if (path.length <= 0)                           856   if (path.length <= 0)
866     {                                             857     {
867       /* Found the exact match ! */               858       /* Found the exact match ! */
868       sos_fs_nscache_unref_node(nsnode);          859       sos_fs_nscache_unref_node(nsnode);
869       return -SOS_EEXIST;                         860       return -SOS_EEXIST;
870     }                                             861     }
871                                                   862 
872   /* Create a new entry in the file system */     863   /* Create a new entry in the file system */
873   retval = fs_create_child_node(nsnode,           864   retval = fs_create_child_node(nsnode,
874                                 & path,           865                                 & path,
875                                 type,             866                                 type,
876                                 /* flags */0,     867                                 /* flags */0,
877                                 creator, acces    868                                 creator, access_rights,
878                                 & new_nsnode);    869                                 & new_nsnode);
879   sos_fs_nscache_unref_node(nsnode);              870   sos_fs_nscache_unref_node(nsnode);
880                                                   871 
881   /* node not needed by this function ? */        872   /* node not needed by this function ? */
882   if (NULL == result_nsnode)                      873   if (NULL == result_nsnode)
883     sos_fs_nscache_unref_node(new_nsnode);        874     sos_fs_nscache_unref_node(new_nsnode);
884   else                                            875   else
885     *result_nsnode = new_nsnode;                  876     *result_nsnode = new_nsnode;
886                                                   877 
887   return retval;                                  878   return retval;
888 }                                                 879 }
889                                                   880 
890                                                   881 
891 static sos_ret_t                                  882 static sos_ret_t
892 fs_remove_node(const struct sos_process * acto    883 fs_remove_node(const struct sos_process * actor,
893                struct sos_fs_nscache_node * ns    884                struct sos_fs_nscache_node * nsnode)
894 {                                                 885 {
895   sos_ret_t retval;                               886   sos_ret_t retval;
896   struct sos_fs_nscache_node * parent_nsnode;     887   struct sos_fs_nscache_node * parent_nsnode;
897   struct sos_fs_node * parent_fsnode;             888   struct sos_fs_node * parent_fsnode;
898   struct sos_fs_pathname childname;               889   struct sos_fs_pathname childname;
899                                                   890 
900   /* Refuse to do anything if this is the root    891   /* Refuse to do anything if this is the root of a mounted FS */
901   if (nsnode == sos_fs_nscache_get_fs_node(nsn    892   if (nsnode == sos_fs_nscache_get_fs_node(nsnode)->fs->root)
902     return -SOS_EBUSY;                            893     return -SOS_EBUSY;
903                                                   894 
904   retval = sos_fs_nscache_get_parent(nsnode, &    895   retval = sos_fs_nscache_get_parent(nsnode, & parent_nsnode);
905   if (SOS_OK != retval)                           896   if (SOS_OK != retval)
906     return retval;                                897     return retval;
907   parent_fsnode = sos_fs_nscache_get_fs_node(p    898   parent_fsnode = sos_fs_nscache_get_fs_node(parent_nsnode);
908                                                   899 
909   /* Make sure FS is writable ! */                900   /* Make sure FS is writable ! */
910   if (parent_fsnode->fs->flags & SOS_FS_MOUNT_    901   if (parent_fsnode->fs->flags & SOS_FS_MOUNT_READONLY)
911     return -SOS_EPERM;                            902     return -SOS_EPERM;
912                                                   903 
913   /* Make sure the parent directory is writeab    904   /* Make sure the parent directory is writeable */
914   if (! (parent_fsnode->access_rights & SOS_FS    905   if (! (parent_fsnode->access_rights & SOS_FS_WRITABLE) )
915     return -SOS_EACCES;                           906     return -SOS_EACCES;
916                                                   907 
917   sos_fs_nscache_ref_node(parent_nsnode);         908   sos_fs_nscache_ref_node(parent_nsnode);
918                                                   909 
919   sos_fs_nscache_get_name(nsnode, & childname)    910   sos_fs_nscache_get_name(nsnode, & childname);
920   retval = parent_fsnode->ops_dir->unlink(pare    911   retval = parent_fsnode->ops_dir->unlink(parent_fsnode, actor,
921                                           chil    912                                           childname.contents,
922                                           chil    913                                           childname.length);
923   if (SOS_OK == retval)                           914   if (SOS_OK == retval)
924     sos_fs_nscache_disconnect_node(nsnode);       915     sos_fs_nscache_disconnect_node(nsnode);
925                                                   916 
926   /* Unallocate the node */                       917   /* Unallocate the node */
927   if (SOS_OK == retval)                           918   if (SOS_OK == retval)
928     mark_dirty_fsnode(parent_fsnode, FALSE);      919     mark_dirty_fsnode(parent_fsnode, FALSE);
929                                                   920 
930   sos_fs_nscache_unref_node(parent_nsnode);       921   sos_fs_nscache_unref_node(parent_nsnode);
931   return retval;                                  922   return retval;
932 }                                                 923 }
933                                                   924 
934                                                   925 
935 /* *******************************************    926 /* **********************************************************
936  * Exported functions                             927  * Exported functions
937  */                                               928  */
938                                                   929 
939 sos_ret_t sos_fs_new_opened_file(const struct     930 sos_ret_t sos_fs_new_opened_file(const struct sos_process * owner,
940                                  struct sos_fs    931                                  struct sos_fs_nscache_node * nsnode,
941                                  sos_ui32_t op    932                                  sos_ui32_t open_flags,
942                                  struct sos_fs    933                                  struct sos_fs_opened_file ** result_of)
943 {                                                 934 {
944   sos_ret_t retval;                               935   sos_ret_t retval;
945   struct sos_fs_node * fsnode = sos_fs_nscache    936   struct sos_fs_node * fsnode = sos_fs_nscache_get_fs_node(nsnode);
946                                                   937 
947   retval = fsnode->new_opened_file(fsnode, own    938   retval = fsnode->new_opened_file(fsnode, owner, open_flags, result_of);
948   if (SOS_OK != retval)                           939   if (SOS_OK != retval)
949       return retval;                              940       return retval;
950                                                   941 
951   (*result_of)->ref_cnt    = 1;                   942   (*result_of)->ref_cnt    = 1;
952   (*result_of)->generation = 1;                   943   (*result_of)->generation = 1;
953                                                   944 
954   retval = sos_fs_nscache_register_opened_file    945   retval = sos_fs_nscache_register_opened_file(nsnode, *result_of);
955   if (SOS_OK != retval)                           946   if (SOS_OK != retval)
956     {                                             947     {
957       fsnode->close_opened_file(fsnode, *resul    948       fsnode->close_opened_file(fsnode, *result_of);
958       return retval;                              949       return retval;
959     }                                             950     }
960                                                   951 
961   (*result_of)->open_flags = open_flags;          952   (*result_of)->open_flags = open_flags;
962   return SOS_OK;                                  953   return SOS_OK;
963 }                                                 954 }
964                                                   955 
965                                                   956 
966 sos_ret_t                                         957 sos_ret_t
967 sos_fs_duplicate_opened_file(struct sos_fs_ope    958 sos_fs_duplicate_opened_file(struct sos_fs_opened_file * src_of,
968                              const struct sos_    959                              const struct sos_process * dst_proc,
969                              struct sos_fs_ope    960                              struct sos_fs_opened_file ** result_of)
970 {                                                 961 {
971   sos_ret_t retval = src_of->duplicate(src_of,    962   sos_ret_t retval = src_of->duplicate(src_of, dst_proc, result_of);
972   if (SOS_OK != retval)                           963   if (SOS_OK != retval)
973     return retval;                                964     return retval;
974                                                   965 
975   SOS_ASSERT_FATAL((*result_of)->owner == dst_    966   SOS_ASSERT_FATAL((*result_of)->owner == dst_proc);
976   (*result_of)->ref_cnt    = 1;                   967   (*result_of)->ref_cnt    = 1;
977   (*result_of)->generation = 1;                   968   (*result_of)->generation = 1;
978   retval = sos_fs_nscache_register_opened_file    969   retval = sos_fs_nscache_register_opened_file(src_of->direntry, *result_of);
979   if (SOS_OK != retval)                           970   if (SOS_OK != retval)
980     {                                             971     {
981       struct sos_fs_node * fsnode = sos_fs_nsc    972       struct sos_fs_node * fsnode = sos_fs_nscache_get_fs_node(src_of->direntry);
982       fsnode->close_opened_file(fsnode, *resul    973       fsnode->close_opened_file(fsnode, *result_of);
983       return retval;                              974       return retval;
984     }                                             975     }
985                                                   976 
986   return retval;                                  977   return retval;
987 }                                                 978 }
988                                                   979 
989                                                   980 
990 sos_ret_t sos_fs_open(const struct sos_process    981 sos_ret_t sos_fs_open(const struct sos_process *owner,
991                       const char *_path,          982                       const char *_path,
992                       sos_size_t _pathlen,        983                       sos_size_t _pathlen,
993                       sos_ui32_t open_flags,      984                       sos_ui32_t open_flags,
994                       sos_ui32_t creat_access_    985                       sos_ui32_t creat_access_rights,
995                       struct sos_fs_opened_fil    986                       struct sos_fs_opened_file ** of)
996 {                                                 987 {
997   sos_ret_t retval;                               988   sos_ret_t retval;
998   struct sos_fs_nscache_node *nsnode;             989   struct sos_fs_nscache_node *nsnode;
999   struct sos_fs_node * fsnode;                    990   struct sos_fs_node * fsnode;
1000   struct sos_fs_pathname path;                   991   struct sos_fs_pathname path;
1001                                                  992 
1002   /* O_DIR | O_CREAT combination not supporte    993   /* O_DIR | O_CREAT combination not supported */
1003   if ( (open_flags & SOS_FS_OPEN_DIRECTORY)      994   if ( (open_flags & SOS_FS_OPEN_DIRECTORY)
1004        && ( (open_flags & (SOS_FS_OPEN_CREAT     995        && ( (open_flags & (SOS_FS_OPEN_CREAT
1005                            | SOS_FS_OPEN_TRUN    996                            | SOS_FS_OPEN_TRUNC)) ) )
1006     return -SOS_EINVAL;                          997     return -SOS_EINVAL;
1007                                                  998 
1008   if (_pathlen <= 0)                             999   if (_pathlen <= 0)
1009     return -SOS_ENOENT;                          1000     return -SOS_ENOENT;
1010                                                  1001 
1011   path.contents = _path;                         1002   path.contents = _path;
1012   path.length   = _pathlen;                      1003   path.length   = _pathlen;
1013                                                  1004 
1014   if (path.contents[0] == '/')                   1005   if (path.contents[0] == '/')
1015     nsnode = sos_process_get_root(owner)->dir    1006     nsnode = sos_process_get_root(owner)->direntry;
1016   else                                           1007   else
1017     nsnode = sos_process_get_cwd(owner)->dire    1008     nsnode = sos_process_get_cwd(owner)->direntry;
1018                                                  1009 
1019   retval = fs_lookup_node(& path,                1010   retval = fs_lookup_node(& path,
1020                           ! (open_flags & SOS    1011                           ! (open_flags & SOS_FS_OPEN_NOFOLLOW),
1021                           sos_process_get_roo    1012                           sos_process_get_root(owner)->direntry,
1022                           nsnode,                1013                           nsnode,
1023                           & nsnode,              1014                           & nsnode,
1024                           & path,                1015                           & path,
1025                           0);                    1016                           0);
1026   if (SOS_OK != retval)                          1017   if (SOS_OK != retval)
1027     return retval;                               1018     return retval;
1028                                                  1019 
1029   if (path.length <= 0)                          1020   if (path.length <= 0)
1030     {                                            1021     {
1031       /* Found the exact match ! */              1022       /* Found the exact match ! */
1032                                                  1023 
1033       /* Handle O_EXCL flag */                   1024       /* Handle O_EXCL flag */
1034       if (open_flags & SOS_FS_OPEN_EXCL)         1025       if (open_flags & SOS_FS_OPEN_EXCL)
1035         {                                        1026         {
1036           sos_fs_nscache_unref_node(nsnode);     1027           sos_fs_nscache_unref_node(nsnode);
1037           return -SOS_EEXIST;                    1028           return -SOS_EEXIST;
1038         }                                        1029         }
1039                                                  1030 
1040       fsnode = sos_fs_nscache_get_fs_node(nsn    1031       fsnode = sos_fs_nscache_get_fs_node(nsnode);
1041       if ((open_flags & SOS_FS_OPEN_DIRECTORY    1032       if ((open_flags & SOS_FS_OPEN_DIRECTORY)
1042           && (fsnode->type != SOS_FS_NODE_DIR    1033           && (fsnode->type != SOS_FS_NODE_DIRECTORY))
1043         {                                        1034         {
1044           sos_fs_nscache_unref_node(nsnode);     1035           sos_fs_nscache_unref_node(nsnode);
1045           return -SOS_ENOTDIR;                   1036           return -SOS_ENOTDIR;
1046         }                                        1037         }
1047                                                  1038 
1048       /* Handle O_TRUNC flag */                  1039       /* Handle O_TRUNC flag */
1049       if ((open_flags & SOS_FS_OPEN_TRUNC)       1040       if ((open_flags & SOS_FS_OPEN_TRUNC)
1050           && fsnode->ops_file->truncate)         1041           && fsnode->ops_file->truncate)
1051         {                                        1042         {
1052           retval = fsnode->ops_file->truncate    1043           retval = fsnode->ops_file->truncate(fsnode, 0);
1053           if (SOS_OK != retval)                  1044           if (SOS_OK != retval)
1054             {                                    1045             {
1055               sos_fs_nscache_unref_node(nsnod    1046               sos_fs_nscache_unref_node(nsnode);
1056               return retval;                     1047               return retval;
1057             }                                    1048             }
1058         }                                        1049         }
1059     }                                            1050     }
1060   else                                           1051   else
1061     {                                            1052     {
1062       struct sos_fs_nscache_node * parent_nsn    1053       struct sos_fs_nscache_node * parent_nsnode = nsnode;
1063                                                  1054 
1064       /* Did not find an exact match. Should     1055       /* Did not find an exact match. Should create the node ! */
1065       if (! (open_flags & SOS_FS_OPEN_CREAT))    1056       if (! (open_flags & SOS_FS_OPEN_CREAT))
1066         {                                        1057         {
1067           sos_fs_nscache_unref_node(parent_ns    1058           sos_fs_nscache_unref_node(parent_nsnode);
1068           return -SOS_ENOENT;                    1059           return -SOS_ENOENT;
1069         }                                        1060         }
1070                                                  1061 
1071       /* Create a new entry in the file syste    1062       /* Create a new entry in the file system */
1072       retval = fs_create_child_node(parent_ns    1063       retval = fs_create_child_node(parent_nsnode,
1073                                     & path,      1064                                     & path,
1074                                     SOS_FS_NO    1065                                     SOS_FS_NODE_REGULAR_FILE,
1075                                     open_flag    1066                                     open_flags,
1076                                     owner,       1067                                     owner,
1077                                     creat_acc    1068                                     creat_access_rights,
1078                                     & nsnode)    1069                                     & nsnode);
1079       sos_fs_nscache_unref_node(parent_nsnode    1070       sos_fs_nscache_unref_node(parent_nsnode);
1080       if (SOS_OK != retval)                      1071       if (SOS_OK != retval)
1081         {                                        1072         {
1082           return retval;                         1073           return retval;
1083         }                                        1074         }
1084                                                  1075 
1085       fsnode = sos_fs_nscache_get_fs_node(nsn    1076       fsnode = sos_fs_nscache_get_fs_node(nsnode);
1086     }                                            1077     }
1087                                                  1078 
1088   /* Recompute access rights */                  1079   /* Recompute access rights */
1089   open_flags &= ~(SOS_FS_OPEN_CREAT              1080   open_flags &= ~(SOS_FS_OPEN_CREAT
1090                   | SOS_FS_OPEN_EXCL             1081                   | SOS_FS_OPEN_EXCL
1091                   | SOS_FS_OPEN_NOFOLLOW         1082                   | SOS_FS_OPEN_NOFOLLOW
1092                   | SOS_FS_OPEN_DIRECTORY);      1083                   | SOS_FS_OPEN_DIRECTORY);
1093   if (! (fsnode->access_rights & SOS_FS_WRITA    1084   if (! (fsnode->access_rights & SOS_FS_WRITABLE))
1094     open_flags &= ~(SOS_FS_OPEN_WRITE);          1085     open_flags &= ~(SOS_FS_OPEN_WRITE);
1095   if (! (fsnode->access_rights & SOS_FS_READA    1086   if (! (fsnode->access_rights & SOS_FS_READABLE))
1096     open_flags &= ~(SOS_FS_OPEN_READ);           1087     open_flags &= ~(SOS_FS_OPEN_READ);
1097   if (fsnode->fs->flags & SOS_FS_MOUNT_READON    1088   if (fsnode->fs->flags & SOS_FS_MOUNT_READONLY)
1098     open_flags &= ~(SOS_FS_OPEN_READ);           1089     open_flags &= ~(SOS_FS_OPEN_READ);
1099                                                  1090 
1100   /*                                             1091   /*
1101    * Ok, open it right now !                     1092    * Ok, open it right now !
1102    */                                            1093    */
1103   retval = sos_fs_new_opened_file(owner, nsno    1094   retval = sos_fs_new_opened_file(owner, nsnode, open_flags, of);
1104                                                  1095 
1105   sos_fs_nscache_unref_node(nsnode);             1096   sos_fs_nscache_unref_node(nsnode);
1106   return retval;                                 1097   return retval;
1107 }                                                1098 }
1108                                                  1099 
1109                                                  1100 
1110 sos_ret_t sos_fs_close(struct sos_fs_opened_f    1101 sos_ret_t sos_fs_close(struct sos_fs_opened_file * of)
1111 {                                                1102 {
1112   return sos_fs_unref_opened_file(of);           1103   return sos_fs_unref_opened_file(of);
1113 }                                                1104 }
1114                                                  1105 
1115                                                  1106 
1116 sos_ret_t sos_fs_mark_dirty(struct sos_fs_ope    1107 sos_ret_t sos_fs_mark_dirty(struct sos_fs_opened_file * of)
1117 {                                                1108 {
1118   struct sos_fs_node * fsnode = sos_fs_nscach    1109   struct sos_fs_node * fsnode = sos_fs_nscache_get_fs_node(of->direntry);
1119                                                  1110 
1120   /* This function should never get called if    1111   /* This function should never get called if the FS is read-only */
1121   SOS_ASSERT_FATAL(! (fsnode->fs->flags & SOS    1112   SOS_ASSERT_FATAL(! (fsnode->fs->flags & SOS_FS_MOUNT_READONLY));
1122                                                  1113 
1123   return mark_dirty_fsnode(fsnode, of->open_f    1114   return mark_dirty_fsnode(fsnode, of->open_flags & SOS_FS_OPEN_SYNC);
1124 }                                                1115 }
1125                                                  1116 
1126                                                  1117 
1127 sos_ret_t sos_fs_read(struct sos_fs_opened_fi    1118 sos_ret_t sos_fs_read(struct sos_fs_opened_file * of,
1128                       sos_uaddr_t dest_buf,      1119                       sos_uaddr_t dest_buf,
1129                       sos_size_t * /* in/ou *    1120                       sos_size_t * /* in/ou */len)
1130 {                                                1121 {
1131   if (! (of->open_flags & SOS_FS_OPEN_READ))     1122   if (! (of->open_flags & SOS_FS_OPEN_READ))
1132     return -SOS_EPERM;                           1123     return -SOS_EPERM;
1133                                                  1124 
1134   if (! of->ops_file->read)                      1125   if (! of->ops_file->read)
1135     return -SOS_ENOSYS;                          1126     return -SOS_ENOSYS;
1136                                                  1127 
1137   return of->ops_file->read(of, dest_buf, len    1128   return of->ops_file->read(of, dest_buf, len);
1138 }                                                1129 }
1139                                                  1130 
1140                                                  1131 
1141 sos_ret_t sos_fs_write(struct sos_fs_opened_f    1132 sos_ret_t sos_fs_write(struct sos_fs_opened_file * of,
1142                        sos_uaddr_t src_buf,      1133                        sos_uaddr_t src_buf,
1143                        sos_size_t * /* in/out    1134                        sos_size_t * /* in/out */len)
1144 {                                                1135 {
1145  if (! (of->open_flags & SOS_FS_OPEN_WRITE))     1136  if (! (of->open_flags & SOS_FS_OPEN_WRITE))
1146    return -SOS_EPERM;                            1137    return -SOS_EPERM;
1147                                                  1138 
1148  if (! of->ops_file->write)                      1139  if (! of->ops_file->write)
1149    return -SOS_ENOSYS;                           1140    return -SOS_ENOSYS;
1150                                                  1141 
1151   return of->ops_file->write(of, src_buf, len    1142   return of->ops_file->write(of, src_buf, len);
1152 }                                                1143 }
1153                                                  1144 
1154                                                  1145 
1155 sos_ret_t sos_fs_seek(struct sos_fs_opened_fi    1146 sos_ret_t sos_fs_seek(struct sos_fs_opened_file *of,
1156                       sos_lsoffset_t offset,     1147                       sos_lsoffset_t offset,
1157                       sos_seek_whence_t whenc    1148                       sos_seek_whence_t whence,
1158                       sos_lsoffset_t * result    1149                       sos_lsoffset_t * result_position)
1159 {                                                1150 {
1160   if (! of->ops_file->seek)                      1151   if (! of->ops_file->seek)
1161     return -SOS_ENOSYS;                          1152     return -SOS_ENOSYS;
1162                                                  1153 
1163   return of->ops_file->seek(of, offset, whenc    1154   return of->ops_file->seek(of, offset, whence, result_position);
1164 }                                                1155 }
1165                                                  1156 
1166                                                  1157 
1167 sos_ret_t sos_fs_ftruncate(struct sos_fs_open    1158 sos_ret_t sos_fs_ftruncate(struct sos_fs_opened_file *of,
1168                            sos_lsoffset_t len    1159                            sos_lsoffset_t length)
1169 {                                                1160 {
1170   sos_ret_t retval;                              1161   sos_ret_t retval;
1171   struct sos_fs_node * fsnode = sos_fs_nscach    1162   struct sos_fs_node * fsnode = sos_fs_nscache_get_fs_node(of->direntry);
1172                                                  1163 
1173   if (! (of->open_flags & SOS_FS_OPEN_WRITE))    1164   if (! (of->open_flags & SOS_FS_OPEN_WRITE))
1174     return -SOS_EPERM;                           1165     return -SOS_EPERM;
1175                                                  1166 
1176   if (! fsnode->ops_file->truncate)              1167   if (! fsnode->ops_file->truncate)
1177     return -SOS_ENOSYS;                          1168     return -SOS_ENOSYS;
1178                                                  1169 
1179   retval = fsnode->ops_file->truncate(fsnode,    1170   retval = fsnode->ops_file->truncate(fsnode, length);
1180   if (SOS_OK == retval)                          1171   if (SOS_OK == retval)
1181     mark_dirty_fsnode(fsnode, FALSE);            1172     mark_dirty_fsnode(fsnode, FALSE);
1182                                                  1173 
1183   return retval;                                 1174   return retval;
1184 }                                                1175 }
1185                                                  1176 
1186                                                  1177 
1187 sos_ret_t sos_fs_mmap(struct sos_fs_opened_fi    1178 sos_ret_t sos_fs_mmap(struct sos_fs_opened_file *of,
1188                       sos_uaddr_t *uaddr, sos    1179                       sos_uaddr_t *uaddr, sos_size_t size,
1189                       sos_ui32_t access_right    1180                       sos_ui32_t access_rights,
1190                       sos_ui32_t flags,          1181                       sos_ui32_t flags,
1191                       sos_luoffset_t offset)     1182                       sos_luoffset_t offset)
1192 {                                                1183 {
1193   sos_ui32_t required_access = 0;                1184   sos_ui32_t required_access = 0;
1194   struct sos_fs_node * fsnode = sos_fs_nscach    1185   struct sos_fs_node * fsnode = sos_fs_nscache_get_fs_node(of->direntry);
1195                                                  1186 
1196   if (! of->ops_file->mmap)                      1187   if (! of->ops_file->mmap)
1197     return -SOS_ENOSYS;                          1188     return -SOS_ENOSYS;
1198                                                  1189 
1199   /* Translate VM requested rights into FS eq    1190   /* Translate VM requested rights into FS equivalent */
1200   if (access_rights & SOS_VM_MAP_PROT_READ)      1191   if (access_rights & SOS_VM_MAP_PROT_READ)
1201     required_access |= SOS_FS_OPEN_READ;         1192     required_access |= SOS_FS_OPEN_READ;
1202   if ( (access_rights & SOS_VM_MAP_PROT_WRITE    1193   if ( (access_rights & SOS_VM_MAP_PROT_WRITE) && (flags & SOS_VR_MAP_SHARED) )
1203     required_access |= SOS_FS_OPEN_WRITE;        1194     required_access |= SOS_FS_OPEN_WRITE;
1204   if (access_rights & SOS_VM_MAP_PROT_EXEC)      1195   if (access_rights & SOS_VM_MAP_PROT_EXEC)
1205     required_access |= SOS_FS_OPEN_READ;         1196     required_access |= SOS_FS_OPEN_READ;
1206                                                  1197 
1207   /* Make sure that the opened file allowed t    1198   /* Make sure that the opened file allowed this access */
1208   if ((of->open_flags & required_access) != r    1199   if ((of->open_flags & required_access) != required_access)
1209     return -SOS_EPERM;                           1200     return -SOS_EPERM;
1210                                                  1201 
1211   if ( (access_rights & SOS_VM_MAP_PROT_EXEC)    1202   if ( (access_rights & SOS_VM_MAP_PROT_EXEC)
1212        && (fsnode->fs->flags & SOS_FS_MOUNT_N    1203        && (fsnode->fs->flags & SOS_FS_MOUNT_NOEXEC) )
1213     return -SOS_EPERM;                           1204     return -SOS_EPERM;
1214                                                  1205 
1215   return of->ops_file->mmap(of, uaddr, size,     1206   return of->ops_file->mmap(of, uaddr, size, access_rights, flags, offset);  
1216 }                                                1207 }
1217                                                  1208 
1218                                                  1209 
1219 sos_ret_t sos_fs_fcntl(struct sos_fs_opened_f    1210 sos_ret_t sos_fs_fcntl(struct sos_fs_opened_file *of,
1220                        int req_id,               1211                        int req_id,
1221                        sos_ui32_t req_arg /*     1212                        sos_ui32_t req_arg /* Usually: sos_uaddr_t */)
1222 {                                                1213 {
1223   if (! of->ops_file->fcntl)                     1214   if (! of->ops_file->fcntl)
1224     return -SOS_ENOSYS;                          1215     return -SOS_ENOSYS;
1225                                                  1216 
1226   return of->ops_file->fcntl(of, req_id, req_    1217   return of->ops_file->fcntl(of, req_id, req_arg);
1227 }                                                1218 }
1228                                                  1219 
1229                                                  1220 
1230 sos_ret_t sos_fs_ioctl(struct sos_fs_opened_f    1221 sos_ret_t sos_fs_ioctl(struct sos_fs_opened_file *of,
1231                        int req_id,               1222                        int req_id,
1232                        sos_ui32_t req_arg /*     1223                        sos_ui32_t req_arg /* Usually: sos_uaddr_t */)
1233 {                                                1224 {
1234   struct sos_fs_node * fsnode = sos_fs_nscach    1225   struct sos_fs_node * fsnode = sos_fs_nscache_get_fs_node(of->direntry);
1235                                                  1226 
1236   if (fsnode->type == SOS_FS_NODE_DEVICE_CHAR    1227   if (fsnode->type == SOS_FS_NODE_DEVICE_CHAR)
1237     {                                            1228     {
1238       if (! of->ops_chardev->ioctl)              1229       if (! of->ops_chardev->ioctl)
1239         return -SOS_ENOSYS;                      1230         return -SOS_ENOSYS;
1240                                                  1231 
1241       return of->ops_chardev->ioctl(of, req_i    1232       return of->ops_chardev->ioctl(of, req_id, req_arg);
1242     }                                            1233     }
1243   else if (fsnode->type == SOS_FS_NODE_DEVICE << 
1244     {                                         << 
1245       if (! of->ops_blockdev->ioctl)          << 
1246         return -SOS_ENOSYS;                   << 
1247                                               << 
1248       return of->ops_blockdev->ioctl(of, req_ << 
1249     }                                         << 
1250                                                  1234   
1251   return -SOS_ENOSYS;                            1235   return -SOS_ENOSYS;
1252 }                                                1236 }
1253                                                  1237 
1254                                                  1238 
1255 sos_ret_t sos_fs_readdir(struct sos_fs_opened    1239 sos_ret_t sos_fs_readdir(struct sos_fs_opened_file * of,
1256                          struct sos_fs_dirent    1240                          struct sos_fs_dirent * result)
1257 {                                                1241 {
1258   struct sos_fs_node * fsnode = sos_fs_nscach    1242   struct sos_fs_node * fsnode = sos_fs_nscache_get_fs_node(of->direntry);
1259                                                  1243 
1260   if (fsnode->type != SOS_FS_NODE_DIRECTORY)     1244   if (fsnode->type != SOS_FS_NODE_DIRECTORY)
1261     return -SOS_ENOTDIR;                         1245     return -SOS_ENOTDIR;
1262                                                  1246 
1263   return of->ops_dir->readdir(of, result);       1247   return of->ops_dir->readdir(of, result);
1264 }                                                1248 }
1265                                                  1249 
1266                                                  1250 
1267 sos_ret_t sos_fs_creat(const struct sos_proce    1251 sos_ret_t sos_fs_creat(const struct sos_process * creator,
1268                        const char * _path,       1252                        const char * _path,
1269                        sos_size_t _pathlen,      1253                        sos_size_t _pathlen,
1270                        sos_ui32_t access_righ    1254                        sos_ui32_t access_rights)
1271 {                                                1255 {
1272   struct sos_fs_pathname path;                   1256   struct sos_fs_pathname path;
1273                                                  1257 
1274   path.contents = _path;                         1258   path.contents = _path;
1275   path.length   = _pathlen;                      1259   path.length   = _pathlen;
1276                                                  1260 
1277   return fs_create_node(& path, creator, acce    1261   return fs_create_node(& path, creator, access_rights,
1278                         SOS_FS_NODE_REGULAR_F    1262                         SOS_FS_NODE_REGULAR_FILE, NULL);
1279 }                                                1263 }
1280                                                  1264 
1281                                                  1265 
1282 sos_ret_t sos_fs_link(const struct sos_proces    1266 sos_ret_t sos_fs_link(const struct sos_process * creator,
1283                       const char * _old_path,    1267                       const char * _old_path,
1284                       sos_size_t _old_pathlen    1268                       sos_size_t _old_pathlen,
1285                       const char * _new_path,    1269                       const char * _new_path,
1286                       sos_size_t _new_pathlen    1270                       sos_size_t _new_pathlen)
1287 {                                                1271 {
1288   sos_ret_t retval;                              1272   sos_ret_t retval;
1289   struct sos_fs_nscache_node *old_nsnode, *de    1273   struct sos_fs_nscache_node *old_nsnode, *dest_parent_nsnode, *new_nsnode;
1290   struct sos_fs_node * fsnode;                   1274   struct sos_fs_node * fsnode;
1291   struct sos_fs_pathname old_path, new_path;     1275   struct sos_fs_pathname old_path, new_path;
1292                                                  1276 
1293   if (_old_pathlen <= 0)                         1277   if (_old_pathlen <= 0)
1294     return -SOS_ENOENT;                          1278     return -SOS_ENOENT;
1295   if (_new_pathlen <= 0)                         1279   if (_new_pathlen <= 0)
1296     return -SOS_ENOENT;                          1280     return -SOS_ENOENT;
1297                                                  1281 
1298   /* Resolve target FS node using "old_path"     1282   /* Resolve target FS node using "old_path" */
1299   old_path.contents = _old_path;                 1283   old_path.contents = _old_path;
1300   old_path.length   = _old_pathlen;              1284   old_path.length   = _old_pathlen;
1301                                                  1285 
1302   if (old_path.contents[0] == '/')               1286   if (old_path.contents[0] == '/')
1303     old_nsnode = sos_process_get_root(creator    1287     old_nsnode = sos_process_get_root(creator)->direntry;
1304   else                                           1288   else
1305     old_nsnode = sos_process_get_cwd(creator)    1289     old_nsnode = sos_process_get_cwd(creator)->direntry;
1306                                                  1290 
1307   retval = fs_lookup_node(& old_path,            1291   retval = fs_lookup_node(& old_path,
1308                           FALSE /* don't foll    1292                           FALSE /* don't follow symlink */,
1309                           sos_process_get_roo    1293                           sos_process_get_root(creator)->direntry,
1310                           old_nsnode,            1294                           old_nsnode,
1311                           & old_nsnode,          1295                           & old_nsnode,
1312                           & old_path,            1296                           & old_path,
1313                           0);                    1297                           0);
1314   if (SOS_OK != retval)                          1298   if (SOS_OK != retval)
1315     return retval;                               1299     return retval;
1316                                                  1300 
1317   if (old_path.length > 0)                       1301   if (old_path.length > 0)
1318     {                                            1302     {
1319       /* Could not resolve full path ! */        1303       /* Could not resolve full path ! */
1320       sos_fs_nscache_unref_node(old_nsnode);     1304       sos_fs_nscache_unref_node(old_nsnode);
1321       return -SOS_ENOENT;                        1305       return -SOS_ENOENT;
1322     }                                            1306     }
1323                                                  1307 
1324   fsnode = sos_fs_nscache_get_fs_node(old_nsn    1308   fsnode = sos_fs_nscache_get_fs_node(old_nsnode);
1325                                                  1309 
1326   /* Not allowed to link directories ! */        1310   /* Not allowed to link directories ! */
1327   if (fsnode->type == SOS_FS_NODE_DIRECTORY)     1311   if (fsnode->type == SOS_FS_NODE_DIRECTORY)
1328     {                                            1312     {
1329       sos_fs_nscache_unref_node(old_nsnode);     1313       sos_fs_nscache_unref_node(old_nsnode);
1330       return -SOS_ENOENT;                        1314       return -SOS_ENOENT;
1331     }                                            1315     }
1332                                                  1316 
1333   /* Resolve destination path */                 1317   /* Resolve destination path */
1334   new_path.contents = _new_path;                 1318   new_path.contents = _new_path;
1335   new_path.length   = _new_pathlen;              1319   new_path.length   = _new_pathlen;
1336                                                  1320 
1337   if (new_path.contents[0] == '/')               1321   if (new_path.contents[0] == '/')
1338     dest_parent_nsnode = sos_process_get_root    1322     dest_parent_nsnode = sos_process_get_root(creator)->direntry;
1339   else                                           1323   else
1340     dest_parent_nsnode = sos_process_get_cwd(    1324     dest_parent_nsnode = sos_process_get_cwd(creator)->direntry;
1341                                                  1325 
1342   retval = fs_lookup_node(& new_path,            1326   retval = fs_lookup_node(& new_path,
1343                           TRUE /* Follow syml    1327                           TRUE /* Follow symlink */,
1344                           sos_process_get_roo    1328                           sos_process_get_root(creator)->direntry,
1345                           dest_parent_nsnode,    1329                           dest_parent_nsnode,
1346                           & dest_parent_nsnod    1330                           & dest_parent_nsnode,
1347                           & new_path,            1331                           & new_path,
1348                           0);                    1332                           0);
1349   if (SOS_OK != retval)                          1333   if (SOS_OK != retval)
1350     {                                            1334     {
1351       sos_fs_nscache_unref_node(old_nsnode);     1335       sos_fs_nscache_unref_node(old_nsnode);
1352       return retval;                             1336       return retval;
1353     }                                            1337     }
1354                                                  1338 
1355   if (new_path.length == 0)                      1339   if (new_path.length == 0)
1356     {                                            1340     {
1357       /* Found the exact match ! Not allowed     1341       /* Found the exact match ! Not allowed to overwrite it ! */
1358       sos_fs_nscache_unref_node(dest_parent_n    1342       sos_fs_nscache_unref_node(dest_parent_nsnode);
1359       sos_fs_nscache_unref_node(old_nsnode);     1343       sos_fs_nscache_unref_node(old_nsnode);
1360       return -SOS_EEXIST;                        1344       return -SOS_EEXIST;
1361     }                                            1345     }
1362                                                  1346 
1363   /* Create a new entry in the file system */    1347   /* Create a new entry in the file system */
1364   retval = fs_register_child_node(creator, de    1348   retval = fs_register_child_node(creator, dest_parent_nsnode, & new_path,
1365                                   fsnode, 0,     1349                                   fsnode, 0,
1366                                   & new_nsnod    1350                                   & new_nsnode);
1367                                                  1351 
1368   sos_fs_nscache_unref_node(dest_parent_nsnod    1352   sos_fs_nscache_unref_node(dest_parent_nsnode);
1369   sos_fs_nscache_unref_node(old_nsnode);         1353   sos_fs_nscache_unref_node(old_nsnode);
1370   sos_fs_nscache_unref_node(new_nsnode);         1354   sos_fs_nscache_unref_node(new_nsnode);
1371   return retval;                                 1355   return retval;
1372 }                                                1356 }
1373                                                  1357 
1374                                                  1358 
1375 sos_ret_t sos_fs_rename(const struct sos_proc    1359 sos_ret_t sos_fs_rename(const struct sos_process * actor,
1376                         const char * _old_pat    1360                         const char * _old_path,
1377                         sos_size_t _old_pathl    1361                         sos_size_t _old_pathlen,
1378                         const char * _new_pat    1362                         const char * _new_path,
1379                         sos_size_t _new_pathl    1363                         sos_size_t _new_pathlen)
1380 {                                                1364 {
1381   sos_ret_t retval;                              1365   sos_ret_t retval;
1382   struct sos_fs_nscache_node *old_nsnode, *ol    1366   struct sos_fs_nscache_node *old_nsnode, *old_parent_nsnode,
1383     *dest_parent_nsnode, *replaced_nsnode;       1367     *dest_parent_nsnode, *replaced_nsnode;
1384   struct sos_fs_pathname old_name, replaced_n    1368   struct sos_fs_pathname old_name, replaced_name;
1385   struct sos_fs_pathname old_path, new_path;     1369   struct sos_fs_pathname old_path, new_path;
1386                                                  1370 
1387   old_nsnode = old_parent_nsnode = dest_paren    1371   old_nsnode = old_parent_nsnode = dest_parent_nsnode = replaced_nsnode = NULL;
1388                                                  1372 
1389   if (_old_pathlen <= 0)                         1373   if (_old_pathlen <= 0)
1390     return -SOS_ENOENT;                          1374     return -SOS_ENOENT;
1391   if (_new_pathlen <= 0)                         1375   if (_new_pathlen <= 0)
1392     return -SOS_ENOENT;                          1376     return -SOS_ENOENT;
1393                                                  1377 
1394   /* Resolve target FS node using "old_path"     1378   /* Resolve target FS node using "old_path" */
1395   old_path.contents = _old_path;                 1379   old_path.contents = _old_path;
1396   old_path.length   = _old_pathlen;              1380   old_path.length   = _old_pathlen;
1397                                                  1381 
1398   if (old_path.contents[0] == '/')               1382   if (old_path.contents[0] == '/')
1399     old_nsnode = sos_process_get_root(actor)-    1383     old_nsnode = sos_process_get_root(actor)->direntry;
1400   else                                           1384   else
1401     old_nsnode = sos_process_get_cwd(actor)->    1385     old_nsnode = sos_process_get_cwd(actor)->direntry;
1402                                                  1386 
1403   retval = fs_lookup_node(& old_path,            1387   retval = fs_lookup_node(& old_path,
1404                           FALSE /* don't foll    1388                           FALSE /* don't follow symlink */,
1405                           sos_process_get_roo    1389                           sos_process_get_root(actor)->direntry,
1406                           old_nsnode,            1390                           old_nsnode,
1407                           & old_nsnode,          1391                           & old_nsnode,
1408                           & old_path,            1392                           & old_path,
1409                           0);                    1393                           0);
1410   if (SOS_OK != retval)                          1394   if (SOS_OK != retval)
1411     return retval;                               1395     return retval;
1412                                                  1396 
1413   if (old_path.length > 0)                       1397   if (old_path.length > 0)
1414     {                                            1398     {
1415       /* Could not resolve full path ! */        1399       /* Could not resolve full path ! */
1416       sos_fs_nscache_unref_node(old_nsnode);     1400       sos_fs_nscache_unref_node(old_nsnode);
1417       return -SOS_ENOENT;                        1401       return -SOS_ENOENT;
1418     }                                            1402     }
1419                                                  1403 
1420   /* Not allowed to rename mountpoints ! */      1404   /* Not allowed to rename mountpoints ! */
1421   if (sos_fs_nscache_is_mountnode(old_nsnode)    1405   if (sos_fs_nscache_is_mountnode(old_nsnode))
1422     {                                            1406     {
1423       sos_fs_nscache_unref_node(old_nsnode);     1407       sos_fs_nscache_unref_node(old_nsnode);
1424       return -SOS_ENOENT;                        1408       return -SOS_ENOENT;
1425     }                                            1409     }
1426                                                  1410 
1427   /* Keep a reference on this node's parent,     1411   /* Keep a reference on this node's parent, in case we must undo the
1428      rename */                                   1412      rename */
1429   retval = sos_fs_nscache_get_parent(old_nsno    1413   retval = sos_fs_nscache_get_parent(old_nsnode, & old_parent_nsnode);
1430   if (SOS_OK != retval)                          1414   if (SOS_OK != retval)
1431     {                                            1415     {
1432       sos_fs_nscache_unref_node(old_nsnode);     1416       sos_fs_nscache_unref_node(old_nsnode);
1433       return retval;                             1417       return retval;
1434     }                                            1418     }
1435   sos_fs_nscache_ref_node(old_parent_nsnode);    1419   sos_fs_nscache_ref_node(old_parent_nsnode);
1436                                                  1420 
1437   /* Resolve destination path */                 1421   /* Resolve destination path */
1438   replaced_nsnode   = NULL;                      1422   replaced_nsnode   = NULL;
1439   new_path.contents = _new_path;                 1423   new_path.contents = _new_path;
1440   new_path.length   = _new_pathlen;              1424   new_path.length   = _new_pathlen;
1441                                                  1425 
1442   if (new_path.contents[0] == '/')               1426   if (new_path.contents[0] == '/')
1443     dest_parent_nsnode = sos_process_get_root    1427     dest_parent_nsnode = sos_process_get_root(actor)->direntry;
1444   else                                           1428   else
1445     dest_parent_nsnode = sos_process_get_cwd(    1429     dest_parent_nsnode = sos_process_get_cwd(actor)->direntry;
1446                                                  1430 
1447   retval = fs_lookup_node(& new_path,            1431   retval = fs_lookup_node(& new_path,
1448                           TRUE /* Follow syml    1432                           TRUE /* Follow symlink */,
1449                           sos_process_get_roo    1433                           sos_process_get_root(actor)->direntry,
1450                           dest_parent_nsnode,    1434                           dest_parent_nsnode,
1451                           & dest_parent_nsnod    1435                           & dest_parent_nsnode,
1452                           & new_path,            1436                           & new_path,
1453                           0);                    1437                           0);
1454   if (SOS_OK != retval)                          1438   if (SOS_OK != retval)
1455     {                                            1439     {
1456       goto undo_rename;                          1440       goto undo_rename;
1457     }                                            1441     }
1458                                                  1442 
1459   /* Nothing to do ? */                          1443   /* Nothing to do ? */
1460   if (old_nsnode == dest_parent_nsnode)          1444   if (old_nsnode == dest_parent_nsnode)
1461     {                                            1445     {
1462       sos_fs_nscache_unref_node(old_nsnode);     1446       sos_fs_nscache_unref_node(old_nsnode);
1463       sos_fs_nscache_unref_node(old_parent_ns    1447       sos_fs_nscache_unref_node(old_parent_nsnode);
1464       sos_fs_nscache_unref_node(dest_parent_n    1448       sos_fs_nscache_unref_node(dest_parent_nsnode);
1465       return SOS_OK;                             1449       return SOS_OK;
1466     }                                            1450     }
1467                                                  1451 
1468   /* Remove old nsnode from file ns cache */     1452   /* Remove old nsnode from file ns cache */
1469   sos_fs_nscache_get_name(old_nsnode, & old_n    1453   sos_fs_nscache_get_name(old_nsnode, & old_name);
1470   retval = fs_remove_node(actor, old_nsnode);    1454   retval = fs_remove_node(actor, old_nsnode);
1471   if (SOS_OK != retval)                          1455   if (SOS_OK != retval)
1472     {                                            1456     {
1473       sos_fs_nscache_unref_node(old_nsnode);     1457       sos_fs_nscache_unref_node(old_nsnode);
1474       sos_fs_nscache_unref_node(old_parent_ns    1458       sos_fs_nscache_unref_node(old_parent_nsnode);
1475       sos_fs_nscache_unref_node(dest_parent_n    1459       sos_fs_nscache_unref_node(dest_parent_nsnode);
1476       return -SOS_ENOENT;                        1460       return -SOS_ENOENT;
1477     }                                            1461     }
1478                                                  1462 
1479   if (new_path.length == 0)                      1463   if (new_path.length == 0)
1480     {                                            1464     {
1481       /* Found the exact match ! We disconnec    1465       /* Found the exact match ! We disconnect it from the namespace,
1482          but keep it aside */                    1466          but keep it aside */
1483                                                  1467 
1484       /* Not allowed to replace directories *    1468       /* Not allowed to replace directories */
1485       if (sos_fs_nscache_get_fs_node(dest_par    1469       if (sos_fs_nscache_get_fs_node(dest_parent_nsnode)->type
1486           == SOS_FS_NODE_DIRECTORY)              1470           == SOS_FS_NODE_DIRECTORY)
1487         {                                        1471         {
1488           retval = -SOS_EBUSY;                   1472           retval = -SOS_EBUSY;
1489           goto undo_rename;                      1473           goto undo_rename;
1490         }                                        1474         }
1491                                                  1475 
1492       replaced_nsnode = dest_parent_nsnode;      1476       replaced_nsnode = dest_parent_nsnode;
1493       dest_parent_nsnode = NULL;                 1477       dest_parent_nsnode = NULL;
1494                                                  1478 
1495       /* Retrieve the parent of the node to r    1479       /* Retrieve the parent of the node to replace */
1496       retval = sos_fs_nscache_get_parent(repl    1480       retval = sos_fs_nscache_get_parent(replaced_nsnode,
1497                                          & de    1481                                          & dest_parent_nsnode);
1498       if (SOS_OK != retval)                      1482       if (SOS_OK != retval)
1499         {                                        1483         {
1500           dest_parent_nsnode = replaced_nsnod    1484           dest_parent_nsnode = replaced_nsnode;
1501           goto undo_rename;                      1485           goto undo_rename;
1502         }                                        1486         }
1503                                                  1487 
1504       sos_fs_nscache_ref_node(dest_parent_nsn    1488       sos_fs_nscache_ref_node(dest_parent_nsnode);
1505                                                  1489 
1506       /* Disconnect this node from its parent    1490       /* Disconnect this node from its parent */
1507       sos_fs_nscache_get_name(replaced_nsnode    1491       sos_fs_nscache_get_name(replaced_nsnode, & replaced_name);
1508       retval = fs_remove_node(actor, replaced    1492       retval = fs_remove_node(actor, replaced_nsnode);
1509       if (SOS_OK != retval)                      1493       if (SOS_OK != retval)
1510         goto undo_rename;                        1494         goto undo_rename;
1511     }                                            1495     }
1512                                                  1496 
1513   /* Create a new entry in the file system */    1497   /* Create a new entry in the file system */
1514   retval = fs_connect_existing_child_node(act    1498   retval = fs_connect_existing_child_node(actor, dest_parent_nsnode,
1515                                           & n    1499                                           & new_path,
1516                                           old    1500                                           old_nsnode);
1517   if (SOS_OK != retval)                          1501   if (SOS_OK != retval)
1518     goto undo_rename;                            1502     goto undo_rename;
1519                                                  1503 
1520   sos_fs_nscache_unref_node(old_nsnode);         1504   sos_fs_nscache_unref_node(old_nsnode);
1521   sos_fs_nscache_unref_node(old_parent_nsnode    1505   sos_fs_nscache_unref_node(old_parent_nsnode);
1522   sos_fs_nscache_unref_node(dest_parent_nsnod    1506   sos_fs_nscache_unref_node(dest_parent_nsnode);
1523   if (NULL != replaced_nsnode)                   1507   if (NULL != replaced_nsnode)
1524     sos_fs_nscache_unref_node(replaced_nsnode    1508     sos_fs_nscache_unref_node(replaced_nsnode);
1525                                                  1509 
1526   return retval;                                 1510   return retval;
1527                                                  1511 
1528  undo_rename:                                    1512  undo_rename:
1529                                                  1513 
1530   /* Handle special case: the node replaced s    1514   /* Handle special case: the node replaced something. In case the
1531      previous operation failed, we try to rei    1515      previous operation failed, we try to reinsert the replaced
1532      node */                                     1516      node */
1533   if (NULL != replaced_nsnode)                   1517   if (NULL != replaced_nsnode)
1534     {                                            1518     {
1535       fs_connect_existing_child_node(actor, d    1519       fs_connect_existing_child_node(actor, dest_parent_nsnode,
1536                                      & replac    1520                                      & replaced_name,
1537                                      replaced    1521                                      replaced_nsnode);
1538       sos_fs_nscache_unref_node(replaced_nsno    1522       sos_fs_nscache_unref_node(replaced_nsnode);
1539     }                                            1523     }
1540                                                  1524 
1541   fs_connect_existing_child_node(actor, old_p    1525   fs_connect_existing_child_node(actor, old_parent_nsnode,
1542                                  & old_name,     1526                                  & old_name,
1543                                  old_nsnode);    1527                                  old_nsnode);
1544   sos_fs_nscache_unref_node(old_nsnode);         1528   sos_fs_nscache_unref_node(old_nsnode);
1545   sos_fs_nscache_unref_node(old_parent_nsnode    1529   sos_fs_nscache_unref_node(old_parent_nsnode);
1546                                                  1530 
1547   if (NULL != dest_parent_nsnode)                1531   if (NULL != dest_parent_nsnode)
1548     sos_fs_nscache_unref_node(dest_parent_nsn    1532     sos_fs_nscache_unref_node(dest_parent_nsnode);
1549                                                  1533 
1550   return retval;                                 1534   return retval;
1551 }                                                1535 }
1552                                                  1536 
1553                                                  1537 
1554 sos_ret_t sos_fs_unlink(const struct sos_proc    1538 sos_ret_t sos_fs_unlink(const struct sos_process * actor,
1555                         const char * _path,      1539                         const char * _path,
1556                         sos_size_t _pathlen)     1540                         sos_size_t _pathlen)
1557 {                                                1541 {
1558   sos_ret_t retval;                              1542   sos_ret_t retval;
1559   struct sos_fs_pathname path;                   1543   struct sos_fs_pathname path;
1560   struct sos_fs_nscache_node * nsnode;           1544   struct sos_fs_nscache_node * nsnode;
1561                                                  1545 
1562   path.contents = _path;                         1546   path.contents = _path;
1563   path.length   = _pathlen;                      1547   path.length   = _pathlen;
1564                                                  1548 
1565   if (path.length <= 0)                          1549   if (path.length <= 0)
1566     return -SOS_ENOENT;                          1550     return -SOS_ENOENT;
1567                                                  1551 
1568   if (path.contents[0] == '/')                   1552   if (path.contents[0] == '/')
1569     nsnode = sos_process_get_root(actor)->dir    1553     nsnode = sos_process_get_root(actor)->direntry;
1570   else                                           1554   else
1571     nsnode = sos_process_get_cwd(actor)->dire    1555     nsnode = sos_process_get_cwd(actor)->direntry;
1572                                                  1556 
1573   retval = fs_lookup_node(& path, FALSE,         1557   retval = fs_lookup_node(& path, FALSE,
1574                           sos_process_get_roo    1558                           sos_process_get_root(actor)->direntry,
1575                           nsnode,                1559                           nsnode,
1576                           & nsnode, & path, 0    1560                           & nsnode, & path, 0);
1577   if (SOS_OK != retval)                          1561   if (SOS_OK != retval)
1578     return retval;                               1562     return retval;
1579                                                  1563 
1580   /* Make sure the whole path has been resolv    1564   /* Make sure the whole path has been resolved */
1581   if (path.length > 0)                           1565   if (path.length > 0)
1582     {                                            1566     {
1583       sos_fs_nscache_unref_node(nsnode);         1567       sos_fs_nscache_unref_node(nsnode);
1584       return -SOS_ENOENT;                        1568       return -SOS_ENOENT;
1585     }                                            1569     }
1586                                                  1570 
1587   if (sos_fs_nscache_get_fs_node(nsnode)->typ    1571   if (sos_fs_nscache_get_fs_node(nsnode)->type == SOS_FS_NODE_DIRECTORY)
1588     retval = -SOS_EISDIR;                        1572     retval = -SOS_EISDIR;
1589   else                                           1573   else
1590     retval = fs_remove_node(actor, nsnode);      1574     retval = fs_remove_node(actor, nsnode);
1591                                                  1575 
1592   sos_fs_nscache_unref_node(nsnode);             1576   sos_fs_nscache_unref_node(nsnode);
1593   return retval;                                 1577   return retval;
1594 }                                                1578 }
1595                                                  1579 
1596                                                  1580 
1597 sos_ret_t sos_fs_symlink(const struct sos_pro    1581 sos_ret_t sos_fs_symlink(const struct sos_process * creator,
1598                          const char * _path,     1582                          const char * _path,
1599                          sos_size_t _pathlen,    1583                          sos_size_t _pathlen,
1600                          sos_uaddr_t symlink_    1584                          sos_uaddr_t symlink_target,
1601                          sos_size_t symlink_t    1585                          sos_size_t symlink_target_len)
1602 {                                                1586 {
1603   sos_ret_t retval;                              1587   sos_ret_t retval;
1604   struct sos_fs_pathname path;                   1588   struct sos_fs_pathname path;
1605   struct sos_fs_node * fsnode;                   1589   struct sos_fs_node * fsnode;
1606   struct sos_fs_nscache_node * symlink;          1590   struct sos_fs_nscache_node * symlink;
1607   struct sos_fs_opened_file * tmp_of;            1591   struct sos_fs_opened_file * tmp_of;
1608   sos_size_t len;                                1592   sos_size_t len;
1609                                                  1593 
1610   path.contents = _path;                         1594   path.contents = _path;
1611   path.length   = _pathlen;                      1595   path.length   = _pathlen;
1612                                                  1596 
1613   retval = fs_create_node(& path, creator, SO    1597   retval = fs_create_node(& path, creator, SOS_FS_S_IRWXALL,
1614                           SOS_FS_NODE_SYMLINK    1598                           SOS_FS_NODE_SYMLINK, & symlink);
1615   if (SOS_OK != retval)                          1599   if (SOS_OK != retval)
1616     return retval;                               1600     return retval;
1617                                                  1601 
1618   /* Artificially open the symlink to change     1602   /* Artificially open the symlink to change its contents */
1619   fsnode = sos_fs_nscache_get_fs_node(symlink    1603   fsnode = sos_fs_nscache_get_fs_node(symlink);
1620   retval = fsnode->new_opened_file(fsnode, cr    1604   retval = fsnode->new_opened_file(fsnode, creator,
1621                                    SOS_FS_OPE    1605                                    SOS_FS_OPEN_WRITE, & tmp_of);
1622   if (SOS_OK != retval)                          1606   if (SOS_OK != retval)
1623     {                                            1607     {
1624       fs_remove_node(creator, symlink);          1608       fs_remove_node(creator, symlink);
1625       sos_fs_nscache_unref_node(symlink);        1609       sos_fs_nscache_unref_node(symlink);
1626       return retval;                             1610       return retval;
1627     }                                            1611     }
1628                                                  1612 
1629   tmp_of->ref_cnt = 1;                           1613   tmp_of->ref_cnt = 1;
1630   retval = sos_fs_nscache_register_opened_fil    1614   retval = sos_fs_nscache_register_opened_file(symlink, tmp_of);
1631   if (SOS_OK != retval)                          1615   if (SOS_OK != retval)
1632     {                                            1616     {
1633       fsnode->close_opened_file(fsnode, tmp_o    1617       fsnode->close_opened_file(fsnode, tmp_of);
1634       fs_remove_node(creator, symlink);          1618       fs_remove_node(creator, symlink);
1635       sos_fs_nscache_unref_node(symlink);        1619       sos_fs_nscache_unref_node(symlink);
1636       return retval;                             1620       return retval;
1637     }                                            1621     }
1638                                                  1622 
1639   len = symlink_target_len;                      1623   len = symlink_target_len;
1640   retval = sos_fs_write(tmp_of, symlink_targe    1624   retval = sos_fs_write(tmp_of, symlink_target, & len);
1641   mark_dirty_fsnode(fsnode, FALSE);              1625   mark_dirty_fsnode(fsnode, FALSE);
1642   fsnode->close_opened_file(fsnode, tmp_of);     1626   fsnode->close_opened_file(fsnode, tmp_of);
1643                                                  1627   
1644   if ((SOS_OK != retval) || (len != symlink_t    1628   if ((SOS_OK != retval) || (len != symlink_target_len))
1645     {                                            1629     {
1646       fs_remove_node(creator, symlink);          1630       fs_remove_node(creator, symlink);
1647       if (SOS_OK == retval)                      1631       if (SOS_OK == retval)
1648         retval = -SOS_ENAMETOOLONG;              1632         retval = -SOS_ENAMETOOLONG;
1649     }                                            1633     }
1650                                                  1634 
1651   sos_fs_nscache_unref_node(symlink);            1635   sos_fs_nscache_unref_node(symlink);
1652   return retval;                                 1636   return retval;
1653 }                                                1637 }
1654                                                  1638 
1655                                                  1639 
1656 sos_ret_t sos_fs_mkdir(const struct sos_proce    1640 sos_ret_t sos_fs_mkdir(const struct sos_process * creator,
1657                        const char * _path,       1641                        const char * _path,
1658                        sos_size_t _pathlen,      1642                        sos_size_t _pathlen,
1659                        sos_ui32_t access_righ    1643                        sos_ui32_t access_rights)
1660 {                                                1644 {
1661   struct sos_fs_pathname path;                   1645   struct sos_fs_pathname path;
1662                                                  1646 
1663   path.contents = _path;                         1647   path.contents = _path;
1664   path.length   = _pathlen;                      1648   path.length   = _pathlen;
1665                                                  1649 
1666   return fs_create_node(& path, creator, acce    1650   return fs_create_node(& path, creator, access_rights,
1667                         SOS_FS_NODE_DIRECTORY    1651                         SOS_FS_NODE_DIRECTORY, NULL);
1668 }                                                1652 }
1669                                                  1653 
1670                                                  1654 
1671 sos_ret_t sos_fs_rmdir(const struct sos_proce    1655 sos_ret_t sos_fs_rmdir(const struct sos_process * actor,
1672                        const char * _path,       1656                        const char * _path,
1673                        sos_size_t _pathlen)      1657                        sos_size_t _pathlen)
1674 {                                                1658 {
1675   sos_ret_t retval;                              1659   sos_ret_t retval;
1676   struct sos_fs_pathname path;                   1660   struct sos_fs_pathname path;
1677   struct sos_fs_nscache_node * nsnode;           1661   struct sos_fs_nscache_node * nsnode;
1678                                                  1662 
1679   path.contents = _path;                         1663   path.contents = _path;
1680   path.length   = _pathlen;                      1664   path.length   = _pathlen;
1681                                                  1665 
1682   if (path.length <= 0)                          1666   if (path.length <= 0)
1683     return -SOS_ENOENT;                          1667     return -SOS_ENOENT;
1684                                                  1668 
1685   if (path.contents[0] == '/')                   1669   if (path.contents[0] == '/')
1686     nsnode = sos_process_get_root(actor)->dir    1670     nsnode = sos_process_get_root(actor)->direntry;
1687   else                                           1671   else
1688     nsnode = sos_process_get_cwd(actor)->dire    1672     nsnode = sos_process_get_cwd(actor)->direntry;
1689                                                  1673 
1690   retval = fs_lookup_node(& path, FALSE,         1674   retval = fs_lookup_node(& path, FALSE,
1691                           sos_process_get_roo    1675                           sos_process_get_root(actor)->direntry,
1692                           nsnode,                1676                           nsnode,
1693                           & nsnode, & path, 0    1677                           & nsnode, & path, 0);
1694   if (SOS_OK != retval)                          1678   if (SOS_OK != retval)
1695     return retval;                               1679     return retval;
1696                                                  1680 
1697   /* Make sure the whole path has been resolv    1681   /* Make sure the whole path has been resolved */
1698   if (path.length > 0)                           1682   if (path.length > 0)
1699     {                                            1683     {
1700       sos_fs_nscache_unref_node(nsnode);         1684       sos_fs_nscache_unref_node(nsnode);
1701       return -SOS_ENOENT;                        1685       return -SOS_ENOENT;
1702     }                                            1686     }
1703                                                  1687 
1704   /* Cannot rmdir non-dir nodes */               1688   /* Cannot rmdir non-dir nodes */
1705   if (sos_fs_nscache_get_fs_node(nsnode)->typ    1689   if (sos_fs_nscache_get_fs_node(nsnode)->type != SOS_FS_NODE_DIRECTORY)
1706     retval = -SOS_ENOTDIR;                       1690     retval = -SOS_ENOTDIR;
1707                                                  1691 
1708   /* Cannot remove directory if it is still u    1692   /* Cannot remove directory if it is still used by somebody else */
1709   else if (sos_fs_nscache_get_ref_cnt(nsnode)    1693   else if (sos_fs_nscache_get_ref_cnt(nsnode) > 1)
1710     retval = -SOS_EBUSY;                         1694     retval = -SOS_EBUSY;
1711                                                  1695 
1712   /* Cannot remove directory if it is still h    1696   /* Cannot remove directory if it is still has children stored on
1713      disk */                                     1697      disk */
1714   else if (sos_fs_nscache_get_fs_node(nsnode)    1698   else if (sos_fs_nscache_get_fs_node(nsnode)->ondisk_lnk_cnt > 1)
1715     retval = -SOS_ENOTEMPTY;                     1699     retval = -SOS_ENOTEMPTY;
1716                                                  1700 
1717   /* Otherwise, yes : suppress the node on di    1701   /* Otherwise, yes : suppress the node on disk */
1718   else                                           1702   else
1719     retval = fs_remove_node(actor, nsnode);      1703     retval = fs_remove_node(actor, nsnode);
1720                                                  1704 
1721   sos_fs_nscache_unref_node(nsnode);             1705   sos_fs_nscache_unref_node(nsnode);
1722   return retval;                                 1706   return retval;
1723 }                                                1707 }
1724                                                  1708 
1725                                                  1709 
1726 sos_ret_t sos_fs_mknod(const struct sos_proce    1710 sos_ret_t sos_fs_mknod(const struct sos_process * creator,
1727                        const char * _path,       1711                        const char * _path,
1728                        sos_size_t _pathlen,      1712                        sos_size_t _pathlen,
1729                        sos_fs_node_type_t typ    1713                        sos_fs_node_type_t type /* only block/char allowed */,
1730                        sos_ui32_t access_righ    1714                        sos_ui32_t access_rights,
1731                        const struct sos_fs_de    1715                        const struct sos_fs_dev_id_t * devid)
1732 {                                                1716 {
1733   sos_ret_t retval;                              1717   sos_ret_t retval;
1734   struct sos_fs_pathname path;                   1718   struct sos_fs_pathname path;
1735   struct sos_fs_nscache_node * nsnode;           1719   struct sos_fs_nscache_node * nsnode;
1736   struct sos_fs_node * fsnode;                   1720   struct sos_fs_node * fsnode;
1737                                                  1721 
1738   if ((type != SOS_FS_NODE_DEVICE_BLOCK)      !! 1722   if (type != SOS_FS_NODE_DEVICE_CHAR)
1739       && (type != SOS_FS_NODE_DEVICE_CHAR))   << 
1740     return -SOS_EINVAL;                          1723     return -SOS_EINVAL;
1741                                                  1724 
1742   path.contents = _path;                         1725   path.contents = _path;
1743   path.length   = _pathlen;                      1726   path.length   = _pathlen;
1744                                                  1727 
1745   retval = fs_create_node(& path, creator, ac    1728   retval = fs_create_node(& path, creator, access_rights,
1746                           type, & nsnode);       1729                           type, & nsnode);
1747   if (SOS_OK != retval)                          1730   if (SOS_OK != retval)
1748     return retval;                               1731     return retval;
1749                                                  1732 
1750   fsnode = sos_fs_nscache_get_fs_node(nsnode)    1733   fsnode = sos_fs_nscache_get_fs_node(nsnode);
1751   fsnode->dev_id.device_class    = devid->dev    1734   fsnode->dev_id.device_class    = devid->device_class;
1752   fsnode->dev_id.device_instance = devid->dev    1735   fsnode->dev_id.device_instance = devid->device_instance;
1753                                                  1736 
1754   sos_fs_nscache_unref_node(nsnode);             1737   sos_fs_nscache_unref_node(nsnode);
1755   return SOS_OK;                                 1738   return SOS_OK;
1756 }                                                1739 }
1757                                                  1740 
1758                                                  1741 
1759 sos_ret_t sos_fs_stat(const struct sos_proces    1742 sos_ret_t sos_fs_stat(const struct sos_process * actor,
1760                       const char * _path,        1743                       const char * _path,
1761                       sos_size_t _pathlen,       1744                       sos_size_t _pathlen,
1762                       int nofollow,              1745                       int nofollow,
1763                       struct sos_fs_stat * re    1746                       struct sos_fs_stat * result)
1764 {                                                1747 {
1765   sos_ret_t retval;                              1748   sos_ret_t retval;
1766   struct sos_fs_pathname path;                   1749   struct sos_fs_pathname path;
1767   struct sos_fs_nscache_node * nsnode;           1750   struct sos_fs_nscache_node * nsnode;
1768   struct sos_fs_node * fsnode;                   1751   struct sos_fs_node * fsnode;
1769                                                  1752 
1770   path.contents = _path;                         1753   path.contents = _path;
1771   path.length   = _pathlen;                      1754   path.length   = _pathlen;
1772                                                  1755 
1773   if (path.length <= 0)                          1756   if (path.length <= 0)
1774     return -SOS_ENOENT;                          1757     return -SOS_ENOENT;
1775                                                  1758 
1776   if (path.contents[0] == '/')                   1759   if (path.contents[0] == '/')
1777     nsnode = sos_process_get_root(actor)->dir    1760     nsnode = sos_process_get_root(actor)->direntry;
1778   else                                           1761   else
1779     nsnode = sos_process_get_cwd(actor)->dire    1762     nsnode = sos_process_get_cwd(actor)->direntry;
1780                                                  1763 
1781   retval = fs_lookup_node(& path, (nofollow !    1764   retval = fs_lookup_node(& path, (nofollow != 0),
1782                           sos_process_get_roo    1765                           sos_process_get_root(actor)->direntry,
1783                           nsnode,                1766                           nsnode,
1784                           & nsnode, & path, 0    1767                           & nsnode, & path, 0);
1785   if (SOS_OK != retval)                          1768   if (SOS_OK != retval)
1786     return retval;                               1769     return retval;
1787                                                  1770 
1788   /* Make sure the whole path has been resolv    1771   /* Make sure the whole path has been resolved */
1789   if (path.length > 0)                           1772   if (path.length > 0)
1790     {                                            1773     {
1791       sos_fs_nscache_unref_node(nsnode);         1774       sos_fs_nscache_unref_node(nsnode);
1792       return -SOS_ENOENT;                        1775       return -SOS_ENOENT;
1793     }                                            1776     }
1794                                                  1777 
1795   fsnode = sos_fs_nscache_get_fs_node(nsnode)    1778   fsnode = sos_fs_nscache_get_fs_node(nsnode);
1796   retval = fsnode->ops_file->stat(fsnode, res    1779   retval = fsnode->ops_file->stat(fsnode, result);
1797                                                  1780   
1798   sos_fs_nscache_unref_node(nsnode);             1781   sos_fs_nscache_unref_node(nsnode);
1799   return retval;                                 1782   return retval;
1800 }                                                1783 }
1801                                                  1784 
1802                                                  1785 
1803 sos_ret_t sos_fs_fsync(struct sos_fs_opened_f    1786 sos_ret_t sos_fs_fsync(struct sos_fs_opened_file * of)
1804 {                                                1787 {
1805   struct sos_fs_node * fsnode = sos_fs_nscach    1788   struct sos_fs_node * fsnode = sos_fs_nscache_get_fs_node(of->direntry);
1806   return sos_fs_sync_node(fsnode);            !! 1789   return fsnode->sync(fsnode);
1807 }                                                1790 }
1808                                                  1791 
1809                                                  1792 
1810 sos_ret_t sos_fs_chmod(const struct sos_proce    1793 sos_ret_t sos_fs_chmod(const struct sos_process * actor,
1811                        const char * _path,       1794                        const char * _path,
1812                        sos_size_t _pathlen,      1795                        sos_size_t _pathlen,
1813                        sos_ui32_t access_righ    1796                        sos_ui32_t access_rights)
1814 {                                                1797 {
1815   sos_ret_t retval;                              1798   sos_ret_t retval;
1816   struct sos_fs_pathname path;                   1799   struct sos_fs_pathname path;
1817   struct sos_fs_nscache_node * nsnode;           1800   struct sos_fs_nscache_node * nsnode;
1818   struct sos_fs_node * fsnode;                   1801   struct sos_fs_node * fsnode;
1819                                                  1802 
1820   path.contents = _path;                         1803   path.contents = _path;
1821   path.length   = _pathlen;                      1804   path.length   = _pathlen;
1822                                                  1805 
1823   if (path.length <= 0)                          1806   if (path.length <= 0)
1824     return -SOS_ENOENT;                          1807     return -SOS_ENOENT;
1825                                                  1808 
1826   if (path.contents[0] == '/')                   1809   if (path.contents[0] == '/')
1827     nsnode = sos_process_get_root(actor)->dir    1810     nsnode = sos_process_get_root(actor)->direntry;
1828   else                                           1811   else
1829     nsnode = sos_process_get_cwd(actor)->dire    1812     nsnode = sos_process_get_cwd(actor)->direntry;
1830                                                  1813 
1831   retval = fs_lookup_node(& path, TRUE,          1814   retval = fs_lookup_node(& path, TRUE,
1832                           sos_process_get_roo    1815                           sos_process_get_root(actor)->direntry,
1833                           nsnode,                1816                           nsnode,
1834                           & nsnode, & path, 0    1817                           & nsnode, & path, 0);
1835   if (SOS_OK != retval)                          1818   if (SOS_OK != retval)
1836     return retval;                               1819     return retval;
1837                                                  1820 
1838   /* Make sure the whole path has been resolv    1821   /* Make sure the whole path has been resolved */
1839   if (path.length > 0)                           1822   if (path.length > 0)
1840     {                                            1823     {
1841       sos_fs_nscache_unref_node(nsnode);         1824       sos_fs_nscache_unref_node(nsnode);
1842       return -SOS_ENOENT;                        1825       return -SOS_ENOENT;
1843     }                                            1826     }
1844                                                  1827 
1845   fsnode = sos_fs_nscache_get_fs_node(nsnode)    1828   fsnode = sos_fs_nscache_get_fs_node(nsnode);
1846   retval = fsnode->ops_file->chmod(fsnode, ac    1829   retval = fsnode->ops_file->chmod(fsnode, access_rights);
1847   if (SOS_OK == retval)                          1830   if (SOS_OK == retval)
1848     mark_dirty_fsnode(fsnode, FALSE);            1831     mark_dirty_fsnode(fsnode, FALSE);
1849                                                  1832   
1850   sos_fs_nscache_unref_node(nsnode);             1833   sos_fs_nscache_unref_node(nsnode);
1851   return retval;                                 1834   return retval;
1852 }                                                1835 }
1853                                                  1836 
1854                                                  1837 
1855 sos_ret_t sos_fs_vfstat(const struct sos_proc    1838 sos_ret_t sos_fs_vfstat(const struct sos_process * actor,
1856                         const char * _path,      1839                         const char * _path,
1857                         sos_size_t _pathlen,     1840                         sos_size_t _pathlen,
1858                         struct sos_fs_statfs     1841                         struct sos_fs_statfs * result)
1859 {                                                1842 {
1860   sos_ret_t retval;                              1843   sos_ret_t retval;
1861   struct sos_fs_pathname path;                   1844   struct sos_fs_pathname path;
1862   struct sos_fs_nscache_node * nsnode;           1845   struct sos_fs_nscache_node * nsnode;
1863   struct sos_fs_node * fsnode;                   1846   struct sos_fs_node * fsnode;
1864                                                  1847 
1865   path.contents = _path;                         1848   path.contents = _path;
1866   path.length   = _pathlen;                      1849   path.length   = _pathlen;
1867                                                  1850 
1868   if (path.length <= 0)                          1851   if (path.length <= 0)
1869     return -SOS_ENOENT;                          1852     return -SOS_ENOENT;
1870                                                  1853 
1871   if (path.contents[0] == '/')                   1854   if (path.contents[0] == '/')
1872     nsnode = sos_process_get_root(actor)->dir    1855     nsnode = sos_process_get_root(actor)->direntry;
1873   else                                           1856   else
1874     nsnode = sos_process_get_cwd(actor)->dire    1857     nsnode = sos_process_get_cwd(actor)->direntry;
1875                                                  1858 
1876   retval = fs_lookup_node(& path, FALSE,         1859   retval = fs_lookup_node(& path, FALSE,
1877                           sos_process_get_roo    1860                           sos_process_get_root(actor)->direntry,
1878                           nsnode,                1861                           nsnode,
1879                           & nsnode, & path, 0    1862                           & nsnode, & path, 0);
1880   if (SOS_OK != retval)                          1863   if (SOS_OK != retval)
1881     return retval;                               1864     return retval;
1882                                                  1865 
1883   /* Make sure the whole path has been resolv    1866   /* Make sure the whole path has been resolved */
1884   if (path.length > 0)                           1867   if (path.length > 0)
1885     {                                            1868     {
1886       sos_fs_nscache_unref_node(nsnode);         1869       sos_fs_nscache_unref_node(nsnode);
1887       return -SOS_ENOENT;                        1870       return -SOS_ENOENT;
1888     }                                            1871     }
1889                                                  1872 
1890   fsnode = sos_fs_nscache_get_fs_node(nsnode)    1873   fsnode = sos_fs_nscache_get_fs_node(nsnode);
1891   if (fsnode->fs->statfs)                        1874   if (fsnode->fs->statfs)
1892     retval = fsnode->fs->statfs(fsnode->fs, r    1875     retval = fsnode->fs->statfs(fsnode->fs, result);
1893   else                                           1876   else
1894     retval = -SOS_ENOSYS;                        1877     retval = -SOS_ENOSYS;
1895                                                  1878   
1896   sos_fs_nscache_unref_node(nsnode);             1879   sos_fs_nscache_unref_node(nsnode);
1897   return retval;                                 1880   return retval;  
1898 }                                                1881 }
1899                                                  1882 
1900                                                  1883 
1901 /** This function is resilient against mounti    1884 /** This function is resilient against mounting/unmounting of other FS */
1902 sos_ret_t sos_fs_sync_all_fs()                   1885 sos_ret_t sos_fs_sync_all_fs()
1903 {                                                1886 {
1904   int dummy = 0;                                 1887   int dummy = 0;
1905   sos_ui64_t uid = 0;                            1888   sos_ui64_t uid = 0;
1906                                                  1889 
1907   while (1)                                      1890   while (1)
1908     {                                            1891     {
1909       /* Iterate over the FS types */            1892       /* Iterate over the FS types */
1910       struct sos_fs_manager_type * fstype;       1893       struct sos_fs_manager_type * fstype;
1911       int ntype;                                 1894       int ntype;
1912       list_foreach(fs_list, fstype, ntype)       1895       list_foreach(fs_list, fstype, ntype)
1913         {                                        1896         {
1914           /* Iterate over the FS instances */    1897           /* Iterate over the FS instances */
1915           struct sos_fs_manager_instance * fs    1898           struct sos_fs_manager_instance * fs;
1916           int ninst;                             1899           int ninst;
1917                                                  1900 
1918           /* This scan will be exhaustive and !! 1901           list_foreach(fstype->instances, fs, ninst)
1919              addition/removal of file systems << 
1920              added with list_add_tail (becaus << 
1921              ie in order head -> tail) */     << 
1922                                               << 
1923           /* As long as we don't block, we ca << 
1924              prev/next fields of the FS insta << 
1925           list_foreach_forward(fstype->instan << 
1926             {                                    1902             {
1927               if (fs->uid <= uid)                1903               if (fs->uid <= uid)
1928                 continue;                        1904                 continue;
1929                                                  1905 
1930               uid = fs->uid;                     1906               uid = fs->uid;
1931               sos_fs_sync_fs(fs);                1907               sos_fs_sync_fs(fs);
1932                                                  1908 
1933               /* We must NOT continue the loo    1909               /* We must NOT continue the loops because the
1934                  prev/next/current fs types/i    1910                  prev/next/current fs types/instances might have been
1935                  removed or added (sync block    1911                  removed or added (sync blocks, by definition) ! */
1936               goto lookup_next_fs;               1912               goto lookup_next_fs;
1937             }                                    1913             }
1938         }                                        1914         }
1939                                                  1915 
1940       /* Reached the end of the list */       << 
1941       break;                                  << 
1942                                               << 
1943     lookup_next_fs:                              1916     lookup_next_fs:
1944       /* Loop over */                            1917       /* Loop over */
1945       dummy ++;                                  1918       dummy ++;
1946     }                                            1919     }
1947                                                  1920 
1948   /* Now flush all the block devices to disk  !! 1921   return SOS_OK;
1949   return sos_blockdev_sync_all_devices();     << 
1950 }                                                1922 }
1951                                                  1923 
1952                                                  1924 
1953                                                  1925 
1954 /* ******************************************    1926 /* *************************************************************
1955  * mount/umount stuff                            1927  * mount/umount stuff
1956  */                                              1928  */
1957                                                  1929 
1958                                                  1930 
1959 sos_ret_t sos_fs_register_fs_instance(struct     1931 sos_ret_t sos_fs_register_fs_instance(struct sos_fs_manager_instance * fs,
1960                                       struct     1932                                       struct sos_fs_node * root_fsnode)
1961 {                                                1933 {
1962   sos_ret_t retval;                              1934   sos_ret_t retval;
1963   struct sos_fs_nscache_node * nsnode_root;      1935   struct sos_fs_nscache_node * nsnode_root;
1964                                                  1936 
1965   retval = sos_fs_nscache_create_mounted_root    1937   retval = sos_fs_nscache_create_mounted_root(root_fsnode, & nsnode_root);
1966   if (SOS_OK != retval)                          1938   if (SOS_OK != retval)
1967     return retval;                               1939     return retval;
1968                                                  1940 
1969   fs->uid  = ++last_fs_instance_uid;             1941   fs->uid  = ++last_fs_instance_uid;
1970   fs->root = nsnode_root;                        1942   fs->root = nsnode_root;
1971   sos_hash_insert(fs->nodecache, root_fsnode)    1943   sos_hash_insert(fs->nodecache, root_fsnode);
1972                                                  1944 
1973   list_add_tail(fs->fs_type->instances, fs);     1945   list_add_tail(fs->fs_type->instances, fs);
1974   return SOS_OK;                                 1946   return SOS_OK;
1975 }                                                1947 }
1976                                                  1948 
1977                                                  1949 
1978 sos_ret_t sos_fs_unregister_fs_instance(struc    1950 sos_ret_t sos_fs_unregister_fs_instance(struct sos_fs_manager_instance * fs)
1979 {                                                1951 {
1980   fs->uid = 0;                                   1952   fs->uid = 0;
1981   list_delete(fs->fs_type->instances, fs);       1953   list_delete(fs->fs_type->instances, fs);
1982   return SOS_OK;                                 1954   return SOS_OK;
1983 }                                                1955 }
1984                                                  1956 
1985                                                  1957 
1986 sos_ret_t sos_fs_register_fs_type(struct sos_    1958 sos_ret_t sos_fs_register_fs_type(struct sos_fs_manager_type * fstype)
1987 {                                                1959 {
1988   struct sos_fs_manager_type * iterator;         1960   struct sos_fs_manager_type * iterator;
1989   int nbtypes;                                   1961   int nbtypes;
1990                                                  1962 
1991   list_foreach_forward(fs_list, iterator, nbt    1963   list_foreach_forward(fs_list, iterator, nbtypes)
1992     {                                            1964     {
1993       if (! strncmp(fstype->name, iterator->n    1965       if (! strncmp(fstype->name, iterator->name, SOS_FS_MANAGER_NAME_MAXLEN))
1994         return -SOS_EEXIST;                      1966         return -SOS_EEXIST;
1995     }                                            1967     }
1996                                                  1968 
1997   list_add_tail(fs_list, fstype);                1969   list_add_tail(fs_list, fstype);
1998   return SOS_OK;                                 1970   return SOS_OK;
1999 }                                                1971 }
2000                                                  1972 
2001                                                  1973 
2002 sos_ret_t sos_fs_unregister_fs_type(struct so    1974 sos_ret_t sos_fs_unregister_fs_type(struct sos_fs_manager_type * fstype)
2003 {                                                1975 {
2004   struct sos_fs_manager_type * iterator;         1976   struct sos_fs_manager_type * iterator;
2005   int nbtypes;                                   1977   int nbtypes;
2006                                                  1978 
2007   if (! list_is_empty(fstype->instances))        1979   if (! list_is_empty(fstype->instances))
2008     return -SOS_EBUSY;                           1980     return -SOS_EBUSY;
2009                                                  1981 
2010   list_foreach_forward(fs_list, iterator, nbt    1982   list_foreach_forward(fs_list, iterator, nbtypes)
2011     {                                            1983     {
2012       if (! strncmp(fstype->name, iterator->n    1984       if (! strncmp(fstype->name, iterator->name, SOS_FS_MANAGER_NAME_MAXLEN))
2013         {                                        1985         {
2014           list_delete(fs_list, fstype);          1986           list_delete(fs_list, fstype);
2015           return SOS_OK;                         1987           return SOS_OK;
2016         }                                        1988         }
2017     }                                            1989     }
2018                                                  1990 
2019   return -SOS_EINVAL;                            1991   return -SOS_EINVAL;
2020 }                                                1992 }
2021                                                  1993 
2022                                                  1994 
2023 /**                                              1995 /**
2024  * _src_path may be empty                        1996  * _src_path may be empty
2025  */                                              1997  */
2026 sos_ret_t sos_fs_mount(struct sos_process * a    1998 sos_ret_t sos_fs_mount(struct sos_process * actor,
2027                        const char * _src_path    1999                        const char * _src_path,
2028                        sos_size_t _src_pathle    2000                        sos_size_t _src_pathlen,
2029                        const char * _dst_path    2001                        const char * _dst_path,
2030                        sos_size_t _dst_pathle    2002                        sos_size_t _dst_pathlen,
2031                        const char * fsname,      2003                        const char * fsname,
2032                        sos_ui32_t mountflags,    2004                        sos_ui32_t mountflags,
2033                        const char * args,        2005                        const char * args,
2034                        struct sos_fs_manager_    2006                        struct sos_fs_manager_instance ** result_fs)
2035 {                                                2007 {
2036   sos_ret_t retval;                              2008   sos_ret_t retval;
2037   struct sos_fs_pathname src_path, dst_path;     2009   struct sos_fs_pathname src_path, dst_path;
2038   struct sos_fs_nscache_node * src_nsnode, *     2010   struct sos_fs_nscache_node * src_nsnode, * dst_nsnode;
2039   struct sos_fs_manager_type * fs_type;          2011   struct sos_fs_manager_type * fs_type;
2040   struct sos_fs_manager_instance * new_fs;       2012   struct sos_fs_manager_instance * new_fs;
2041   int nb_fstypes;                                2013   int nb_fstypes;
2042                                                  2014 
2043   if (_dst_pathlen <= 0)                         2015   if (_dst_pathlen <= 0)
2044     return -SOS_ENOENT;                          2016     return -SOS_ENOENT;
2045                                                  2017 
2046   /* Look for the FS manager type */             2018   /* Look for the FS manager type */
2047   list_foreach(fs_list, fs_type, nb_fstypes)     2019   list_foreach(fs_list, fs_type, nb_fstypes)
2048     {                                            2020     {
2049       if (! strcmp(fsname, fs_type->name))       2021       if (! strcmp(fsname, fs_type->name))
2050         break;                                   2022         break;
2051     }                                            2023     }
2052   if (! list_foreach_early_break(fs_list, fs_    2024   if (! list_foreach_early_break(fs_list, fs_type, nb_fstypes))
2053     return -SOS_ENODEV;                          2025     return -SOS_ENODEV;
2054                                                  2026 
2055   src_path.contents = _src_path;                 2027   src_path.contents = _src_path;
2056   src_path.length   = _src_pathlen;              2028   src_path.length   = _src_pathlen;
2057                                                  2029 
2058   /* Compute the start_nsnode for the source     2030   /* Compute the start_nsnode for the source */
2059   if (src_path.length <= 0)                      2031   if (src_path.length <= 0)
2060     src_nsnode = NULL;                           2032     src_nsnode = NULL;
2061   else if (src_path.contents[0] == '/')          2033   else if (src_path.contents[0] == '/')
2062     src_nsnode = sos_process_get_root(actor)-    2034     src_nsnode = sos_process_get_root(actor)->direntry;
2063   else                                           2035   else
2064     src_nsnode = sos_process_get_cwd(actor)->    2036     src_nsnode = sos_process_get_cwd(actor)->direntry;
2065                                                  2037 
2066   /* Lookup the source node */                   2038   /* Lookup the source node */
2067   if (src_nsnode)                                2039   if (src_nsnode)
2068     {                                            2040     {
2069       retval = fs_lookup_node(& src_path, TRU    2041       retval = fs_lookup_node(& src_path, TRUE,
2070                               sos_process_get    2042                               sos_process_get_root(actor)->direntry,
2071                               src_nsnode,        2043                               src_nsnode,
2072                               & src_nsnode, &    2044                               & src_nsnode, & src_path, 0);
2073       if (SOS_OK != retval)                      2045       if (SOS_OK != retval)
2074         return retval;                           2046         return retval;
2075                                                  2047 
2076       /* Make sure the whole path has been re    2048       /* Make sure the whole path has been resolved */
2077       if (src_path.length > 0)                   2049       if (src_path.length > 0)
2078         {                                        2050         {
2079           sos_fs_nscache_unref_node(src_nsnod    2051           sos_fs_nscache_unref_node(src_nsnode);
2080           return -SOS_ENOENT;                    2052           return -SOS_ENOENT;
2081         }                                        2053         }
2082     }                                            2054     }
2083                                                  2055 
2084   dst_path.contents = _dst_path;                 2056   dst_path.contents = _dst_path;
2085   dst_path.length   = _dst_pathlen;              2057   dst_path.length   = _dst_pathlen;
2086                                                  2058 
2087   /* Compute the start_nsnode for the destina    2059   /* Compute the start_nsnode for the destination */
2088   if (dst_path.contents[0] == '/')               2060   if (dst_path.contents[0] == '/')
2089     dst_nsnode = sos_process_get_root(actor)-    2061     dst_nsnode = sos_process_get_root(actor)->direntry;
2090   else                                           2062   else
2091     dst_nsnode = sos_process_get_cwd(actor)->    2063     dst_nsnode = sos_process_get_cwd(actor)->direntry;
2092                                                  2064 
2093   /* Lookup the destination node */              2065   /* Lookup the destination node */
2094   retval = fs_lookup_node(& dst_path, TRUE,      2066   retval = fs_lookup_node(& dst_path, TRUE,
2095                           sos_process_get_roo    2067                           sos_process_get_root(actor)->direntry,
2096                           dst_nsnode,            2068                           dst_nsnode,
2097                           & dst_nsnode, & dst    2069                           & dst_nsnode, & dst_path, 0);
2098   if ((SOS_OK != retval) || (dst_path.length     2070   if ((SOS_OK != retval) || (dst_path.length > 0))
2099     {                                            2071     {
2100       if (src_nsnode)                            2072       if (src_nsnode)
2101         sos_fs_nscache_unref_node(src_nsnode)    2073         sos_fs_nscache_unref_node(src_nsnode);
2102       if (dst_path.length > 0)                   2074       if (dst_path.length > 0)
2103         retval = -SOS_ENOENT;                    2075         retval = -SOS_ENOENT;
2104       return retval;                             2076       return retval;
2105     }                                            2077     }
2106                                                  2078 
2107   /* Actually call the mount callback of the     2079   /* Actually call the mount callback of the FS */
2108   retval                                         2080   retval
2109     = fs_type->mount(fs_type,                    2081     = fs_type->mount(fs_type,
2110                      (src_nsnode)?sos_fs_nsca    2082                      (src_nsnode)?sos_fs_nscache_get_fs_node(src_nsnode):NULL,
2111                      args, & new_fs);            2083                      args, & new_fs);
2112   if (SOS_OK != retval)                          2084   if (SOS_OK != retval)
2113     {                                            2085     {
2114       if (src_nsnode)                            2086       if (src_nsnode)
2115         sos_fs_nscache_unref_node(src_nsnode)    2087         sos_fs_nscache_unref_node(src_nsnode);
2116       sos_fs_nscache_unref_node(dst_nsnode);     2088       sos_fs_nscache_unref_node(dst_nsnode);
2117       return retval;                             2089       return retval;
2118     }                                            2090     }
2119                                                  2091 
2120   /* Make sure the nodecache was created */      2092   /* Make sure the nodecache was created */
2121   SOS_ASSERT_FATAL(NULL != new_fs->nodecache)    2093   SOS_ASSERT_FATAL(NULL != new_fs->nodecache);
2122   SOS_ASSERT_FATAL(NULL != new_fs->root);        2094   SOS_ASSERT_FATAL(NULL != new_fs->root);
2123                                                  2095 
2124   /* Update some reserved fields */              2096   /* Update some reserved fields */
2125   sos_fs_nscache_get_fs_node(new_fs->root)->f    2097   sos_fs_nscache_get_fs_node(new_fs->root)->fs = new_fs;
2126                                                  2098 
2127   /* Register the mountpoint in the nscache *    2099   /* Register the mountpoint in the nscache */
2128   retval = sos_fs_nscache_mount(dst_nsnode, n    2100   retval = sos_fs_nscache_mount(dst_nsnode, new_fs->root);
2129   SOS_ASSERT_FATAL(SOS_OK == retval);            2101   SOS_ASSERT_FATAL(SOS_OK == retval);
2130                                                  2102 
2131   /* Un-reference the temporary nsnodes */       2103   /* Un-reference the temporary nsnodes */
2132   if (src_nsnode)                                2104   if (src_nsnode)
2133     sos_fs_nscache_unref_node(src_nsnode);       2105     sos_fs_nscache_unref_node(src_nsnode);
2134   sos_fs_nscache_unref_node(dst_nsnode);         2106   sos_fs_nscache_unref_node(dst_nsnode);
2135                                                  2107 
2136   if (result_fs)                                 2108   if (result_fs)
2137     *result_fs = new_fs;                         2109     *result_fs = new_fs;
2138                                                  2110 
2139   return SOS_OK;                                 2111   return SOS_OK;
2140 }                                                2112 }
2141                                                  2113 
2142                                                  2114 
2143 sos_ret_t sos_fs_umount(struct sos_process *     2115 sos_ret_t sos_fs_umount(struct sos_process * actor,
2144                         const char * _mounted    2116                         const char * _mounted_root_path,
2145                         sos_size_t _mounted_r    2117                         sos_size_t _mounted_root_pathlen)
2146 {                                                2118 {
2147   sos_ret_t retval;                              2119   sos_ret_t retval;
2148   struct sos_fs_pathname mounted_root_path;      2120   struct sos_fs_pathname mounted_root_path;
2149   struct sos_fs_nscache_node * mounted_root_n    2121   struct sos_fs_nscache_node * mounted_root_nsnode;
2150   struct sos_fs_manager_instance * fs;           2122   struct sos_fs_manager_instance * fs;
2151                                                  2123 
2152   if (_mounted_root_pathlen <= 0)                2124   if (_mounted_root_pathlen <= 0)
2153     return -SOS_ENOENT;                          2125     return -SOS_ENOENT;
2154                                                  2126 
2155   mounted_root_path.contents = _mounted_root_    2127   mounted_root_path.contents = _mounted_root_path;
2156   mounted_root_path.length   = _mounted_root_    2128   mounted_root_path.length   = _mounted_root_pathlen;
2157                                                  2129 
2158   /* Compute the start_nsnode for the mounted    2130   /* Compute the start_nsnode for the mounted_root */
2159   if (mounted_root_path.contents[0] == '/')      2131   if (mounted_root_path.contents[0] == '/')
2160     mounted_root_nsnode = sos_process_get_roo    2132     mounted_root_nsnode = sos_process_get_root(actor)->direntry;
2161   else                                           2133   else
2162     mounted_root_nsnode = sos_process_get_cwd    2134     mounted_root_nsnode = sos_process_get_cwd(actor)->direntry;
2163                                                  2135 
2164   /* Lookup the mounted_root node */             2136   /* Lookup the mounted_root node */
2165   retval = fs_lookup_node(& mounted_root_path    2137   retval = fs_lookup_node(& mounted_root_path, TRUE,
2166                           sos_process_get_roo    2138                           sos_process_get_root(actor)->direntry,
2167                           mounted_root_nsnode    2139                           mounted_root_nsnode,
2168                           & mounted_root_nsno    2140                           & mounted_root_nsnode, & mounted_root_path, 0);
2169   if (SOS_OK != retval)                          2141   if (SOS_OK != retval)
2170     return retval;                               2142     return retval;
2171                                                  2143 
2172   /* Make sure the whole path has been resolv    2144   /* Make sure the whole path has been resolved */
2173   if (mounted_root_path.length > 0)              2145   if (mounted_root_path.length > 0)
2174     {                                            2146     {
2175       sos_fs_nscache_unref_node(mounted_root_    2147       sos_fs_nscache_unref_node(mounted_root_nsnode);
2176       return -SOS_ENOENT;                        2148       return -SOS_ENOENT;
2177     }                                            2149     }
2178                                                  2150 
2179   /* Make sure this node is the real root of     2151   /* Make sure this node is the real root of the FS */
2180   fs = sos_fs_nscache_get_fs_node(mounted_roo    2152   fs = sos_fs_nscache_get_fs_node(mounted_root_nsnode)->fs;
2181   if (fs->root != mounted_root_nsnode)           2153   if (fs->root != mounted_root_nsnode)
2182     {                                            2154     {
2183       sos_fs_nscache_unref_node(mounted_root_    2155       sos_fs_nscache_unref_node(mounted_root_nsnode);
2184       return -SOS_ENOENT;                        2156       return -SOS_ENOENT;
2185     }                                            2157     }
2186                                                  2158 
2187   /* Disconnect this FS mounted_root from nam    2159   /* Disconnect this FS mounted_root from namespace cache */
2188   retval = sos_fs_nscache_umount(mounted_root    2160   retval = sos_fs_nscache_umount(mounted_root_nsnode);
2189                                                  2161 
2190   /* Mounted_Root not needed anymore */          2162   /* Mounted_Root not needed anymore */
2191   sos_fs_nscache_unref_node(mounted_root_nsno    2163   sos_fs_nscache_unref_node(mounted_root_nsnode);
2192   if (SOS_OK != retval)                          2164   if (SOS_OK != retval)
2193     return retval;                               2165     return retval;
2194                                                  2166 
2195   fs->root = NULL;                               2167   fs->root = NULL;
2196                                                  2168 
2197   /* Flush any changes to disk */                2169   /* Flush any changes to disk */
2198   retval = sos_fs_sync_fs(fs);                   2170   retval = sos_fs_sync_fs(fs);
2199   if (SOS_OK != retval)                          2171   if (SOS_OK != retval)
2200     {                                            2172     {
2201       return retval;                             2173       return retval;
2202     }                                            2174     }
2203                                                  2175 
2204   retval = fs->fs_type->umount(fs->fs_type, f    2176   retval = fs->fs_type->umount(fs->fs_type, fs);
2205   return retval;                                 2177   return retval;
2206 }                                                2178 }
                                                      

source navigation ] diff markup ] identifier search ] general search ]