/* * stdc-small-db.c - handle a small database file, with fixed-length records. * uses standard C library I/O functions, including fopen, fseek, fgetpos, * fsetpos etc. */ #include /* standard input/output routines. */ #define RECORD_LEN 30 /* size of a record. */ /* * function: get_record. Reads a record from the given file. * input: pointer to file stream, number of record in file (0 is * the first record), and a pointer to a buffer. * output: '1' on success, '0' on failure. In case of success, the record * is copied to the supplied buffer. */ int get_record(FILE* file, long record_num, char* buf) { long file_pos; /* stores the original read/write pointer position. */ int success = 0; /* success/failure indicator. assume failure here. */ /* sanity checks */ if (!file || record_num < 0 || !buf) { return 0; } /* note the current read/write pointer position. */ file_pos = ftell(file); if (file_pos < 0) { perror("get_record: ftell"); } else { /* move to the record's location. */ if (fseek(file, record_num * RECORD_LEN, SEEK_SET) < 0) { perror("get_record: fseek"); } else { /* read the record from the file stream. */ if (fread(buf, RECORD_LEN, 1, file) == 1) { success = 1; /* mark that we succeeded in reading the record */ } else { perror("get_record: fread"); } /* restore the original read/write pointer position. */ if (fseek(file, file_pos, SEEK_SET) < 0) { perror("get_record: fseek"); } } } return success; } /* * function: put_record. Writes a record to the given file. * input: pointer to file stream, number of the record in file (0 is * the first record) and a pointer to a buffer containing the * data to be written. * output: '1' on success, '0' on failure. */ int put_record(FILE* file, long record_num, char* buf) { long file_pos; /* stores the original read/write pointer position. */ int success = 0; /* success/failure indicator. assume failure here. */ /* sanity checks */ if (!file || record_num < 0 || !buf) { return 0; } /* note the current read/write pointer position. */ file_pos = ftell(file); if (file_pos < 0) { perror("put_record: ftell"); } else { /* move to the record's location. */ if (fseek(file, record_num * RECORD_LEN, SEEK_SET) < 0) { perror("put_record: fseek"); } else { /* write the record to the file stream. */ if (fwrite(buf, RECORD_LEN, 1, file) == 1) { success = 1; /* mark that we succeeded in writing the record */ } else { perror("put_record: fwrite"); } /* restore the original read/write pointer position. */ if (fseek(file, file_pos, SEEK_SET) < 0) { perror("put_record: ftell"); } } } return success; } /* * function: main. write and read some records to/from a file. * input: none. * output: none. */ void main() { char* file_name = "small_db.data"; char buf[RECORD_LEN]; FILE* db_file; /* open the database file, in read and write mode. */ db_file = fopen(file_name, "w+"); if (!db_file) { perror("fopen"); exit(1); } /* write some records into the database file. */ strcpy(buf, "hello world"); put_record(db_file, 5, buf); strcpy(buf, "adios, amigos"); put_record(db_file, 17, buf); strcpy(buf, "marchaba marchabtain"); put_record(db_file, 12, buf); /* now read some records from the database file. */ get_record(db_file, 17, buf); printf("record %d: '%s'\n", 17, buf); get_record(db_file, 5, buf); printf("record %d: '%s'\n", 5, buf); get_record(db_file, 3, buf); /* never written - should be garbage */ printf("record %d: '%s'\n", 3, buf); if (fclose(db_file) == EOF) { perror("fclose"); exit(1); } }