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


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

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