source: rtems/cpukit/libfs/src/rfs/rtems-rfs-format.c @ 965dc55

4.104.115
Last change on this file since 965dc55 was 3cfa636, checked in by Chris Johns <chrisj@…>, on 02/26/10 at 05:54:59

010-02-26 Chris Johns <chrisj@…>

  • libfs/src/rfs/rtems-rfs-block.c: Reset a buffer handle after moving down an indirection level.
  • libfs/src/rfs/rtems-rfs-dir.c: Move directory entry validation into a macro and use the macro. Fix the range check on the ino so all inodes can be used.
  • libfs/src/rfs/rtems-rfs-file-system.c,
libfs/src/rfs/rtems-rfs-file-system.h
Add a version number to the superblock. Use RTEMS_RFS_INODE_SIZE.
  • libfs/src/rfs/rtems-rfs-file.c: Fix the size offset on partial block lengths. Set the size in the file handle on a truncate to 0.
  • libfs/src/rfs/rtems-rfs-format.c: Add a version number to the superblock. Use RTEMS_RFS_INODE_SIZE. A better set of defaults for small disks.
  • libfs/src/rfs/rtems-rfs-inode.c: Use RTEMS_RFS_INODE_SIZE. Free the allocated inode if it cannot be opened.
  • libfs/src/rfs/rtems-rfs-inode.h: Add RTEMS_RFS_INODE_SIZE.
  • libfs/src/rfs/rtems-rfs-rtems-file.c: Move some of the iop acceses inside the fs lock.
  • libfs/src/rfs/rtems-rfs-shell.c: Use RTEMS_RFS_INODE_SIZE.
  • Property mode set to 100644
File size: 17.6 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 Format
16 *
17 * Format the file system ready for use.
18 */
19
20#include <stdlib.h>
21#include <stdio.h>
22
23#include <rtems/rfs/rtems-rfs-data.h>
24#include <rtems/rfs/rtems-rfs-file-system.h>
25#include <rtems/rfs/rtems-rfs-inode.h>
26#include <rtems/rtems-rfs-format.h>
27#include <rtems/rfs/rtems-rfs-dir.h>
28
29/**
30 * Return the number of gigabytes.
31 */
32#define GIGS(_g) ((_g) * 1024 * 1024)
33
34/**
35 * Return the number of bits that fit in the block size.
36 */
37static int
38rtems_rfs_bits_per_block (rtems_rfs_file_system* fs)
39{
40  return rtems_rfs_bitmap_numof_bits (rtems_rfs_fs_block_size (fs));
41}
42
43/**
44 * Return a rounded up integer quotient given a dividend and divisor. That is:
45 * "quotient = dividend / divisor"
46 */
47int
48rtems_rfs_rup_quotient (uint32_t dividend, uint32_t divisor)
49{
50  if (dividend == 0)
51    return 1;
52  return ((dividend - 1) / divisor) + 1;
53}
54
55/**
56 * Return the number of inodes as a percentage of the total number that can fit
57 * in a blocl.
58 */
59static int
60rtems_rfs_inodes_from_percent (rtems_rfs_file_system* fs,
61                               int                    percentage)
62{
63  int blocks;
64  blocks = ((rtems_rfs_fs_blocks (fs) -
65             RTEMS_RFS_SUPERBLOCK_SIZE) * percentage) / 100;
66  blocks = rtems_rfs_rup_quotient (blocks, fs->group_count);
67  return blocks * (rtems_rfs_fs_block_size (fs) / RTEMS_RFS_INODE_SIZE);
68}
69
70/**
71 * Return the inode overhead given a number of inodes.
72 */
73static int
74rtems_rfs_inode_overhead (rtems_rfs_file_system* fs)
75{
76  int blocks;
77  int bits_per_block;
78  blocks = rtems_rfs_rup_quotient(fs->group_inodes * RTEMS_RFS_INODE_SIZE,
79                                  rtems_rfs_fs_block_size (fs));
80  bits_per_block = rtems_rfs_bits_per_block (fs);
81  /*
82   * There could be more bits that there are blocks, eg 512K disk with 512
83   * blocks.
84   */
85  if (bits_per_block > (rtems_rfs_fs_blocks (fs) - RTEMS_RFS_SUPERBLOCK_SIZE))
86    bits_per_block = rtems_rfs_fs_blocks (fs) - RTEMS_RFS_SUPERBLOCK_SIZE;
87  return ((blocks + 1) * 100 * 10) / bits_per_block;
88}
89
90static bool
91rtems_rfs_check_config (rtems_rfs_file_system*         fs,
92                        const rtems_rfs_format_config* config)
93{
94  fs->block_size = config->block_size;
95  if (!fs->block_size)
96  {
97    uint64_t total_size = rtems_rfs_fs_media_size (fs);
98
99    if (total_size >= GIGS (1))
100    {
101      uint32_t gigs = (total_size + GIGS (1)) / GIGS (1);
102      int      b;
103      for (b = 31; b > 0; b--)
104        if ((gigs & (1 << b)) != 0)
105          break;
106      fs->block_size = 1 << b;
107    }
108
109    if (fs->block_size < 512)
110      fs->block_size = 512;
111   
112    if (fs->block_size > (4 * 1024))
113      fs->block_size = (4 * 1024);
114  }
115 
116  if ((fs->block_size % rtems_rfs_fs_media_block_size (fs)) != 0)
117  {
118    printf ("block size (%ld) is not a multiple of media block size (%ld)\n",
119            fs->block_size, rtems_rfs_fs_media_block_size (fs));
120    return false;
121  }
122
123  fs->group_blocks = config->group_blocks;
124  if (!fs->group_blocks)
125  {
126    /*
127     * The number of blocks per group is defined by the number of bits in a
128     * block.
129     */
130    fs->group_blocks = rtems_rfs_bitmap_numof_bits (fs->block_size);
131  }
132
133  if (fs->group_blocks > rtems_rfs_bitmap_numof_bits (fs->block_size))
134  {
135    printf ("group block count is higher than bits in block\n");
136    return false;
137  }
138 
139  fs->blocks = rtems_rfs_fs_media_size (fs) / fs->block_size;
140
141  /*
142   * The bits per block sets the upper limit for the number of blocks in a
143   * group. The disk will be divided into groups which are the number of bits
144   * per block.
145   */ 
146  fs->group_count = rtems_rfs_rup_quotient (rtems_rfs_fs_blocks (fs),
147                                            rtems_rfs_bits_per_block (fs));
148
149  fs->group_inodes = config->group_inodes;
150  if (!fs->group_inodes)
151  {
152    int inode_overhead = RTEMS_RFS_INODE_OVERHEAD_PERCENTAGE;
153   
154    /*
155     * The number of inodes per group is set as a percentage.
156     */
157    if (config->inode_overhead)
158      inode_overhead = config->inode_overhead;
159     
160    fs->group_inodes = rtems_rfs_inodes_from_percent (fs, inode_overhead);
161  }
162
163  /*
164   * Round up to fill a block because the minimum allocation unit is a block.
165   */
166  fs->inodes_per_block = rtems_rfs_fs_block_size (fs) / RTEMS_RFS_INODE_SIZE;
167  fs->group_inodes =
168    rtems_rfs_rup_quotient (fs->group_inodes,
169                            fs->inodes_per_block) * fs->inodes_per_block;
170 
171  if (fs->group_inodes > rtems_rfs_bitmap_numof_bits (fs->block_size))
172    fs->group_inodes = rtems_rfs_bitmap_numof_bits (fs->block_size);
173
174  fs->max_name_length = config->max_name_length;
175  if (!fs->max_name_length)
176  {
177    fs->max_name_length = 512;
178  }
179 
180  return true;
181}
182
183static bool
184rtems_rfs_write_group (rtems_rfs_file_system* fs,
185                       int                    group,
186                       bool                   initialise_inodes,
187                       bool                   verbose)
188{
189  rtems_rfs_buffer_handle  handle;
190  rtems_rfs_bitmap_control bitmap;
191  rtems_rfs_buffer_block   group_base;
192  size_t                   group_size;
193  int                      blocks;
194  int                      b;
195  int                      rc;
196 
197  group_base = rtems_rfs_fs_block (fs, group, 0);
198
199  if (group_base > rtems_rfs_fs_blocks (fs))
200  {
201    printf ("rtems-rfs: write-group: group %d base beyond disk limit\n",
202            group);
203    return false;
204  }
205
206  group_size = fs->group_blocks;
207
208  /*
209   * Be nice to strange sizes of disks. These are embedded systems after all
210   * and nice numbers do not always work out. Let the last block pick up the
211   * remainder of the blocks.
212   */
213  if ((group_base + group_size) > rtems_rfs_fs_blocks (fs))
214    group_size = rtems_rfs_fs_blocks (fs) - group_base;
215
216  if (verbose)
217    printf ("\rrtems-rfs: format: group %3d: base = %ld, size = %ld",
218            group, group_base, group_size);
219
220  /*
221   * Open a handle and request an empty buffer.
222   */
223  rc = rtems_rfs_buffer_handle_open (fs, &handle);
224  if (rc > 0)
225  {
226    printf ("\nrtems-rfs: write-group: handle open failed: %d: %s\n",
227            rc, strerror (rc));
228    return false;
229  }
230
231  if (verbose)
232    printf (", blocks");
233 
234  /*
235   * Open the block bitmap using the new buffer.
236   */
237  rc = rtems_rfs_bitmap_open (&bitmap, fs, &handle, group_size,
238                              group_base + RTEMS_RFS_GROUP_BLOCK_BITMAP_BLOCK);
239  if (rc > 0)
240  {
241    rtems_rfs_buffer_handle_close (fs, &handle);
242    printf ("\nrtems-rfs: write-group: group %3d: open block bitmap failed: %d: %s\n",
243            group, rc, strerror (rc));
244    return false;
245  }
246
247  /*
248   * Force the whole buffer to a known state. The bit map may not occupy the
249   * whole block.
250   */
251  memset (rtems_rfs_buffer_data (&handle), 0xff, rtems_rfs_fs_block_size (fs));
252 
253  /*
254   * Clear the bitmap.
255   */
256  rc = rtems_rfs_bitmap_map_clear_all (&bitmap);
257  if (rc > 0)
258  {
259    rtems_rfs_bitmap_close (&bitmap);
260    rtems_rfs_buffer_handle_close (fs, &handle);
261    printf ("\nrtems-rfs: write-group: group %3d: block bitmap clear all failed: %d: %s\n",
262            group, rc, strerror (rc));
263    return false;
264  }
265 
266  /*
267   * Forced allocation of the block bitmap.
268   */
269  rtems_rfs_bitmap_map_set (&bitmap, RTEMS_RFS_GROUP_BLOCK_BITMAP_BLOCK);
270
271  /*
272   * Forced allocation of the inode bitmap.
273   */
274  rtems_rfs_bitmap_map_set (&bitmap, RTEMS_RFS_GROUP_INODE_BITMAP_BLOCK);
275
276  /*
277   * Determine the number of inodes blocks in the group.
278   */
279  blocks = rtems_rfs_rup_quotient (fs->group_inodes, fs->inodes_per_block);
280
281  /*
282   * Forced allocation of the inode blocks which follow the block bitmap.
283   */
284  for (b = 0; b < blocks; b++)
285    rtems_rfs_bitmap_map_set (&bitmap, b + RTEMS_RFS_GROUP_INODE_BLOCK);
286
287  /*
288   * Close the block bitmap.
289   */
290  rc = rtems_rfs_bitmap_close (&bitmap);
291  if (rc > 0)
292  {
293    rtems_rfs_buffer_handle_close (fs, &handle);
294    printf ("\nrtems-rfs: write-group: group %3d: close block bitmap failed: %d: %s\n",
295            group, rc, strerror (rc));
296    return false;
297  }
298
299  rtems_rfs_buffer_mark_dirty (&handle);
300
301  if (verbose)
302    printf (", inodes");
303 
304  /*
305   * Open the inode bitmap using the old buffer. Should release any changes.
306   */
307  rc = rtems_rfs_bitmap_open (&bitmap, fs, &handle, group_size,
308                              group_base + RTEMS_RFS_GROUP_INODE_BITMAP_BLOCK);
309  if (rc > 0)
310  {
311    rtems_rfs_buffer_handle_close (fs, &handle);
312    printf ("\nrtems-rfs: write-group: group %3d: open inode bitmap failed: %d: %s\n",
313            group, rc, strerror (rc));
314    return false;
315  }
316
317  /*
318   * Force the whole buffer to a known state. The bit map may not occupy the
319   * whole block.
320   */
321  memset (rtems_rfs_buffer_data (&handle), 0x00, rtems_rfs_fs_block_size (fs));
322 
323  /*
324   * Clear the inode bitmap.
325   */
326  rc = rtems_rfs_bitmap_map_clear_all (&bitmap);
327  if (rc > 0)
328  {
329    rtems_rfs_bitmap_close (&bitmap);
330    rtems_rfs_buffer_handle_close (fs, &handle);
331    printf ("\nrtems-rfs: write-group: group %3d: inode bitmap" \
332            " clear all failed: %d: %s\n", group, rc, strerror (rc));
333    return false;
334  }
335 
336  /*
337   * Close the inode bitmap.
338   */
339  rc = rtems_rfs_bitmap_close (&bitmap);
340  if (rc > 0)
341  {
342    rtems_rfs_buffer_handle_close (fs, &handle);
343    printf ("\nrtems-rfs: write-group: group %3d: close inode" \
344            " bitmap failed: %d: %s\n", group, rc, strerror (rc));
345    return false;
346  }
347
348  rtems_rfs_buffer_mark_dirty (&handle);
349
350  /*
351   * Initialise the inode tables if rerquired to do so.
352   */
353  if (initialise_inodes)
354  {
355    for (b = 0; b < blocks; b++)
356    {
357      rc = rtems_rfs_buffer_handle_request (fs, &handle,
358                                            group_base + b + RTEMS_RFS_GROUP_INODE_BLOCK,
359                                            false);
360      if (rc > 0)
361      {
362        rtems_rfs_buffer_handle_close (fs, &handle);
363        printf ("\nrtems-rfs: write-group: group %3d: block %ld request failed: %d: %s\n",
364                group, group_base + b + RTEMS_RFS_GROUP_INODE_BLOCK,
365                rc, strerror (rc));
366        return false;
367      }
368   
369      /*
370       * Force the whole buffer to a known state. The bit map may not occupy the
371       * whole block.
372       */
373      memset (rtems_rfs_buffer_data (&handle), 0xff, rtems_rfs_fs_block_size (fs));
374 
375      rtems_rfs_buffer_mark_dirty (&handle);
376    }
377  }
378 
379  rc = rtems_rfs_buffer_handle_close (fs, &handle);
380  if (rc > 0)
381  {
382    printf ("\nrtems-rfs: write-group: buffer handle close failed: %d: %s\n",
383            rc, strerror (rc));
384    return false;
385  }
386 
387  return true;
388}
389
390static bool
391rtems_rfs_write_superblock (rtems_rfs_file_system* fs)
392{
393  rtems_rfs_buffer_handle handle;
394  uint8_t*                sb;
395  int                     rc;
396
397  rc = rtems_rfs_buffer_handle_open (fs, &handle);
398  if (rc > 0)
399  {
400    printf ("rtems-rfs: write-superblock: handle open failed: %d: %s\n",
401            rc, strerror (rc));
402    return false;
403  }
404
405  rc = rtems_rfs_buffer_handle_request (fs, &handle, 0, false);
406  if (rc > 0)
407  {
408    rtems_rfs_buffer_handle_close (fs, &handle);
409    printf ("rtems-rfs: write-superblock: request failed: %d: %s\n",
410            rc, strerror (rc));
411    return false;
412  }
413
414  sb = rtems_rfs_buffer_data (&handle);
415 
416#define write_sb(_o, _d) rtems_rfs_write_u32(sb + (_o), _d)
417 
418  memset (sb, 0xff, rtems_rfs_fs_block_size (fs));
419
420  write_sb (RTEMS_RFS_SB_OFFSET_MAGIC, RTEMS_RFS_SB_MAGIC);
421  write_sb (RTEMS_RFS_SB_OFFSET_VERSION, RTEMS_RFS_VERSION);
422  write_sb (RTEMS_RFS_SB_OFFSET_BLOCKS, rtems_rfs_fs_blocks (fs));
423  write_sb (RTEMS_RFS_SB_OFFSET_BLOCK_SIZE, rtems_rfs_fs_block_size (fs));
424  write_sb (RTEMS_RFS_SB_OFFSET_BAD_BLOCKS, fs->bad_blocks);
425  write_sb (RTEMS_RFS_SB_OFFSET_MAX_NAME_LENGTH, fs->max_name_length);
426  write_sb (RTEMS_RFS_SB_OFFSET_GROUPS, fs->group_count);
427  write_sb (RTEMS_RFS_SB_OFFSET_GROUP_BLOCKS, fs->group_blocks);
428  write_sb (RTEMS_RFS_SB_OFFSET_GROUP_INODES, fs->group_inodes);
429  write_sb (RTEMS_RFS_SB_OFFSET_INODE_SIZE, RTEMS_RFS_INODE_SIZE);
430
431  rtems_rfs_buffer_mark_dirty (&handle);
432
433  rc = rtems_rfs_buffer_handle_release (fs, &handle);
434  if (rc > 0)
435  {
436    rtems_rfs_buffer_handle_close (fs, &handle);
437    printf ("rtems-rfs: write-superblock: buffer release failed: %d: %s\n",
438            rc, strerror (rc));
439    return false;
440  }
441
442  rc = rtems_rfs_buffer_handle_close (fs, &handle);
443  if (rc > 0)
444  {
445    printf ("rtems-rfs: write-superblock: buffer handle close failed: %d: %s\n",
446            rc, strerror (rc));
447    return false;
448  }
449 
450  return true;
451}
452
453static int
454rtems_rfs_write_root_dir (const char* name)
455{
456  rtems_rfs_file_system* fs;
457  rtems_rfs_inode_handle inode;
458  rtems_rfs_ino          ino;
459  int                    rc;
460
461  /*
462   * External API so returns -1.
463   */
464  rc = rtems_rfs_fs_open (name, NULL, RTEMS_RFS_FS_FORCE_OPEN, &fs);
465  if (rc < 0)
466  {
467    printf ("rtems-rfs: format: file system open failed: %d: %s\n",
468            errno, strerror (errno));
469    return -1;
470  }
471 
472  rc = rtems_rfs_inode_alloc (fs, RTEMS_RFS_ROOT_INO, &ino);
473  if (rc > 0)
474  {
475    printf ("rtems-rfs: format: inode allocation failed: %d: %s\n",
476            rc, strerror (rc));
477    rtems_rfs_fs_close (fs);
478    return rc;
479  }
480
481  if (ino != RTEMS_RFS_ROOT_INO)
482  {
483    printf ("rtems-rfs: format: allocated inode not root ino: %ld\n", ino);
484    rtems_rfs_fs_close (fs);
485    return rc;
486  }
487 
488  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
489  if (rc > 0)
490  {
491    printf ("rtems-rfs: format: inode open failed: %d: %s\n",
492            rc, strerror (rc));
493    rtems_rfs_group_bitmap_free (fs, true, ino);
494    rtems_rfs_fs_close (fs);
495    return rc;
496  }
497
498  rc = rtems_rfs_inode_initialise (&inode, 0,
499                                   (RTEMS_RFS_S_IFDIR | RTEMS_RFS_S_IRWXU |
500                                    RTEMS_RFS_S_IXGRP | RTEMS_RFS_S_IXOTH),
501                                   0, 0);
502  if (rc > 0)
503    printf ("rtems-rfs: format: inode initialise failed: %d: %s\n",
504            rc, strerror (rc));
505 
506  rc = rtems_rfs_dir_add_entry (fs, &inode, ".", 1, ino);
507  if (rc > 0)
508    printf ("rtems-rfs: format: directory add failed: %d: %s\n",
509            rc, strerror (rc));
510 
511  rc = rtems_rfs_inode_close (fs, &inode);
512  if (rc > 0)
513    printf ("rtems-rfs: format: inode close failed: %d: %s\n",
514            rc, strerror (rc));
515 
516  rc = rtems_rfs_fs_close (fs);
517  if (rc < 0)
518    printf ("rtems-rfs: format: file system close failed: %d: %s\n",
519            errno, strerror (errno));
520 
521  return rc;
522}
523
524int
525rtems_rfs_format (const char* name, const rtems_rfs_format_config* config)
526{
527  rtems_rfs_file_system fs;
528  int                   group;
529  int                   rc;
530
531  if (config->verbose)
532    printf ("rtems-rfs: format: %s\n", name);
533 
534  memset (&fs, 0, sizeof (rtems_rfs_file_system));
535
536  rtems_chain_initialize_empty (&fs.release);
537  rtems_chain_initialize_empty (&fs.release_modified);
538  rtems_chain_initialize_empty (&fs.file_shares);
539
540  fs.max_held_buffers = RTEMS_RFS_FS_MAX_HELD_BUFFERS;
541
542  fs.release_count = 0;
543  fs.release_modified_count = 0;
544
545  fs.flags = RTEMS_RFS_FS_NO_LOCAL_CACHE;
546 
547  /*
548   * Open the buffer interface.
549   */
550  rc = rtems_rfs_buffer_open (name, &fs);
551  if (rc > 0)
552  {
553    printf ("rtems-rfs: format: buffer open failed: %d: %s\n",
554            rc, strerror (rc));
555    return -1;
556  }
557
558  /*
559   * Check the media.
560   */
561  if (rtems_rfs_fs_media_block_size (&fs) == 0)
562  {
563    printf ("rtems-rfs: media block is invalid: %lu\n",
564            rtems_rfs_fs_media_block_size (&fs));
565    return -1;
566  }
567 
568  /*
569   * Check the configuration data.
570   */
571  if (!rtems_rfs_check_config (&fs, config))
572    return -1;
573
574  if (config->verbose)
575  {
576    printf ("rtems-rfs: format: media size = %llu\n",
577            rtems_rfs_fs_media_size (&fs));
578    printf ("rtems-rfs: format: media blocks = %ld\n",
579            rtems_rfs_fs_media_blocks (&fs));
580    printf ("rtems-rfs: format: media block size = %lu\n",
581            rtems_rfs_fs_media_block_size (&fs));
582    printf ("rtems-rfs: format: size = %llu\n",
583            rtems_rfs_fs_size (&fs));
584    printf ("rtems-rfs: format: blocks = %lu\n",
585            rtems_rfs_fs_blocks (&fs));
586    printf ("rtems-rfs: format: block size = %lu\n",
587            rtems_rfs_fs_block_size (&fs));
588    printf ("rtems-rfs: format: bits per block = %u\n",
589            rtems_rfs_bits_per_block (&fs));
590    printf ("rtems-rfs: format: inode size = %lu\n", RTEMS_RFS_INODE_SIZE);
591    printf ("rtems-rfs: format: inodes = %lu (%d.%d%%)\n",
592            fs.group_inodes * fs.group_count,
593            rtems_rfs_inode_overhead (&fs) / 10,
594            rtems_rfs_inode_overhead (&fs) % 10);
595    printf ("rtems-rfs: format: groups = %u\n", fs.group_count);
596    printf ("rtems-rfs: format: group blocks = %lu\n", fs.group_blocks);
597    printf ("rtems-rfs: format: group inodes = %lu\n", fs.group_inodes);
598  }
599
600  rc = rtems_rfs_buffer_setblksize (&fs, rtems_rfs_fs_block_size (&fs));
601  if (rc > 0)
602  {
603    printf ("rtems-rfs: format: setting block size failed: %d: %s\n",
604            rc, strerror (rc));
605    return -1;
606  }
607 
608  if (!rtems_rfs_write_superblock (&fs))
609  {
610    printf ("rtems-rfs: format: superblock write failed\n");
611    return -1;
612  }
613
614  for (group = 0; group < fs.group_count; group++)
615    if (!rtems_rfs_write_group (&fs, group,
616                                config->initialise_inodes, config->verbose))
617      return -1;
618
619  if (config->verbose)
620    printf ("\n");
621 
622  rc = rtems_rfs_buffer_close (&fs);
623  if (rc > 0)
624  {
625    printf ("rtems-rfs: format: buffer close failed: %d: %s\n",
626            rc, strerror (rc));
627    return -1;
628  }
629
630  rc = rtems_rfs_write_root_dir (name);
631  if (rc > 0)
632  {
633    printf ("rtems-rfs: format: writing root dir failed: %d: %s\n",
634            rc, strerror (rc));
635    return -1;
636  }
637 
638  return 0;
639}
Note: See TracBrowser for help on using the repository browser.