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) and /sos/fs.c (Article 8)


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

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