home *** CD-ROM | disk | FTP | other *** search
- /*
- * (c) Copyright 1990, Kim Fabricius Storm. All rights reserved.
- *
- * Database access and update
- */
-
- #include "config.h"
- #include "db.h"
-
- import char
- *master_directory, *db_directory, *db_data_directory, *news_directory;
-
- export master_header master;
- export group_header *active_groups = NULL;
- export group_header **sorted_groups = NULL;
-
- export int reread_groups_file = 0; /* nnmaster -G */
-
- export data_header db_hdr;
- export data_dynamic_data db_data;
-
- export int32 db_read_counter = 0; /* articles read by db_read_art */
- export int32 db_write_counter = 0; /* articles written by db_write_art */
-
- /*
- * Init access to a group
- */
-
- export group_header *current_group = NULL;
-
- export char group_path_name[FILENAME];
- export char *group_file_name = NULL;
-
- static char *group_position = NULL;
- static article_number current_digest_article = 0;
-
- init_group(gh)
- register group_header *gh;
- {
- register char *p, *q;
-
- current_digest_article = 0;
-
- if (gh == NULL) return 0;
- if (gh->master_flag & M_IGNORE_GROUP) return 0;
- if (gh == current_group) return 1;
-
- current_group = gh;
-
- if (gh->group_flag & G_FOLDER) {
- group_position = NULL;
- group_file_name = NULL;
- strcpy(group_path_name, gh->group_name);
- return 1;
- }
-
- #ifdef NNTP
- if (use_nntp && nntp_set_group(gh) < 0)
- return 0;
- #endif /* NNTP */
-
- if (group_position == NULL)
- if (who_am_i == I_AM_MASTER || who_am_i == I_AM_EXPIRE)
- group_position = group_path_name;
- else {
- strcpy(group_path_name, news_directory);
- group_position = group_path_name + strlen(group_path_name);
- *group_position++ = '/';
- }
-
- for (p = group_position, q = gh->group_name; *q; q++)
- *p++ = (*q == '.') ? '/' : *q;
-
- if (who_am_i == I_AM_MASTER) {
-
- /* The master will chdir to the group's directory to get */
- /* better performance (can use relative path names). */
-
- *p++ = NUL;
-
- if (!use_nntp) {
- if (chdir(news_directory) < 0)
- sys_error(news_directory);
-
- if (chdir(group_path_name) < 0)
- return 0;
- }
- group_file_name = group_path_name;
- return 1;
- }
-
- /* client */
- if (gh->master_flag & M_NO_DIRECTORY) return 0;
-
- *p++ = '/';
- *p = NUL;
- group_file_name = p;
- return 1;
- }
-
- /*
- * Open master & group file; read it in if first open.
- *
- * GROUPS file format is:
- *
- * One line per group:
- * <group name> [<space><timestamp>] [<space><options>] <NL>
- * If <timestamp> is omitted, a timestamp of 0 is used (very old group).
- * If <group name> is "@", the master entry is ignored.
- *
- * <options>:
- * D Digest all articles in the group
- * N Never digest articles
- * @ Bogus group, ignore completely
- * ! Don't collect this group
- *
- * Do not edit the GROUPS file while nnmaster is running.
- * After editing the groups file (options), run nnmaster -G.
- */
-
- static FILE *group_file = NULL;
-
- open_groups(mode)
- int mode;
- {
- group_file = open_file(relative(db_directory, "GROUPS"), mode);
-
- if (group_file != NULL && (mode & OPEN_CREATE)) {
- fprintf(group_file,
- "#\n#\tRUN 'nnmaster -G' AFTER MODIFYING THIS FILE\n");
- fprintf(group_file,
- "#\n#\tDO NOT REMOVE OR REORDER ANY LINES IN THIS FILE\n#\n");
- }
-
- return group_file != NULL;
- }
-
- close_groups()
- {
- if (group_file != NULL) {
- fclose(group_file);
- group_file = NULL;
- }
- }
-
- db_append_group(gh)
- register group_header *gh;
- {
- char flags[16], *fp;
- int was_open = (group_file != NULL);
-
- if (!was_open) open_groups(OPEN_UPDATE|MUST_EXIST);
-
- fseek(group_file, (off_t)0, 2);
- if (gh->group_name[0] == NUL) {
- fputc('@', group_file);
- goto out;
- }
-
- fprintf(group_file, "%s", gh->group_name);
- if (gh->creation_time > 0)
- fprintf(group_file, " %ld", (long)(gh->creation_time));
-
- fp = flags;
-
- if (gh->master_flag & M_IGNORE_G)
- *fp++ = '!';
- if (gh->master_flag & M_ALWAYS_DIGEST)
- *fp++ = 'D';
- if (gh->master_flag & M_NEVER_DIGEST)
- *fp++ = 'N';
- if (gh->master_flag & M_INCLUDE_OLD)
- *fp++ = 'O';
- if (gh->master_flag & M_AUTO_RECOLLECT)
- *fp++ = 'R';
- if (gh->archive_file != NULL)
- *fp++ = '>';
-
- if (fp != flags) {
- *fp++ = NUL;
- fprintf(group_file, " %s%s", flags,
- gh->archive_file != NULL ? gh->archive_file : "");
- }
-
- out:
- fputc(NL, group_file);
- fflush(group_file);
-
- if (!was_open) close_groups();
- }
-
- static char *mk_archive_file(gh, cp, logerr)
- register group_header *gh;
- register char *cp;
- int logerr;
- {
- char *name;
-
- while (*cp && (*cp == '>' || isspace(*cp))) cp++;
-
- name = cp;
- while (*cp && !isspace(*cp)) cp++;
- if (*cp) *cp++ = NUL;
- if (*name) {
- gh->archive_file = copy_str(name);
-
- if (*name == '/')
- gh->master_flag |= M_AUTO_ARCHIVE;
- else {
- gh->master_flag &= ~M_AUTO_ARCHIVE;
- if (who_am_i == I_AM_MASTER)
- if (logerr)
- log_entry('E', "GROUPS %s >%s: Full path required",
- gh->group_name, name);
- else
- printf("Error in GROUPS: %s >%s: Full path required\n",
- gh->group_name, name);
- }
- }
-
- return cp;
- }
-
- db_parse_group(gh, trust_master)
- register group_header *gh;
- int trust_master; /* trust what is in the master file */
- {
- char line[256];
- register char *cp, *name;
- int ignore;
-
- do {
- if (fgets(line, 256, group_file) == NULL) return 0;
- for (cp = line; *cp && isspace(*cp); cp++);
- } while (*cp == NUL || *cp == '#');
-
- gh->archive_file = NULL;
-
- name = cp;
-
- if (trust_master) {
- cp = name + gh->group_name_length;
- } else {
- /* parse GROUPS line */
-
- if (*cp == '@') {
- ignore = 1;
- gh->group_name_length = 0;
- gh->group_name = "";
- goto ignore_group;
- }
-
- if (gh->group_name_length == 0) {
- while (*cp && !isspace(*cp)) cp++;
- gh->group_name_length = cp - name;
- } else {
- cp = name + gh->group_name_length;
- if (*cp == NUL || !isspace(*cp)) {
- sys_error("MASTER/GROUPS conflict: %d/%s", gh->group_num, line);
- }
- }
- }
-
- if (*cp) *cp++ = NUL;
- if (gh->group_name_length > 0)
- gh->group_name = copy_str(name);
- else
- gh->group_name = "";
-
- if (trust_master) {
- if (gh->master_flag & M_AUTO_ARCHIVE) {
- while (*cp && *cp != '>') cp++;
- if (*cp == '>') cp = mk_archive_file(gh, cp, 1);
- }
- return 1;
- }
-
- while (*cp && isspace(*cp)) cp++;
-
- if (*cp && isdigit(*cp)) {
- gh->creation_time = atol(cp);
- while (*cp && isdigit(*cp)) cp++;
- } else
- gh->creation_time = 0;
-
- while (*cp && isspace(*cp)) cp++;
-
- ignore = 0;
- gh->master_flag &= ~(M_ALWAYS_DIGEST | M_NEVER_DIGEST |
- M_AUTO_RECOLLECT | M_AUTO_ARCHIVE);
-
- while (*cp) {
- switch (*cp++) {
- case ' ':
- case '\t':
- case NL:
- case CR:
- continue;
-
- case 'D': /* Collect this group, digest all articles */
- gh->master_flag |= M_ALWAYS_DIGEST;
- continue;
-
- case 'N': /* Collect this group, never digest articles */
- gh->master_flag |= M_NEVER_DIGEST;
- continue;
-
- case 'O': /* Ignore -O option for this group */
- gh->master_flag |= M_INCLUDE_OLD;
- continue;
-
- case 'R': /* Recollect this group when new articles arrive */
- gh->master_flag |= M_AUTO_RECOLLECT;
- continue;
-
- case '>': /* Archive all new articles in gh->archive_file */
- cp = mk_archive_file(gh, cp, 0);
- continue;
-
- case '@': /* Bogus GROUP -- ignore completely */
- ignore = 1;
- gh->group_name_length = 0;
- break;
-
- case '!': /* Do not collect this group */
- case 'X':
- ignore = 1;
- break;
-
- case '#': /* comment */
- *cp = NUL;
- break;
-
- default:
- printf("Bad GROUPS flag for %s: `%c'\n", gh->group_name, *--cp);
- break;
- }
- break;
- }
-
- ignore_group:
-
- /* G_DONE indicates to master that the group must be cleaned */
-
- if (ignore) {
- if ((gh->master_flag & M_IGNORE_GROUP) == 0) {
- gh->master_flag |= M_MUST_CLEAN;
- log_entry('X', "Group %s ignored", gh->group_name);
- }
- gh->master_flag |= M_IGNORE_G;
- } else { /* was group ignored in GROUPS, but not active before? */
- if ((gh->master_flag & M_IGNORE_GROUP) == M_IGNORE_G) {
- gh->master_flag &= ~M_NO_DIRECTORY;
- log_entry('X', "Group %s activated", gh->group_name);
- }
- gh->master_flag &= ~M_IGNORE_G;
- }
-
- return 1;
- }
-
- /*
- * Open master & group files; read then in if first open.
- */
-
- static FILE *master_file = NULL;
- static int db_sequential = 0;
-
- open_master(mode)
- int mode;
- {
- register group_header *gh;
- int trust_master;
-
- close_master();
-
- master_file = open_file(relative(db_directory, "MASTER"), mode|MUST_EXIST);
-
- db_sequential = 0;
- if (mode == OPEN_CREATE) db_sequential = 1;
-
- if (mode != OPEN_READ) return;
-
- db_read_master();
-
- if (who_am_i != I_AM_MASTER && master.db_lock[0]) {
- printf("DATABASE LOCKED.\n%s\n", master.db_lock);
- nn_exit(88);
- }
-
- freeobj(sorted_groups);
- freeobj(active_groups);
- active_groups = NULL;
- sorted_groups = NULL;
-
- db_expand_master();
-
- open_groups(OPEN_READ|MUST_EXIST);
-
- trust_master = (who_am_i != I_AM_MASTER || !reread_groups_file);
-
- db_sequential = 1;
- Loop_Groups_Header(gh) {
- gh->group_num = l_g_index;
- db_read_group(gh);
- db_parse_group(gh, trust_master);
- }
- db_sequential = 0;
-
- close_groups();
-
- sort_groups();
- }
-
- db_expand_master()
- {
- master.free_groups = 20;
-
- active_groups = resizeobj(active_groups, group_header,
- master.number_of_groups + master.free_groups);
- sorted_groups = resizeobj(sorted_groups, group_header *,
- master.number_of_groups + master.free_groups);
- }
-
- close_master()
- {
- if (master_file != NULL) {
- fclose(master_file);
- master_file = NULL;
- }
- }
-
- update_group(gh)
- group_header *gh;
- {
- group_number numg;
-
- numg = master.number_of_groups;
- db_read_master();
- master.number_of_groups = numg;
- if (master.db_lock[0]) return -3;
-
- db_read_group(gh);
-
- if (gh->master_flag & M_IGNORE_GROUP) return 0;
- if (gh->master_flag & M_BLOCKED) return -1;
-
- return 1;
- }
-
-
- static sort_gh(g1, g2)
- group_header **g1, **g2;
- {
- return strcmp((*g1)->group_name, (*g2)->group_name);
- }
-
-
- sort_groups()
- {
- register group_header *gh;
-
- Loop_Groups_Header(gh)
- sorted_groups[l_g_index] = gh;
-
- quicksort(sorted_groups, master.number_of_groups, group_header *, sort_gh);
-
- s_g_first = 0;
- Loop_Groups_Sorted(gh)
- if (gh->group_name[0] != NUL) {
- s_g_first = l_g_index;
- break;
- }
- }
-
-
- group_header *lookup_no_alias(name)
- char *name;
- {
- register i, j, k, t;
-
- i = s_g_first; j = master.number_of_groups - 1;
-
- while (i <= j) {
- k = (i + j) / 2;
-
- if ( (t=strcmp(name, sorted_groups[k]->group_name)) > 0)
- i = k+1;
- else
- if (t < 0)
- j = k-1;
- else
- return sorted_groups[k];
- }
-
- return NULL;
- }
-
- group_header *lookup(name)
- char *name;
- {
- register group_header *gh;
-
- gh = lookup_no_alias(name);
- if (gh == NULL || (gh->master_flag & M_ALIASED) == 0) return gh;
-
- do
- gh = &active_groups[gh->data_write_offset];
- while (gh->master_flag & M_ALIASED);
-
- return gh;
- }
-
- art_collected(gh, art_num)
- group_header *gh;
- article_number art_num;
- {
- return gh->first_db_article <= art_num && gh->last_db_article >= art_num;
- }
-
- char *db_data_path(namebuf, gh, d_or_x)
- char *namebuf;
- group_header *gh;
- char d_or_x;
- {
- register char *cp, *np;
-
- if (db_data_directory != NULL) {
- #ifdef DB_LONG_NAMES
- sprintf(namebuf, "%s/%s.%c", db_data_directory, gh->group_name, d_or_x);
- #else
- sprintf(namebuf, "%s/%d.%c", db_data_directory, gh->group_num, d_or_x);
- #endif
- } else {
- np = namebuf;
- /* master chdir to the group's directory */
- if (who_am_i != I_AM_MASTER) {
- for (cp = news_directory; *np = *cp++; np++);
- *np++ = '/';
- for (cp = gh->group_name; *cp; cp++)
- *np++ = *cp == '.' ? '/' : *cp;
- *np++ = '/';
- }
-
- *np++ = '.';
- *np++ = 'n';
- *np++ = 'n';
- *np++ = d_or_x;
- *np++ = NUL;
- }
-
- return namebuf;
- }
-
-
- FILE *open_data_file(gh, d_or_x, mode)
- group_header *gh;
- char d_or_x;
- int mode;
- {
- char data_file[FILENAME];
-
- db_data_path(data_file, gh, d_or_x);
-
- if (mode == -1) {
- unlink(data_file);
- return (FILE *)NULL;
- } else
- return open_file(data_file, mode);
- }
-
-
- #ifdef NETWORK_DATABASE
-
- #define MASTER_FIELDS 5 /* + DB_LOCK_MESSAGE bytes */
- #define GROUP_FIELDS 9
- #define ARTICLE_FIELDS 10
-
-
- typedef int32 net_long;
-
-
- #ifdef NETWORK_BYTE_ORDER
-
- #define net_to_host(buf, n)
- #define host_to_net(buf, n)
-
- #else
-
- static net_to_host(buf, lgt)
- register net_long *buf;
- int lgt;
- {
- while (--lgt >= 0) {
- *buf = ntohl(*buf);
- buf++;
- }
- }
-
- static host_to_net(buf, lgt)
- register net_long *buf;
- int lgt;
- {
- while (--lgt >= 0) {
- *buf = htonl(*buf);
- buf++;
- }
- }
- #endif /* not NETWORK_BYTE_ORDER */
- #endif /* NETWORK_DATABASE */
-
- #define NWDB_MAGIC 0x00190000 /* NN#n <-> NW#n */
-
- db_read_master()
- {
- #ifdef NETWORK_DATABASE
- net_long buf[MASTER_FIELDS];
-
- rewind(master_file);
- if (fread((char *)buf, sizeof(net_long), MASTER_FIELDS, master_file)
- != MASTER_FIELDS) goto err;
- if (fread(master.db_lock, sizeof(char), DB_LOCK_MESSAGE, master_file)
- != DB_LOCK_MESSAGE) goto err;
-
- net_to_host(buf, MASTER_FIELDS);
-
- master.db_magic = buf[0] ^ NWDB_MAGIC;
- master.last_scan = buf[1];
- master.last_size = buf[2];
- master.number_of_groups = buf[3];
- master.db_created = buf[4];
-
- #else
- rewind(master_file);
- if (fread((char *)&master, sizeof(master_header), 1, master_file) != 1)
- goto err;
- #endif
-
- if (master.db_magic != NNDB_MAGIC)
- sys_error("Database magic number mismatch");
- return;
-
- err:
- sys_error("Incomplete MASTER file");
- }
-
-
- db_write_master()
- {
- #ifdef NETWORK_DATABASE
- net_long buf[MASTER_FIELDS];
-
- buf[0] = master.db_magic ^ NWDB_MAGIC;
- buf[1] = master.last_scan;
- buf[2] = master.last_size;
- buf[3] = master.number_of_groups;
- buf[4] = master.db_created;
-
- host_to_net(buf, MASTER_FIELDS);
- rewind(master_file);
- if (fwrite((char *)buf, sizeof(net_long), MASTER_FIELDS, master_file)
- != MASTER_FIELDS) goto err;
- if (fwrite(master.db_lock, sizeof(char), DB_LOCK_MESSAGE, master_file)
- != DB_LOCK_MESSAGE) goto err;
- #else
- rewind(master_file);
- if (fwrite((char *)&master, sizeof(master_header), 1, master_file) != 1)
- goto err;
- #endif
-
- fflush(master_file);
- return;
-
- err:
- sys_error("Write to MASTER failed");
- }
-
- db_read_group(gh)
- register group_header *gh;
- {
- #ifdef NETWORK_DATABASE
- net_long buf[GROUP_FIELDS];
-
- if (!db_sequential)
- fseek(master_file,
- (off_t)(MASTER_FIELDS * sizeof(net_long) + DB_LOCK_MESSAGE +
- GROUP_FIELDS * sizeof(net_long) * gh->group_num), 0);
-
- if (fread((char *)buf, sizeof(net_long), GROUP_FIELDS, master_file) != GROUP_FIELDS)
- goto err;
-
- net_to_host(buf, GROUP_FIELDS);
-
- gh->first_db_article = buf[0];
- gh->last_db_article = buf[1];
- gh->index_write_offset = buf[2];
- gh->data_write_offset = buf[3];
- gh->group_name_length = buf[4];
- gh->master_flag = buf[5];
- gh->first_a_article = buf[6];
- gh->last_a_article = buf[7];
- gh->creation_time = buf[8];
- #else
-
- if (!db_sequential)
- fseek(master_file,
- (off_t)(sizeof(master_header) + SAVED_GROUP_HEADER_SIZE(*gh) * gh->group_num), 0);
-
- if (fread((char *)gh, SAVED_GROUP_HEADER_SIZE(*gh), 1, master_file) != 1)
- goto err;
-
- #endif
- return;
-
- err:
- sys_error("Read GROUPS failed");
- }
-
-
- db_write_group(gh)
- register group_header *gh;
- {
- #ifdef NETWORK_DATABASE
- net_long buf[GROUP_FIELDS];
-
- if (!db_sequential)
- fseek(master_file,
- (off_t)(MASTER_FIELDS * sizeof(net_long) + DB_LOCK_MESSAGE +
- GROUP_FIELDS * sizeof(net_long) * gh->group_num), 0);
-
- buf[0] = gh->first_db_article;
- buf[1] = gh->last_db_article;
- buf[2] = gh->index_write_offset;
- buf[3] = gh->data_write_offset;
- buf[4] = gh->group_name_length;
- buf[5] = gh->master_flag;
- buf[6] = gh->first_a_article;
- buf[7] = gh->last_a_article;
- buf[8] = gh->creation_time;
-
- host_to_net(buf, GROUP_FIELDS);
- if (fwrite((char *)buf, sizeof(net_long), GROUP_FIELDS, master_file) != GROUP_FIELDS)
- goto err;
- #else
- if (!db_sequential)
- fseek(master_file, (off_t)(sizeof(master_header) + SAVED_GROUP_HEADER_SIZE(*gh) * gh->group_num), 0);
-
- if (fwrite((char *)gh, SAVED_GROUP_HEADER_SIZE(*gh), 1, master_file) != 1)
- goto err;
- #endif
- fflush(master_file);
- return;
-
- err:
- sys_error("Write GROUPS failed");
- }
-
- db_read_art(f)
- FILE *f;
- {
- #ifdef NETWORK_DATABASE
- net_long buf[ARTICLE_FIELDS];
-
- if (fread((char *)buf, sizeof(net_long), ARTICLE_FIELDS, f) != ARTICLE_FIELDS)
- return 0;
-
- net_to_host(buf, ARTICLE_FIELDS);
-
- db_hdr.dh_number = buf[0];
- db_hdr.dh_date = buf[1];
- db_hdr.dh_hpos = buf[2];
- db_hdr.dh_lpos = buf[3];
- db_hdr.dh_fpos = buf[4];
- db_hdr.dh_lines = buf[5];
- db_hdr.dh_replies = buf[6];
- db_hdr.dh_cross_postings = buf[7];
- db_hdr.dh_subject_length = buf[8];
- db_hdr.dh_sender_length = buf[9];
- #else
- if (fread((char *)&db_hdr, sizeof(data_header), 1, f) != 1) return 0;
- #endif
-
- if (db_hdr.dh_number < 0) {
- current_digest_article = db_hdr.dh_number = -db_hdr.dh_number;
- db_data.dh_type = DH_DIGEST_HEADER;
- } else
- if (db_hdr.dh_number == 0) {
- db_hdr.dh_number = current_digest_article;
- db_data.dh_type = DH_SUB_DIGEST;
- } else {
- current_digest_article = 0;
- db_data.dh_type = DH_NORMAL;
- }
-
- if (db_hdr.dh_cross_postings)
- if (fread((char *)db_data.dh_cross, sizeof(cross_post_number),
- (int)db_hdr.dh_cross_postings, f)
- != (int)db_hdr.dh_cross_postings) return -1;
-
- if (db_hdr.dh_sender_length)
- if (fread(db_data.dh_sender, sizeof(char),
- (int)db_hdr.dh_sender_length, f)
- != db_hdr.dh_sender_length) return -1;
- db_data.dh_sender[db_hdr.dh_sender_length] = NUL;
-
- if (db_hdr.dh_subject_length)
- if (fread(db_data.dh_subject, sizeof(char),
- (int)db_hdr.dh_subject_length, f)
- != db_hdr.dh_subject_length) return -1;
- db_data.dh_subject[db_hdr.dh_subject_length] = NUL;
-
- db_read_counter++;
-
- return 1;
- }
-
- db_write_art(f)
- FILE *f;
- {
- #ifdef NETWORK_DATABASE
- net_long buf[ARTICLE_FIELDS];
- #endif
- article_number art_num = db_hdr.dh_number;
-
- switch (db_data.dh_type) {
- case DH_NORMAL:
- break;
- case DH_SUB_DIGEST:
- db_hdr.dh_number = 0;
- break;
- case DH_DIGEST_HEADER:
- db_hdr.dh_number = -art_num;
- break;
- }
-
- #ifdef NETWORK_DATABASE
- buf[0] = db_hdr.dh_number;
- buf[1] = db_hdr.dh_date;
- buf[2] = db_hdr.dh_hpos;
- buf[3] = db_hdr.dh_lpos;
- buf[4] = db_hdr.dh_fpos;
- buf[5] = db_hdr.dh_lines;
- buf[6] = db_hdr.dh_replies;
- buf[7] = db_hdr.dh_cross_postings;
- buf[8] = db_hdr.dh_subject_length;
- buf[9] = db_hdr.dh_sender_length;
-
- host_to_net(buf, ARTICLE_FIELDS);
-
- if (fwrite((char *)buf, sizeof(net_long), ARTICLE_FIELDS, f) != ARTICLE_FIELDS)
- return -1;
- #else
-
- if (fwrite((char *)&db_hdr, sizeof(data_header), 1, f) != 1)
- return -1;
-
- #endif
- if (db_hdr.dh_cross_postings)
- if (fwrite((char *)db_data.dh_cross, sizeof(cross_post_number),
- (int)db_hdr.dh_cross_postings, f)
- != (int)db_hdr.dh_cross_postings) return -1;
-
- if (db_hdr.dh_sender_length)
- if (fwrite(db_data.dh_sender, sizeof(char),
- (int)db_hdr.dh_sender_length, f)
- != db_hdr.dh_sender_length) return -1;
-
- if (db_hdr.dh_subject_length)
- if (fwrite(db_data.dh_subject, sizeof(char),
- (int)db_hdr.dh_subject_length, f)
- != db_hdr.dh_subject_length) return -1;
-
- db_hdr.dh_number = art_num;
-
- db_write_counter++;
-
- return 1;
- }
-
-
- off_t get_index_offset(gh, art_num)
- group_header *gh;
- article_number art_num;
- {
- #ifdef NETWORK_DATABASE
- return (off_t)((art_num - gh->first_db_article) * sizeof(net_long));
- #else
- return (off_t)((art_num - gh->first_db_article) * sizeof(off_t));
- #endif
- }
-
- off_t get_data_offset(gh, art_num)
- group_header *gh;
- article_number art_num;
- {
- FILE *index;
- off_t data_offset;
-
- if (gh->first_db_article == art_num) return (off_t)0;
-
- index = open_data_file(gh, 'x', OPEN_READ);
- if (index == NULL) return (off_t)(-1);
-
- fseek(index, get_index_offset(gh, art_num), 0);
- if (!db_read_offset(index, &data_offset))
- return (off_t)(-1);
-
- fclose(index);
-
- return data_offset;
- }
-
-
- db_read_offset(f, offset)
- FILE *f;
- off_t *offset;
- {
- #ifdef NETWORK_DATABASE
- net_long temp;
-
- if (fread((char *)&temp, sizeof(net_long), 1, f) != 1) return 0;
-
- #ifndef NETWORK_BYTE_ORDER
- temp = ntohl(temp);
- #endif
- *offset = temp;
- #else
-
- if (fread((char *)offset, sizeof(off_t), 1, f) != 1) return 0;
- #endif
- return 1;
- }
-
- db_write_offset(f, offset)
- FILE *f;
- off_t *offset;
- {
- #ifdef NETWORK_DATABASE
- net_long temp;
-
- temp = *offset;
-
- #ifndef NETWORK_BYTE_ORDER
- temp = htonl(temp);
- #endif
- if (fwrite((char *)&temp, sizeof(net_long), 1, f) != 1) return 0;
-
- #else
-
- if (fwrite((char *)offset, sizeof(off_t), 1, f) != 1) return 0;
- #endif
- return 1;
- }
-
-