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