source: rtems/cpukit/libfs/src/rfs/rtems-rfs-link.c @ 8ec7abb

4.104.115
Last change on this file since 8ec7abb was 8ec7abb, checked in by Chris Johns <chrisj@…>, on 03/04/10 at 06:36:51

010-03-04 Chris Johns <chrisj@…>

  • libcsupport/include/rtems/libio.h, libcsupport/src/_rename_r.c: Add a rename file op and have rename use it.
  • libfs/Makefile.am, libfs/src/dosfs/msdos_rename.c, libfs/src/imfs/imfs_rename.c: New files to support the rename file op.
  • libfs/src/imfs/imfs.h: Add rename interface.
  • libfs/src/imfs/imfs_init.c: Add rename handler.
  • libfs/src/imfs/miniimfs_init.c: Fix up ops struct.
  • libfs/src/dosfs/msdos.h: Add msdos_rename and remove msdos_file_link.
  • libfs/src/dosfs/msdos_create.c: Remove the link call.
  • libfs/src/dosfs/msdos_eval.c: Fix a path parsing bug.
  • libfs/src/dosfs/msdos_init.c: Add rename handler and clean up the struct naming.
  • libfs/src/rfs/rtems-rfs-link.c, libfs/src/rfs/rtems-rfs-link.h: Change the link call to allow linking of directories if told to and change the unlink to handle unlink directories that are not empty so rename can be supported.
  • libfs/src/rfs/rtems-rfs-rtems-dir.c: Fix the link/unlink calls.
  • libfs/src/rfs/rtems-rfs-rtems.c: Add a rename handler. Fix the link/unlink calls.
  • libfs/src/dosfs/msdos_dir.c, libfs/src/dosfs/msdos_format.c, libfs/src/dosfs/msdos_misc.c, httpd/asp.c, libfs/src/nfsclient/src/nfs.c: Work around a newlib warning when using the is*() family of calls.
  • Property mode set to 100644
File size: 11.5 KB
Line 
1/*
2 *  COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org>
3 *
4 *  The license and distribution terms for this file may be
5 *  found in the file LICENSE in this distribution or at
6 *  http://www.rtems.com/license/LICENSE.
7 *
8 *  $Id$
9 */
10/**
11 * @file
12 *
13 * @ingroup rtems-rfs
14 *
15 * RTEMS File Systems Link Routines.
16 *
17 * These functions manage links. A link is the addition of a directory entry in
18 * a parent directory and incrementing the links count in the inode.
19 */
20
21#include <rtems/rfs/rtems-rfs-block.h>
22#include <rtems/rfs/rtems-rfs-buffer.h>
23#include <rtems/rfs/rtems-rfs-file-system.h>
24#include <rtems/rfs/rtems-rfs-trace.h>
25#include <rtems/rfs/rtems-rfs-dir.h>
26#include <rtems/rfs/rtems-rfs-dir-hash.h>
27#include <rtems/rfs/rtems-rfs-link.h>
28
29int
30rtems_rfs_link (rtems_rfs_file_system* fs,
31                const char*            name,
32                int                    length,
33                rtems_rfs_ino          parent,
34                rtems_rfs_ino          target,
35                bool                   link_dir)
36{
37  rtems_rfs_inode_handle parent_inode;
38  rtems_rfs_inode_handle target_inode;
39  uint16_t               links;
40  int                    rc;
41
42  if (rtems_rfs_trace (RTEMS_RFS_TRACE_LINK))
43  {
44    int c;
45    printf ("rtems-rfs: link: parent(%lu) -> ", parent);
46    for (c = 0; c < length; c++)
47      printf ("%c", name[c]);
48    printf ("(%lu)\n", target);
49  }
50
51  rc = rtems_rfs_inode_open (fs, target, &target_inode, true);
52  if (rc)
53    return rc;
54
55  /*
56   * If the target inode is a directory and we cannot link directories
57   * return a not supported error code.
58   */
59  if (!link_dir && S_ISDIR (rtems_rfs_inode_get_mode (&target_inode)))
60  {
61    rtems_rfs_inode_close (fs, &target_inode);
62    return ENOTSUP;
63  }
64 
65  rc = rtems_rfs_inode_open (fs, parent, &parent_inode, true);
66  if (rc)
67  {
68    rtems_rfs_inode_close (fs, &target_inode);
69    return rc;
70  }
71
72  rc = rtems_rfs_dir_add_entry (fs, &parent_inode, name, length, target);
73  if (rc > 0)
74  {
75    rtems_rfs_inode_close (fs, &parent_inode);
76    rtems_rfs_inode_close (fs, &target_inode);
77    return rc;
78  }
79 
80  links = rtems_rfs_inode_get_links (&target_inode) + 1;
81  rtems_rfs_inode_set_links (&target_inode, links);
82
83  rc = rtems_rfs_inode_time_stamp_now (&parent_inode, true, true);
84  if (rc > 0)
85  {
86    rtems_rfs_inode_close (fs, &parent_inode);
87    rtems_rfs_inode_close (fs, &target_inode);
88    return rc;
89  }
90
91  rc = rtems_rfs_inode_close (fs, &parent_inode);
92  if (rc > 0)
93  {
94    rtems_rfs_inode_close (fs, &target_inode);
95    return rc;
96  }
97
98  rc = rtems_rfs_inode_close (fs, &target_inode);
99
100  return rc;
101}
102
103int
104rtems_rfs_unlink (rtems_rfs_file_system* fs,
105                  rtems_rfs_ino          parent,
106                  rtems_rfs_ino          target,
107                  uint32_t               doff,
108                  rtems_rfs_unlink_dir   dir_mode)
109{
110  rtems_rfs_inode_handle parent_inode;
111  rtems_rfs_inode_handle target_inode;
112  uint16_t               links;
113  bool                   dir;
114  int                    rc;
115
116  if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
117    printf ("rtems-rfs: unlink: parent(%lu) -X-> (%lu)\n", parent, target);
118
119  rc = rtems_rfs_inode_open (fs, target, &target_inode, true);
120  if (rc)
121    return rc;
122 
123  /*
124   * If a directory process the unlink mode.
125   */
126 
127  dir = RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&target_inode)); 
128  if (dir)
129  {
130    switch (dir_mode)
131    {
132      case rtems_rfs_unlink_dir_denied:
133        if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
134          printf ("rtems-rfs: link is a directory\n");
135        rtems_rfs_inode_close (fs, &target_inode);
136        return EISDIR;
137
138      case rtems_rfs_unlink_dir_if_empty:
139        rc = rtems_rfs_dir_empty (fs, &target_inode);
140        if (rc > 0)
141        {
142          if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
143            printf ("rtems-rfs: dir-empty: %d: %s\n", rc, strerror (rc));
144          rtems_rfs_inode_close (fs, &target_inode);
145          return rc;
146        }
147        break;
148
149      default:
150        break;
151    }
152  }
153 
154  rc = rtems_rfs_inode_open (fs, parent, &parent_inode, true);
155  if (rc)
156  {
157    if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
158      printf ("rtems-rfs: link: inode-open failed: %d: %s\n",
159              rc, strerror (rc));
160    rtems_rfs_inode_close (fs, &target_inode);
161    return rc;
162  }
163 
164  rc = rtems_rfs_dir_del_entry (fs, &parent_inode, target, doff);
165  if (rc > 0)
166  {
167    if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
168      printf ("rtems-rfs: unlink: dir-del failed: %d: %s\n",
169              rc, strerror (rc));
170    rtems_rfs_inode_close (fs, &parent_inode);
171    rtems_rfs_inode_close (fs, &target_inode);
172    return rc;
173  }
174 
175  links = rtems_rfs_inode_get_links (&target_inode);
176
177  if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
178    printf ("rtems-rfs: unlink: target:%lu links:%u\n", target, links);
179
180  if (links > 1)
181  {
182    links--;
183    rtems_rfs_inode_set_links (&target_inode, links);
184  }
185  else
186  {
187    /*
188     * Erasing the inode releases all blocks attached to it.
189     */
190    rc = rtems_rfs_inode_delete (fs, &target_inode);
191    if (rc > 0)
192    {
193      if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
194        printf ("rtems-rfs: unlink: inode-del failed: %d: %s\n",
195                rc, strerror (rc));
196      rtems_rfs_inode_close (fs, &parent_inode);
197      rtems_rfs_inode_close (fs, &target_inode);
198      return rc;
199    }
200
201    if (dir)
202    {
203      links = rtems_rfs_inode_get_links (&parent_inode);
204      if (links > 1)
205        links--;
206      rtems_rfs_inode_set_links (&parent_inode, links);
207    }
208  }
209 
210  rc = rtems_rfs_inode_time_stamp_now (&parent_inode, true, true);
211  if (rc > 0)
212  {
213    if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
214      printf ("rtems-rfs: link: inode-time-stamp failed: %d: %s\n",
215              rc, strerror (rc));
216    rtems_rfs_inode_close (fs, &parent_inode);
217    rtems_rfs_inode_close (fs, &target_inode);
218    return rc;
219  }
220
221  rc = rtems_rfs_inode_close (fs, &parent_inode);
222  if (rc > 0)
223  {
224    if (rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
225      printf ("rtems-rfs: link: parent inode-close failed: %d: %s\n",
226              rc, strerror (rc));
227    rtems_rfs_inode_close (fs, &target_inode);
228    return rc;
229  }
230
231  rc = rtems_rfs_inode_close (fs, &target_inode);
232
233  if ((rc > 0) && rtems_rfs_trace (RTEMS_RFS_TRACE_UNLINK))
234    printf ("rtems-rfs: link: target inode-close failed: %d: %s\n",
235            rc, strerror (rc));
236 
237  return rc;
238}
239
240int
241rtems_rfs_symlink (rtems_rfs_file_system* fs,
242                   const char*            name,
243                   int                    length,
244                   const char*            link,
245                   int                    link_length,
246                   uid_t                  uid,
247                   gid_t                  gid,
248                   rtems_rfs_ino          parent)
249{
250  rtems_rfs_inode_handle inode;
251  rtems_rfs_ino          ino;
252  int                    rc;
253 
254  if (rtems_rfs_trace (RTEMS_RFS_TRACE_SYMLINK))
255  {
256    int c;
257    printf ("rtems-rfs: symlink: parent:%lu name:", parent);
258    for (c = 0; c < length; c++)
259      printf ("%c", name[c]);
260    printf (" link:");
261    for (c = 0; c < link_length; c++)
262      printf ("%c", link[c]);
263  }
264
265  if (link_length >= rtems_rfs_fs_block_size (fs))
266    return ENAMETOOLONG;
267 
268  rc = rtems_rfs_inode_create (fs, parent, name, strlen (name),
269                               RTEMS_RFS_S_SYMLINK,
270                               1, uid, gid, &ino);
271  if (rc > 0)
272    return rc;
273 
274  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
275  if (rc > 0)
276    return rc;
277
278  /*
279   * If the link length is less than the length of data union in the inode
280   * place the link into the data area else allocate a block and write the link
281   * to that.
282   */
283  if (link_length < RTEMS_RFS_INODE_DATA_NAME_SIZE)
284  {
285    memset (inode.node->data.name, 0, RTEMS_RFS_INODE_DATA_NAME_SIZE);
286    memcpy (inode.node->data.name, link, link_length);
287    rtems_rfs_inode_set_block_count (&inode, 0);
288  }
289  else
290  {
291    rtems_rfs_block_map     map;
292    rtems_rfs_block_no      block;
293    rtems_rfs_buffer_handle buffer;
294    uint8_t*                data;
295   
296    rc = rtems_rfs_block_map_open (fs, &inode, &map);
297    if (rc > 0)
298    {
299      rtems_rfs_inode_close (fs, &inode);
300      return rc;
301    }
302
303    rc = rtems_rfs_block_map_grow (fs, &map, 1, &block);
304    if (rc > 0)
305    {
306      rtems_rfs_block_map_close (fs, &map);
307      rtems_rfs_inode_close (fs, &inode);
308      return rc;
309    }
310
311    rc = rtems_rfs_buffer_handle_open (fs, &buffer);
312    if (rc > 0)
313    {
314      rtems_rfs_block_map_close (fs, &map);
315      rtems_rfs_inode_close (fs, &inode);
316      return rc;
317    }
318
319    rc = rtems_rfs_buffer_handle_request (fs, &buffer, block, false);
320    if (rc > 0)
321    {
322      rtems_rfs_block_map_close (fs, &map);
323      rtems_rfs_inode_close (fs, &inode);
324      return rc;
325    }
326
327    data = rtems_rfs_buffer_data (&buffer);
328   
329    memset (data, 0xff, rtems_rfs_fs_block_size (fs));
330    memcpy (data, link, link_length);
331
332    rc = rtems_rfs_buffer_handle_close (fs, &buffer);
333    if (rc > 0)
334    {
335      rtems_rfs_block_map_close (fs, &map);
336      rtems_rfs_inode_close (fs, &inode);
337      return rc;
338    }
339
340    rc = rtems_rfs_block_map_close (fs, &map);
341    if (rc > 0)
342    {
343      rtems_rfs_inode_close (fs, &inode);
344      return rc;
345    }
346  }
347 
348  rtems_rfs_inode_set_block_offset (&inode, link_length);
349
350  rc = rtems_rfs_inode_close (fs, &inode);
351 
352  return rc;
353}
354
355int
356rtems_rfs_symlink_read (rtems_rfs_file_system* fs,
357                        rtems_rfs_ino          link,
358                        char*                  path,
359                        size_t                 size,
360                        size_t*                length)
361{
362  rtems_rfs_inode_handle inode;
363  int                    rc;
364 
365  if (rtems_rfs_trace (RTEMS_RFS_TRACE_SYMLINK_READ))
366    printf ("rtems-rfs: symlink-read: link:%lu\n", link);
367
368  rc = rtems_rfs_inode_open (fs, link, &inode, true);
369  if (rc)
370    return rc;
371
372  if (!RTEMS_RFS_S_ISLNK (rtems_rfs_inode_get_mode (&inode)))
373  {
374    rtems_rfs_inode_close (fs, &inode);
375    return EINVAL;
376  }
377
378  *length = rtems_rfs_inode_get_block_offset (&inode);
379 
380  if (size < *length)
381  {
382    rtems_rfs_inode_close (fs, &inode);
383    return EINVAL;
384  }
385     
386  if (rtems_rfs_inode_get_block_count (&inode) == 0)
387  {
388    memcpy (path, inode.node->data.name, *length);
389  }
390  else
391  {
392    rtems_rfs_block_map     map;
393    rtems_rfs_block_no      block;
394    rtems_rfs_buffer_handle buffer;
395    char*                   data;
396   
397    rc = rtems_rfs_block_map_open (fs, &inode, &map);
398    if (rc > 0)
399    {
400      rtems_rfs_inode_close (fs, &inode);
401      return rc;
402    }
403
404    rc = rtems_rfs_block_map_seek (fs, &map, 0, &block);
405    if (rc > 0)
406    {
407      rtems_rfs_block_map_close (fs, &map);
408      rtems_rfs_inode_close (fs, &inode);
409      return rc;
410    }
411
412    rc = rtems_rfs_buffer_handle_open (fs, &buffer);
413    if (rc > 0)
414    {
415      rtems_rfs_block_map_close (fs, &map);
416      rtems_rfs_inode_close (fs, &inode);
417      return rc;
418    }
419
420    rc = rtems_rfs_buffer_handle_request (fs, &buffer, block, false);
421    if (rc > 0)
422    {
423      rtems_rfs_block_map_close (fs, &map);
424      rtems_rfs_inode_close (fs, &inode);
425      return rc;
426    }
427
428    data = rtems_rfs_buffer_data (&buffer);
429    memcpy (path, data, *length);
430
431    rc = rtems_rfs_buffer_handle_close (fs, &buffer);
432    if (rc > 0)
433    {
434      rtems_rfs_block_map_close (fs, &map);
435      rtems_rfs_inode_close (fs, &inode);
436      return rc;
437    }
438
439    rc = rtems_rfs_block_map_close (fs, &map);
440    if (rc > 0)
441    {
442      rtems_rfs_inode_close (fs, &inode);
443      return rc;
444    }
445  }
446
447  path[*length] = '\0';
448
449  rc = rtems_rfs_inode_close (fs, &inode);
450 
451  return rc;
452}
Note: See TracBrowser for help on using the repository browser.