home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / id-utils-3.2-src.tgz / tar.out / fsf / id-utils / libidu / idwrite.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  5KB  |  170 lines

  1. /* idwrite.c -- functions to write ID database files
  2.    Copyright (C) 1995, 1996 Free Software Foundation, Inc.
  3.    Written by Greg McGary <gkm@gnu.ai.mit.edu>
  4.  
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 2, or (at your option)
  8.    any later version.
  9.  
  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.
  14.  
  15.    You should have received a copy of the GNU General Public License
  16.    along with this program; if not, write to the Free Software
  17.    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18. */
  19.  
  20. #include <config.h>
  21. #include "idfile.h"
  22. #include "hash.h"
  23. #include "xobstack.h"
  24. #include "xmalloc.h"
  25. #include "xnls.h"
  26. #include "error.h"
  27.  
  28. int file_link_qsort_compare __P((void const *x, void const *y));
  29.  
  30.  
  31. /****************************************************************************/
  32. /* Serialize and write a file_link hierarchy. */
  33.  
  34. void
  35. serialize_file_links (struct idhead *idhp)
  36. {
  37.   struct file_link **flinks_0;
  38.   struct file_link **flinks;
  39.   struct file_link **end;
  40.   struct file_link **parents_0;
  41.   struct file_link **parents;
  42.   unsigned long parent_index = 0;
  43.   int max_link = 0;
  44.  
  45.   flinks_0 = (struct file_link **) hash_dump (&idhp->idh_file_link_table,
  46.                           0, file_link_qsort_compare);
  47.   end = &flinks_0[idhp->idh_file_link_table.ht_fill];
  48.   parents = parents_0 = MALLOC (struct file_link *, idhp->idh_file_link_table.ht_fill);
  49.   for (flinks = flinks_0; flinks < end; flinks++)
  50.     {
  51.       struct file_link *flink = *flinks;
  52.       int name_length;
  53.  
  54.       if (!(flink->fl_flags & FL_USED))
  55.     break;
  56.       name_length = strlen (flink->fl_name);
  57.       if (name_length > max_link)
  58.     max_link = name_length;
  59.       io_write (idhp->idh_FILE, flink->fl_name, 0, IO_TYPE_STR);
  60.       io_write (idhp->idh_FILE, &flink->fl_flags, sizeof (flink->fl_flags), IO_TYPE_INT);
  61.       io_write (idhp->idh_FILE, (IS_ROOT_FILE_LINK (flink)
  62.                 ? &parent_index : &flink->fl_parent->fl_index),
  63.         FL_PARENT_INDEX_BYTES, IO_TYPE_INT);
  64.       *parents++ = flink->fl_parent; /* save parent link before clobbering */
  65.       flink->fl_index = parent_index++;
  66.     }
  67.   /* restore parent links */
  68.   for ((flinks = flinks_0), (parents = parents_0); flinks < end; flinks++)
  69.     {
  70.       struct file_link *flink = *flinks;
  71.       if (!(flink->fl_flags & FL_USED))
  72.     break;
  73.       flink->fl_parent = *parents++;
  74.     }
  75.   free (parents_0);
  76.   free (flinks_0);
  77.   idhp->idh_max_link = max_link + 1;
  78.   idhp->idh_file_links = parent_index;
  79.   idhp->idh_files = idhp->idh_member_file_table.ht_fill;
  80. }
  81.  
  82. /* Collation sequence:
  83.    - Used before unused.
  84.    - Among used: breadth-first (dirs before files, parent dirs before children)
  85.    - Among files: collate by mf_index.  */
  86.  
  87. int
  88. file_link_qsort_compare (void const *x, void const *y)
  89. {
  90.   struct file_link const *flx = *(struct file_link const *const *) x;
  91.   struct file_link const *fly = *(struct file_link const *const *) y;
  92.   unsigned int x_flags = flx->fl_flags;
  93.   unsigned int y_flags = fly->fl_flags;
  94.   int result;
  95.  
  96.   result = (y_flags & FL_USED) - (x_flags & FL_USED);
  97.   if (result)
  98.     return result;
  99.   if (!(x_flags & FL_USED))    /* If neither link is used, we don't care... */
  100.     return 0;
  101.   result = (y_flags & FL_TYPE_DIR) - (x_flags & FL_TYPE_DIR);
  102.   if (result)
  103.     return result;
  104.   result = (y_flags & FL_TYPE_MASK) - (x_flags & FL_TYPE_MASK);
  105.   if (result)
  106.     return result;
  107.   if (FL_IS_FILE (x_flags))
  108.     {
  109.       struct member_file *x_member = find_member_file (flx);
  110.       struct member_file *y_member = find_member_file (fly);
  111.       return x_member->mf_index - y_member->mf_index;
  112.     }
  113.   else
  114.     {
  115.       int x_depth = links_depth (flx);
  116.       int y_depth = links_depth (fly);
  117.       return (x_depth - y_depth);
  118.     }
  119. }
  120.  
  121.  
  122. /****************************************************************************/
  123.  
  124. int
  125. write_idhead (struct idhead *idhp)
  126. {
  127.   return io_idhead (idhp->idh_FILE, io_write, idhp);
  128. }
  129.  
  130. int
  131. io_write (FILE *output_FILE, void *addr, unsigned int size, int io_type)
  132. {
  133.   if (io_type == IO_TYPE_INT || size == 1)
  134.     {
  135.       switch (size)
  136.     {
  137.     case 4:
  138.       putc (*(unsigned long *)addr, output_FILE);
  139.       putc (*(unsigned long *)addr >> 010, output_FILE);
  140.       putc (*(unsigned long *)addr >> 020, output_FILE);
  141.       putc (*(unsigned long *)addr >> 030, output_FILE);
  142.       break;
  143.     case 3:
  144.       putc (*(unsigned long *)addr, output_FILE);
  145.       putc (*(unsigned long *)addr >> 010, output_FILE);
  146.       putc (*(unsigned long *)addr >> 020, output_FILE);
  147.       break;
  148.     case 2:
  149.       putc (*(unsigned short *)addr, output_FILE);
  150.       putc (*(unsigned short *)addr >> 010, output_FILE);
  151.       break;
  152.     case 1:
  153.       putc (*(unsigned char *)addr, output_FILE);
  154.       break;
  155.     default:
  156.       error (1, 0, _("unsupported size in io_write (): %d"), size);
  157.     }
  158.     }
  159.   else if (io_type == IO_TYPE_STR)
  160.     {
  161.       fputs (addr, output_FILE);
  162.       putc ('\0', output_FILE);
  163.     }
  164.   else if (io_type == IO_TYPE_FIX)
  165.     fwrite (addr, size, 1, output_FILE);
  166.   else
  167.     error (0, 0, _("unknown I/O type: %d"), io_type);
  168.   return size;
  169. }
  170.