1 /* idfile.c -- read & write mkid database file header
2    Copyright (C) 1986, 1995-1996, 1999-2000, 2007-2012 Free Software
3    Foundation, Inc.
4    Written by Greg McGary <gkm@gnu.ai.mit.edu>
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3, or (at your option)
9    any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include <config.h>
21 #include <stdio.h>
22 #include <errno.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <obstack.h>
26 #include <error.h>
27 #include <sys/stat.h>
28 
29 #include "idfile.h"
30 #include "xalloc.h"
31 #include "xnls.h"
32 
33 static int io_size (FILE *, void *, unsigned int size, int);
34 
35 /****************************************************************************/
36 
37 /* Discover the name of the ID file.  If ARG is NULL, consult $IDPATH.
38    If $IDPATH is undefined, default to "ID".  If the candidate file
39    name is relative, search successive ancestor directories until the
40    file is found or we reach the root.  If we find it, return the
41    relative file name, otherwise return NULL.  */
42 
43 char const *
locate_id_file_name(char const * arg)44 locate_id_file_name (char const *arg)
45 {
46   static char file_name_buffer[BUFSIZ];
47   char *buf = file_name_buffer;
48   char *id_path = 0;
49   struct stat rootb;
50   struct stat statb;
51 
52   if (arg == 0)
53     {
54       id_path = getenv ("IDPATH");
55       if (id_path)
56 	{
57 	  id_path = xstrdup (id_path);
58 	  arg = strsep (&id_path, ":");
59 	  /* FIXME: handle multiple ID file names */
60 	}
61     }
62   if (arg == 0)
63     arg = DEFAULT_ID_FILE_NAME;
64 
65   /* if we got absolute name, just use it. */
66   if (arg[0] == '/')
67     return arg;
68   /* if the name we were give exists, don't bother searching */
69   if (stat (arg, &statb) == 0)
70     return arg;
71   /* search up the tree until we find a directory where this
72 	 * relative file name is visible.
73 	 * (or we run out of tree to search by hitting root).
74 	 */
75 
76   if (stat ("/", &rootb) != 0)
77     return NULL;
78   do
79     {
80       strcpy (buf, "../");
81       buf += 3;
82       strcpy (buf, arg);
83       if (stat (file_name_buffer, &statb) == 0)
84 	return file_name_buffer;
85       *buf = '\0';
86       if (stat (file_name_buffer, &statb) != 0)
87 	return NULL;
88     }
89   while (statb.st_ino != rootb.st_ino || statb.st_dev != rootb.st_dev);
90   return NULL;
91 }
92 
93 
94 /****************************************************************************/
95 
96 int
sizeof_idhead(void)97 sizeof_idhead (void)
98 {
99   return io_idhead (0, io_size, 0);
100 }
101 
102 static int
io_size(FILE * ignore_FILE,void * ignore_addr,unsigned int size,int io_type)103 io_size (FILE *ignore_FILE, void *ignore_addr, unsigned int size, int io_type)
104 {
105   if (io_type == IO_TYPE_STR)
106     error (0, 0, _("can't determine the io_size of a string!"));
107   return size;
108 }
109 
110 /* The sizes of the fields must be hard-coded.  They aren't
111    necessarily the sizes of the struct members, because some
112    architectures don't have any way to declare 4-byte integers
113    (e.g., Cray) */
114 
115 int
io_idhead(FILE * fp,io_func_t iof,struct idhead * idhp)116 io_idhead (FILE *fp, io_func_t iof, struct idhead *idhp)
117 {
118   unsigned int size = 0;
119   unsigned char pad = 0;
120   if (fp)
121     fseek (fp, 0L, 0);
122   size += iof (fp, idhp->idh_magic, 2, IO_TYPE_FIX);
123   size += iof (fp, &pad, 1, IO_TYPE_FIX);
124   size += iof (fp, &idhp->idh_version, 1, IO_TYPE_FIX);
125   size += iof (fp, &idhp->idh_flags, 2, IO_TYPE_INT);
126   size += iof (fp, &idhp->idh_file_links, 4, IO_TYPE_INT);
127   size += iof (fp, &idhp->idh_files, 4, IO_TYPE_INT);
128   size += iof (fp, &idhp->idh_tokens, 4, IO_TYPE_INT);
129   size += iof (fp, &idhp->idh_buf_size, 4, IO_TYPE_INT);
130   size += iof (fp, &idhp->idh_vec_size, 4, IO_TYPE_INT);
131   size += iof (fp, &idhp->idh_tokens_offset, 4, IO_TYPE_INT);
132   size += iof (fp, &idhp->idh_flinks_offset, 4, IO_TYPE_INT);
133   size += iof (fp, &idhp->idh_end_offset, 4, IO_TYPE_INT);
134   size += iof (fp, &idhp->idh_max_link, 2, IO_TYPE_INT);
135   size += iof (fp, &idhp->idh_max_path, 2, IO_TYPE_INT);
136   return size;
137 }
138