SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

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

Diff markup

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


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

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