SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

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

Diff markup

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

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