SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

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

Diff markup

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


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

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