wmail: change "!stat(...) == 0" to "stat(...) == -1"
[dockapps.git] / ascd / libworkman / buildindex.c
blobac49c125d881ba789b513a582e31a37f2bf5e9d6
1 /*
2 * $Id: buildindex.c,v 1.2 1999/02/14 09:50:42 dirk Exp $
4 * This file is part of WorkMan, the civilized CD player library
5 * (c) 1991-1997 by Steven Grimm (original author)
6 * (c) by Dirk Försterling (current 'author' = maintainer)
7 * The maintainer can be contacted by his e-mail address:
8 * milliByte@DeathsDoor.com
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
20 * You should have received a copy of the GNU Library General Public
21 * License along with this library; if not, write to the Free
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 * Build a WorkMan database index file from a flat text file. Requires
26 * 4.4BSD libdb library.
29 static char buildindex_id[] = "$Id: buildindex.c,v 1.2 1999/02/14 09:50:42 dirk Exp $";
31 #include <stdio.h>
32 #include <db.h>
33 #include <fcntl.h>
34 #include <errno.h>
35 #include <netinet/in.h> /* for htonl() */
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/stat.h>
39 #include <unistd.h>
41 static char buildindex_id[]="$Id: buildindex.c,v 1.2 1999/02/14 09:50:42 dirk Exp $";
43 char *strrchr();
45 main(argc, argv)
46 int argc;
47 char **argv;
49 DB *db;
50 DBT key, data;
51 FILE *fp;
52 int lock = 1, i = 0, locked, frame;
53 char buf[1000], indname[MAXPATHLEN + 100], framebuf[8], *c;
54 unsigned long pos;
55 BTREEINFO bt;
56 struct stat st;
58 if (argc > 2 && !strcmp(argv[1], "-n"))
60 lock = 0;
61 i++;
64 if (argc < i + 2)
66 fprintf(stderr, "Usage: %s [-n] dbfile [dbfile ...]\n",
67 argv[0]);
68 exit(1);
71 data.data = &pos;
72 data.size = sizeof(pos);
73 key.data = framebuf;
74 key.size = 7; /* %07d */
76 while (++i < argc)
78 fprintf(stderr, "Building index for %s\n", argv[i]);
80 if ((fp = fopen(argv[i], "r")) == NULL)
82 perror(argv[i]);
83 continue;
87 * Figure out the file's mode, uid, gid, so we can set the
88 * permissions on the index file to the same thing.
90 if (fstat(fileno(fp), &st))
92 sprintf(indname, "%s: fstat", argv[i]);
93 perror(indname);
94 fclose(fp);
95 continue;
98 if (lock && lockit(fileno(fp), F_WRLCK))
100 sprintf(indname, "%s: Warning: Couldn't lock", argv[i]);
101 perror(indname);
102 locked = 0;
104 else
105 locked = 1;
108 * Create a database file.
110 bt.flags = R_DUP; /* allow duplicate keys */
111 bt.cachesize = 0;
112 bt.psize = 0;
113 bt.lorder = 4321;
114 bt.minkeypage = 0;
115 bt.compare = NULL; /* use lexical comparison */
116 bt.prefix = NULL; /* no prefix comparisons */
118 /* Index files have ".ind" extensions */
119 sprintf(indname, "%s.ind", argv[i]);
120 if ((db = dbopen(indname, O_CREAT | O_RDWR | O_TRUNC,
121 st.st_mode, DB_BTREE, &bt)) == NULL)
123 perror(indname);
124 if (locked)
125 lockit(fileno(fp), F_UNLCK);
126 fclose(fp);
127 continue;
131 * Now loop through the text file, inserting a record into
132 * the index file for each "tracks" line.
134 while (! feof(fp))
136 pos = ftell(fp);
137 buf[0] = '\0';
138 if (fgets(buf, sizeof(buf), fp) == NULL || ! buf[0])
140 /* End of file? */
141 if (feof(fp))
142 break;
144 /* Nope. A read error. Unlink the database. */
145 perror(argv[i]);
146 (void) unlink(indname);
147 break;
150 if (strncmp(buf, "tracks ", 7))
151 continue;
154 * Found the start of a record. Figure out the start
155 * time of the last track and put an entry in the
156 * index file with that as the key.
158 c = strrchr(buf, ' '); /* this will always succeed */
159 *c = '\0';
160 c = strrchr(buf, ' '); /* this should too, but... */
161 if (c == NULL)
163 fprintf(stderr,
164 "%s: Malformed tracks line at %lu\n",
165 argv[i], pos);
166 continue;
168 sscanf(c+1, "%d", &frame);
169 sprintf(framebuf, "%07d", frame);
170 pos = htonl(pos);
172 if ((db->put)(db, &key, &data, 0))
174 perror(indname);
175 unlink(indname);
176 break;
181 * Clean up.
183 (void) (db->close)(db);
184 if (locked)
185 lockit(fileno(fp), F_UNLCK);
190 * Lock a file. Time out after a little while if we can't get a lock;
191 * this usually means the locking system is broken.
193 * Unfortunately, if there are lots of people contending for a lock,
194 * this can result in the file not getting locked when it probably should.
197 lockit(fd, type)
198 int fd;
199 int type;
201 struct flock fl;
202 int result, timer = 0;
204 fl.l_type = type;
205 fl.l_whence = 0;
206 fl.l_start = 0;
207 fl.l_len = 0;
209 while ((result = fcntl(fd, F_SETLK, &fl)) < 0)
211 if (errno != EACCES || errno != EAGAIN)
212 break;
213 if (timer++ == 30)
215 errno = ETIMEDOUT;
216 break;
219 sleep(1);
222 return (result);