#include #include #include #define LINE_SZ 200 #define A_MEG (4 * 1024 * 1024) char buff1[A_MEG], buff2[A_MEG]; void update_file(char *fname); int main(int ac, char *av[]) { int i; if (ac < 2){ printf("Usage:\n %s file [file ...]\n", av[0]); } for (i = 1; i < ac; i++){ update_file(av[i]); } } void update_file(char *fname) { FILE *fp; char h[500][LINE_SZ]; int count = 0; int header_done; int table_line = -1; int fit_in, i; long update_pos, resume_pos, next_read_pos; char *p; char old_sz[20], new_sz[20]; size_t bytes_read; int record_bytes = 0; int c, n; int hbytes, old_sz_num; printf("Processing %s ...\n", fname); fp = fopen(fname, "r+"); if (fp == NULL) { printf("Could not open %s.\n", fname); return; } count = 0; header_done = 0; while (!header_done && fgets(h[count], LINE_SZ, fp)) { if (!strncasecmp(h[count], "END", strlen("END")) && isspace(h[count][strlen("END")])) { header_done = 1; next_read_pos = ftell(fp); while(isspace(c = fgetc(fp))); ungetc(c, fp); hbytes = ftell(fp); fseek(fp, next_read_pos, SEEK_SET); } else if (!strncasecmp(h[count], "^TABLE", strlen("^TABLE"))) { table_line = count; } else if (!strncasecmp(h[count], "RECORD_BYTES", strlen("RECORD_BYTES"))) { record_bytes = atoi(strchr(h[count], '=') + 1); } count++; } if (!count || (table_line < 0)) { printf("Could not find enough information in file %s.\n", fname); fclose(fp); return; } /* Check for cramped fit-in */ fit_in = 0; p = strchr(h[table_line], '='); if (!p) { printf("Fatal! File %s. ^TABLE does not contain \"=\"\n", fname); fclose(fp); return; } while (*++p == ' '); old_sz_num = atoi(p); sprintf(old_sz, "%d", old_sz_num); sprintf(new_sz, "%d", (hbytes / record_bytes) + 1); if (strcmp(old_sz, new_sz) != 0){ printf("Updating %s [RECORD_BYTES=%d, HEADER=%d, ^TABLE=%s -> %s] ...\n", fname, record_bytes, hbytes, old_sz, new_sz); } else { printf("Skipping %s [RECORD_BYTES=%d, HEADER=%d, ^TABLE=%s] ...\n", fname, record_bytes, hbytes, old_sz); fclose(fp); return; } if (strlen(old_sz) >= strlen(new_sz)) { fit_in = 1; /* No additional space needed */ } else if (h[table_line][strlen(h[table_line]) - 2] == ' ') { fit_in = 2; /* Space avaliable in the same line */ } else if (h[count - 1][strlen(h[count - 1]) - 2] == ' ') { fit_in = 3; /* Space available in END line */ } else { fit_in = 0; /* Cannot fit in, shuffle things down */ sprintf(new_sz, "%d", atoi(new_sz) + 1); } /* Position the file for overwrite */ update_pos = 0; for (i = 0; i < table_line; i++) { update_pos += strlen(h[i]); } switch (fit_in) { case 1: case 2: /* Blank out region */ for (i = 0; (p[i] != '\0') && (p[i] != '\n'); i++){ p[i] = ' '; } memcpy(p, new_sz, strlen(new_sz)); /* sprintf(p, "%s", new_sz); */ /* Position to the first line that needs updating */ fseek(fp, update_pos, SEEK_SET); fputs(h[table_line], fp); break; case 3: sprintf(p, "%s\n", new_sz); p = &h[count - 1][strlen(h[count - 1]) - 2]; strcpy(p, p + 1); /* Position to the first line that needs updating */ fseek(fp, update_pos, SEEK_SET); for (i = table_line; i < count; i++) { fputs(h[i], fp); } break; default: sprintf(p, "%s\n", new_sz); bytes_read = fread(buff1, 1, A_MEG, fp); next_read_pos = ftell(fp); /* Position to the first line that needs updating */ fseek(fp, update_pos, SEEK_SET); for (i = table_line; i < count; i++) { fputs(h[i], fp); } fprintf(fp, "%*s", record_bytes - 1, ""); resume_pos = ftell(fp); while (bytes_read == A_MEG) { fseek(fp, next_read_pos, SEEK_SET); bytes_read = fread(buff2, 1, A_MEG, fp); next_read_pos = ftell(fp); fseek(fp, resume_pos, SEEK_SET); fwrite(buff1, 1, A_MEG, fp); memmove(buff1, buff2, A_MEG); /* Setup for next time around */ } fseek(fp, resume_pos, SEEK_SET); fwrite(buff1, 1, bytes_read, fp); break; } fclose(fp); }