2 * $Id: index.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 * Maintain an external index file for a WorkMan CD database.
26 * Uses the Berkeley libdb library, available from ftp.cs.berkeley.edu.
29 static char index_id
[] = "$Id: index.c,v 1.2 1999/02/14 09:50:42 dirk Exp $";
38 #include <netinet/in.h> /* for htonl() */
39 #include "include/wm_config.h"
40 #include "include/wm_index.h"
42 extern int suppress_locking
;
47 * Find an entry in the index file.
50 * file Name of database file (text version).
51 * ntracks Number of tracks on the CD we're looking for.
52 * tracks Array of track start times.
53 * len CD length in frames.
54 * fuzz Fuzz factor (tolerance value).
55 * pos Pointer to return value.
58 * 1 No matching record found.
59 * 0 Record found; *pos contains offset into text file.
60 * -1 Index file out of date or inaccessible, or another error.
63 idx_find_entry( char *file
, int ntracks
, int *tracks
,
64 int len
, int fuzz
, unsigned long *pos
)
67 char *indexname
= NULL
, keyval
[8];
75 * First, see if the text file is accessible. Lock it if so.
77 text
= fopen(file
, "r");
80 if ((c
= getc(text
)) == EOF
)
85 if (! suppress_locking
)
86 if (lockit(fileno(text
), F_RDLCK
))
93 * Open the index file.
95 indexname
= malloc(strlen(file
) + sizeof(".ind"));
96 if (indexname
== NULL
)
101 strcpy(indexname
, file
);
102 strcat(indexname
, ".ind");
105 bti
.minkeypage
= bti
.maxkeypage
= 0;
106 bti
.psize
= bti
.lorder
= 0;
109 index
= dbopen(indexname
, O_RDONLY
, 0666, DB_BTREE
, &bti
);
118 * Search for the first matching entry.
120 sprintf(keyval
, "%07d", tracks
[ntracks
- 1] - fuzz
);
123 if (c
= (index
->seq
)(index
, &key
, &data
, R_CURSOR
))
125 (index
->close
)(index
);
131 * Now loop through all the possible matches, collecting them into
135 char tracksline
[750], *s
;
138 /* Hit the end of the valid entries? */
139 sscanf(key
.data
, "%d", &val
);
140 if (val
> tracks
[ntracks
- 1] + fuzz
)
143 dbpos
= ntohl(*((unsigned long *) data
.data
));
144 if (fseek(text
, dbpos
, 0))
147 fgets(tracksline
, sizeof(tracksline
), text
);
148 if (strncmp(tracksline
, "tracks ", 7))
150 (void) strtok(tracksline
, " \t");
152 /* Got a valid tracks line. See if it matches the CD. */
153 s
= strtok(NULL
, " \t");
156 if (atoi(s
) != ntracks
)
159 for (i
= 0; i
< ntracks
; i
++)
161 s
= strtok(NULL
, " \t");
165 if (val
+ fuzz
< tracks
[i
] || val
- fuzz
> tracks
[i
])
171 s
= strtok(NULL
, " \t");
175 if (val
+ fuzz
/ 75 < len
/ 75 || val
+ fuzz
/ 75 > len
/ 75)
178 /* XXX - add to sorted list! */
180 (index
->close
)(index
);
183 } while ((c
= (index
->seq
)(index
, &key
, &data
, R_NEXT
)) == 0);
188 (index
->close
)(index
);
193 (index
->close
)(index
);
201 * Delete an entry from the index file.
204 * file Name of database file (text version).
205 * track Last track's start time (database key).
206 * fuzz Fuzz factor (tolerance value).
207 * pos Position of CD in database file.
210 * 1 No matching record found.
212 * -1 Index file out of date or inaccessible, or another error.
214 * Note: it is the caller's responsibility to do locking, as it's assumed
215 * that this operation will accompany a modification of the main database
216 * file and will need to be atomic with that modification.
219 idx_delete_entry(char *file
, int track
, int fuzz
, unsigned long pos
)
222 char *indexname
= NULL
, keyval
[8];
229 * Open the index file.
231 indexname
= malloc(strlen(file
) + sizeof(".ind"));
232 if (indexname
== NULL
)
235 strcpy(indexname
, file
);
236 strcat(indexname
, ".ind");
240 bti
.minkeypage
= bti
.maxkeypage
= 0;
241 bti
.psize
= bti
.lorder
= 0;
244 index
= dbopen(indexname
, O_RDWR
, 0666, DB_BTREE
, &bti
);
250 * Search for the first matching entry.
252 sprintf(keyval
, "%07d", track
- fuzz
);
255 if (c
= (index
->seq
)(index
, &key
, &data
, R_CURSOR
))
260 (index
->close
)(index
);
265 * Look for the entry the user wants to delete.
270 /* Hit the end of the valid entries? */
271 sscanf(key
.data
, "%d", &val
);
272 if (val
> track
+ fuzz
)
275 /* Is this the entry we want? */
276 if (pos
== ntohl(*((unsigned long *) data
.data
)))
281 status
= (index
->del
)(index
, &key
, R_CURSOR
);
282 (index
->close
)(index
);
285 } while ((c
= (index
->seq
)(index
, &key
, &data
, R_NEXT
)) == 0);
290 (index
->close
)(index
);
294 (index
->close
)(index
);
301 * Write out an index file entry.
304 * file Name of database file (text version).
305 * track Start time of last track (database key).
306 * pos Position of entry in text file.
310 * -1 Index file inaccessible, or another error.
312 * Note: it is the caller's responsibility to do locking, as it's assumed
313 * that this operation will accompany a modification of the main database
314 * file and will need to be atomic with that modification.
317 idx_write_entry( char *file
, int track
, unsigned long pos
)
319 char *indexname
, keyval
[8];
326 * Open the index file.
328 indexname
= malloc(strlen(file
) + sizeof(".ind"));
329 if (indexname
== NULL
)
332 strcpy(indexname
, file
);
333 strcat(indexname
, ".ind");
340 bti
.lorder
= 4321; /* network byte order */
343 index
= dbopen(indexname
, O_RDWR
, 0666, DB_BTREE
, &bti
);
349 * Create a new key and value.
353 data
.size
= sizeof(pos
);
357 sprintf(keyval
, "%07d", track
);
359 status
= (index
->put
)(index
, &key
, &data
, 0);
361 (index
->close
)(index
);
370 return (1); /* no record found; text file will be searched. */