initial commit

This commit is contained in:
zongor 2022-09-03 23:35:42 -04:00
commit ff957efd94
11 changed files with 928 additions and 0 deletions

0
.rinx.dclean-copy.txt Executable file
View File

0
.rinx.dclean-master.txt Executable file
View File

7
Makefile Executable file
View File

@ -0,0 +1,7 @@
all: dclean iodir
dclean: dclean.c; gcc -o dclean dclean.c recordio.c
iodir: iodir.c; gcc -o iodir iodir.c
clean:; rm -f dclean ; rm -f iodir ;

1
README.md Executable file
View File

@ -0,0 +1 @@
This is a file cleaner using record i/o, it takes in a `master` and a `copy` directory and will output a shell file which automatically deletes any identical files in the `copy` directory

0
dclean-copy.txt Executable file
View File

0
dclean-master.txt Executable file
View File

274
dclean.c Executable file
View File

@ -0,0 +1,274 @@
#include "dclean.h"
#include "recordio.h"
char buffer[512]; // character buffer for sprintf
int main(int argc, char *argv[])
{
if (argc != 3) {
sprintf(buffer, "usage: dclean directory_master directory_copy\n");
write(1, buffer, strlen(buffer));
return EXIT_FAILURE;
}
char *master = argv[1]; // read in the arguments
char *copy = argv[2];
clean_txt(); // clean the directory
find_directories(master, "dclean-master.txt"); // find all files in the master directory
sortfile("dclean-master.txt", "dclean-master.txt"); // sort the file by filesize
find_directories(copy, "dclean-copy.txt"); // find all of the files in the copy directory
sortfile("dclean-copy.txt", "dclean-copy.txt"); // sort the file by filesize
find_same(); // find which files are the same
}
//-----------------------------------------------------------
// FUNCTION clean_txt:
// this is mostly here to make sure that all of the .txt files are cleared before the program runs
// PARAMETER USAGE :
// none
// FUNCTION CALLED :
// void run_external_process(int fds[2], const char** args);
//-----------------------------------------------------------
void clean_txt()
{
const char *a[3] = {"rm", "dclean-master.txt", NULL};
const char *b[3] = {"rm", "dclean-copy.txt", NULL};
const char *c[3] = {"rm", ".rinx.dclean-master.txt", NULL};
const char *d[3] = {"rm", ".rinx.dclean-copy.txt", NULL};
int s[2]; // pointer for the pipe; (we dont actually use the pipe)
run_external_process(s, a);
run_external_process(s, b);
run_external_process(s, c);
run_external_process(s, d);
}
//-----------------------------------------------------------
// FUNCTION find_same:
// Seaches through the Master and Copy files and checks to see if the files listed are the same using 'diff'
// PARAMETER USAGE :
// none
// FUNCTION CALLED :
// int rio_open(const char *pathname, int flags, mode_t mode);
// int rio_lseek(int fd, int offset, int whence);
// void * rio_read(int fd, int * return_value);
// int identical(char * file1, char * file2);
//-----------------------------------------------------------
void find_same()
{
const char s[2] = {'*', '\n'}; //* and \n character for use in tokenizer
char *token;
char *tokencp;
char *rc;
char *rccp;
int r, rcp, i, j, ir, jr, idn, n;
int fd = rio_open("dclean-master.txt", O_RDONLY, 0644); // open the list of master files
if (fd < 0)
{
fprintf(stderr, "%s\n", strerror(EIO));
exit(EXIT_FAILURE);
}; // error checking
int fdcp = rio_open("dclean-copy.txt", O_RDONLY, 0644); // open the list of copy files
if (fdcp < 0)
{
fprintf(stderr, "%s\n", strerror(EIO));
exit(EXIT_FAILURE);
}; // error checking
int fdsh = open("clean-duplicates.sh", O_RDWR | O_CREAT | O_TRUNC, 0644); // open the shell script
if (fdsh < 0)
{
fprintf(stderr, "%s\n", strerror(EIO));
exit(EXIT_FAILURE);
}; // error checking
n = write(fdsh, "#!/bin/sh\n", strlen("#!/bin/sh\n")); // write this to the top so the .sh works
if (n < 0)
{
fprintf(stderr, "%s\n", strerror(EIO));
exit(EXIT_FAILURE);
}; // error checking
int eol = rio_lseek(fd, 0, SEEK_END); // we now know the length of the master file
int eolcp = rio_lseek(fdcp, 0, SEEK_END); // we now know the length of the copy file
r = rio_lseek(fd, 0, SEEK_SET); // seek back to the beginning
rcp = rio_lseek(fdcp, 0, SEEK_SET);
for (i = 0; i < eol; i++)
{ // loop through all files in the master file
ir = i; // we have to use this since rio_read returns a value back through &ir
rc = rio_read(fd, &ir); // read the ith line of the file
token = strtok(rc, s); // the first token will always be the filesize
token = strtok(NULL, s); // this is the filepath
for (j = 0; j < eolcp; j++)
{ // loop through all files in the copy file
jr = j; // we have to use this since rio_read returns a value back through &jr
rccp = rio_read(fdcp, &jr); // read the jth line of the file
tokencp = strtok(rccp, s); // the first token will always be the filesize
tokencp = strtok(NULL, s); // this is the filepath
idn = identical(token, tokencp); // see if the two files are identical
if (idn == 1)
{ // if they are identical then add them to the shell script
n = write(fdsh, "rm ", strlen("rm ")); // rm (remove command)
n = write(fdsh, tokencp, strlen(tokencp)); // the file in question
n = write(fdsh, "\n", strlen("\n"));
if (n < 0)
{
fprintf(stderr, "%s\n", strerror(EIO));
exit(EXIT_FAILURE);
}; // error checking
}
free(rccp); // we free this as to reset the buffer
}
rio_lseek(fdcp, 0, SEEK_SET); // reset pointer because otherwise we would only search the master file 1 time
free(rc); // free the buffer for the master file
}
}
//-----------------------------------------------------------
// FUNCTION sortfile:
// Sorts the inputfile using /usr/bin/sort
// PARAMETER USAGE :
// char * inputfile : the file for input
// char * outputfile : the file for output
// FUNCTION CALLED :
// none
//-----------------------------------------------------------
int sortfile(char *inputfile, char *outputfile)
{
// equivilent to: sort -n dclean-master.txt > sorted.txt
unsigned char byte;
const char *a[4] = {"sort", "-n", inputfile, NULL}; // construct arguments
#ifdef DEBUG
sprintf(buffer, "Sorting File [%s]\n", inputfile);
write(1, buffer, strlen(buffer));
#endif
pid_t pid; // the pid of the child/parent
int status; // the waiting integer
if ((pid = fork()) == 0)
{ // forking diff (child process)
int fd = open(outputfile, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); // open file (create it if it doesnt exist)
if (fd < 0)
{
fprintf(stderr, "Open (outputfile) Failed because of: %s\n", strerror(EIO));
return -1;
};
dup2(fd, 1); // make stdout go to file
execvp(a[0], a); // create the sort process
exit(0); // exit the child
}
else if (pid < 0)
{ // error checking
sprintf(buffer, "Fork Failed!\n");
write(1, buffer, strlen(buffer));
exit(-1);
}
else
{ // parent process
while (wait(&status) != pid)
; // wait for completion;
}
return 0;
}
//-----------------------------------------------------------
// FUNCTION find_directories:
// Runs "iodir" to generate the .txt files
// PARAMETER USAGE :
// char * file_path : the file for input
// char * out_name : the file for output
// FUNCTION CALLED :
// void run_external_process(int fds[2], const char** args);
//-----------------------------------------------------------
int find_directories(char *file_path, char *out_name)
{
const char *a[4] = {"iodir", file_path, out_name, NULL}; // construct arguments
int fds[2]; // pointer for the pipe we will create in a line or so
#ifdef DEBUG
sprintf(buffer, "Generating Directory File [%s] For path: [%s]\n", out_name, file_path);
write(1, buffer, strlen(buffer));
#endif
run_external_process(fds, a); // generate the files using iodir [I edited it slightly]
return 0;
}
//-----------------------------------------------------------
// FUNCTION identical:
// Runs "diff file1 file2" to generate see if they are the same
// PARAMETER USAGE :
// char * file1 : "master" file
// char * file2 : "copy" file
// FUNCTION CALLED :
// void run_external_process(int fds[2], const char** args);
//-----------------------------------------------------------
int identical(char *file1, char *file2)
{
const char *a[4] = {"diff", file1, file2, NULL}; // construct arguments
int fds[2]; // pointer for the pipe we will create in a line or so
run_external_process(fds, a); // run diff
// continue with parent process
ssize_t size = read(fds[0], buffer, sizeof(buffer)); // read from the pipe
if (size == 0)
{ // diff returns zero when the files are the same
#ifdef DEBUG
sprintf(buffer, "\"%s\" is a copy of \"%s\"\n", file2, file1);
write(1, buffer, strlen(buffer));
#endif
return 1; // they are identical
}
else
{
#ifdef DEBUG
sprintf(buffer, "\"%s\" and \"%s\" differ\n", file1, file2);
write(1, buffer, strlen(buffer));
#endif
return 0; // they are different
}
return -1; // something weird went on; throw an error
}
//-----------------------------------------------------------
// FUNCTION run_external_process:
// Runs child process and returns the childs output to the parent
// PARAMETER USAGE :
// int fds[2] : the pointers to the pipe
// const char** args : the arguments for the execvp
// FUNCTION CALLED :
// none
//-----------------------------------------------------------
void run_external_process(int fds[2], const char **args)
{
pid_t pid; // the pid of the child/parent
int status; // the waiting integer
pipe(fds); // create a new pipe pipe
if ((pid = fork()) == 0)
{ // forking the child process
close(fds[0]); // close the input of the pipe
close(1); // close stdout
dup(fds[1]); // dup the pipes stdout (pipe now sends child's stdout)
execvp(args[0], args); // create the diff process
exit(0); // exit the child
}
else if (pid < 0)
{ // error checking
sprintf(buffer, "Fork Failed!\n");
write(1, buffer, strlen(buffer));
exit(-1);
}
else
{ // parent process
close(fds[1]); // close output of pipe which redirects stdout of the child
while (wait(&status) != pid)
; // wait for completion;
}
}

51
dclean.h Executable file
View File

@ -0,0 +1,51 @@
#ifndef DCLEAN_H_
#define DCLEAN_H_
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <dirent.h>
#include <sys/dir.h>
void run_external_process(int pipe[2], const char** args);
int find_directories(char * file_path, char * out_name);
int sortfile(char *inputfile, char *outputfile);
int identical(char * file1, char * file2);
void list_directory (char * path , char * filename);
void find_same();
void clean_txt();
/*
* dclean <master directory> <copy directory>
*
* A/ B/ # A/excursion.jpg
* excursion.jpg == 123.jpg => rm B/123.jpg
*
*
* | Addon/ |
* | |
* | xyz.txt |
* | |
* | |
* | .. |
* | . |
* V V
* dclean-master.txt dclean-copy.txt
* [ 1024 | A/excursion.jpg] [ 1024 | B/123.jpg]
* [ 127 | A/Addon/xyz.txt] [ | ]
*
* if filesize A == filesize B then
*
* if they are the same add to the to_be_deleted_list
*
* fork and exec "diff" to see if the same
*
*/
#endif /* DCLEAN_H_ */

100
iodir.c Executable file
View File

@ -0,0 +1,100 @@
#include "dclean.h"
struct dirent *dptr;
void list_directory(char *path, char *filename)
{
struct stat st, sb;
DIR *dirp;
int n, fd;
int out = open(filename, O_RDWR | O_CREAT, 0644); // opens file; creates it if it does not exist;
if (out < 0)
{ // error check
fprintf(stderr, "cannot open %s because of %s\n", filename, strerror(5));
exit(EXIT_FAILURE);
}
if ((dirp = opendir(path)) == NULL)
{
fprintf(stderr, "Opening %s : ", path);
perror("opendir:");
return;
}
while ((dptr = readdir(dirp)))
{
char *name = dptr->d_name;
stat(name, &sb);
if ((strcmp(name, "..") != 0) & (strcmp(name, ".") != 0))
{
#ifdef DEBUG
printf("st.st_mode : %d\n", st.st_mode);
#endif
if ((sb.st_mode & S_IFMT) == S_IFDIR)
{
char *p;
#ifdef DEBUG
printf("%s/%s/\n", path, name); // uncomment if you want to see the directory name.
#endif
p = malloc(strlen(name) + strlen(path) + 1 + 1);
strcpy(p, path);
strcat(p, "/");
strcat(p, name);
list_directory(p, filename);
free(p);
}
else if ((sb.st_mode & S_IFMT) == S_IFREG)
{
char *full;
full = malloc(strlen(path) + 1 + strlen(name) + 1);
strcpy(full, path);
strcat(full, "/");
strcat(full, name);
fd = open(full, O_RDONLY);
if (fd < 0)
{
fprintf(stderr, "unable to open file:%s\n", full);
perror("open:");
}
else
{
stat(full, &st);
#ifdef DEBUG
printf("%s %lld\n", full, st.st_size);
#endif
char number[50] = {};
sprintf(number, "%lld", st.st_size);
;
n = write(out, number, strlen(number));
n = write(out, "*", strlen("*"));
n = write(out, full, strlen(full)); // write the record descriptor
n = write(out, "\n", strlen("\n"));
if (n < 0)
{
fprintf(stderr, "%s\n", strerror(EIO));
exit(EXIT_FAILURE);
}; // error checking
}
close(fd);
free(full);
}
#ifdef DEBUG
else
printf("---> Not a regular file %s/%s\n", path, name);
#endif
}
}
closedir(dirp);
}
int main(int argc, char *argv[])
{
list_directory(argv[1], argv[2]);
}

466
recordio.c Executable file
View File

@ -0,0 +1,466 @@
#include "recordio.h"
unsigned char readbyte(int fp);
char pbuf[512]; // print buffer
int eof = 1; // flag for end of file
//-----------------------------------------------------------
// FUNCTION rio_open:
// If create is requested, open both the data file and the index file with O CREAT.
// If O RDONLY or O RDWR is requested, make sure that the index file is present and return an error otherwise.
// PARAMETER USAGE :
// const char* pathname : the path of the file to open
// int flags : the type of open
// mode_t mode : file permissions
// FUNCTION CALLED :
// int16_t encodefd(int d1, int d2)
// printb(unsigned n) : for debugging
//-----------------------------------------------------------
int rio_open(const char *pathname, int flags, mode_t mode)
{
ret:;
int d, d1o, d2o; // output file descriptor
char *name_extention = ".rinx."; // all index files must start with this
char *index_filename = malloc(sizeof(char) * (strlen(name_extention) + strlen(pathname))); // allocate space for the index filename
unsigned char byte; // storage as to read in byte by byte
int record_position = 0;
int n, buff; // counters
record_descriptor rd; // record descriptor
buff = 0; // set the initial buffer size
int d1, d2;
strcat(index_filename, name_extention); // construct the index filename
strcat(index_filename, pathname);
int index_tester = open(index_filename, O_RDONLY);
if (index_tester > 0)
{
close(index_tester);
}
int datafile_tester = open(pathname, O_RDONLY);
if (datafile_tester > 0)
{
close(datafile_tester);
}
else
{ // the file doesnt exist
close(datafile_tester);
d1 = open(pathname, flags, mode); // open the data file
if (d1 < 0)
{ // error check
fprintf(stderr, "cannot open %s because of %s\n", pathname, strerror(5));
return -1;
}
d2 = open(index_filename, O_RDWR | O_CREAT | O_EXCL, 0777);
if (d2 < 0)
{ // error check
fprintf(stderr, "cannot open %s because of %s\n", pathname, strerror(5));
return -1;
}
d = encodefd(d1, d2); // encrypt file descriptor
return d;
}
d1 = open(pathname, flags, mode); // open the data file
if (d1 < 0)
{ // error check
fprintf(stderr, "cannot open %s because of %s\n", pathname, strerror(5));
return -1;
}
if (index_tester < 0)
{ // check if index file doesnt exist
d2 = open(index_filename, O_RDWR | O_CREAT | O_EXCL, 0777);
if (d2 < 0)
{ // error check
fprintf(stderr, "cannot open %s because of %s\n", pathname, strerror(5));
return -1;
}
while (eof)
{ // read until end of file
byte = readbyte(d1); // read in 1 byte
if (eof == 0)
{ // check to see if you are at the end of file
if (buff > 0)
{ // if the buffer is nonzero then we have a file which doesnt end in an endl
rd.position = record_position - buff; // record position
rd.length = buff; // record length
n = write(d2, &rd, sizeof(record_descriptor)); // write the record descriptor
if (n < 0)
{
fprintf(stderr, "create index eof: %s\n", strerror(EIO));
return -1;
}; // error checking
}
eof = 1;
break; // we are at the end of file
}
record_position += sizeof(byte); // increase bytecount
buff += sizeof(byte); // increase bytecount
if (byte == '\n')
{ // check if the byte is an endline
rd.position = record_position - buff; // record position
rd.length = buff; // record length
n = write(d2, &rd, sizeof(record_descriptor)); // write the record descriptor
if (n < 0)
{
fprintf(stderr, "create index norm: %s\n", strerror(EIO));
return -1;
}; // error checking
buff = 0; // reset the buffer
}
}
close(d1);
close(d2);
goto ret; // This goes back to the top of the function if the file doesn't exist so that the file is created and opened correctly
}
else
{ // file exists
d2 = open(index_filename, O_RDWR, 0777);
if (d2 < 0)
{ // error check
fprintf(stderr, "cannot open %s because of %s\n", pathname, strerror(5));
return -1;
}
}
d = encodefd(d1, d2); // encrypt file descriptor
/* ENCODEING/DECODEING CORRECTNESS TEST */
#ifdef DEBUG
printf("d1_in = ");
printb(d1);
printf("d2_in = ");
printb(d2);
printf("d = ");
printb(d);
printf("d1_out = ");
d1o = decodedfd(d);
printb(d1o);
printf("d2_out = ");
d2o = decodeifd(d);
printb(d2o);
#endif
return d;
}
//-----------------------------------------------------------
// FUNCTION rio_read:
// Allocate a buffer large enough to hold the requested buffer,
// read the next record and return the pointer to the allocated area.
// The I/O result should be returned through the return value argument.
// PARAMETER USAGE :
// int fd : the file descriptor
// int * return_value : the record in the index file to read
// FUNCTION CALLED :
// int8_t decodeifd(int16_t d)
// int8_t decodedfd(int16_t d)
//-----------------------------------------------------------
void *rio_read(int fd, int *return_value)
{
void *buffer; // the buffer to be returned
int index_fd, data_fd; // file descriptors
int r; // read error checker
record_descriptor rd; // record descriptor
index_fd = decodeifd(fd); // decrypt index file descriptor
data_fd = decodedfd(fd); // decrypt data file descriptor
r = read(index_fd, &rd, sizeof(rd)); // read in the record
if (r < 0)
{
fprintf(stderr, "rio_read (index): %s\n", strerror(EIO));
return NULL;
}; // error check
int position = rd.position; // the position of the data in the datafile
int length = rd.length; // the size of the data block
buffer = (void *)malloc(length); // allocate buffer memory
int r1 = read(data_fd, buffer, length); // read in the data to the buffer
if (r1 < 0)
{
fprintf(stderr, "rio_read (data)%s\n", strerror(EIO));
return NULL;
}; // error check
*return_value = r1; // The I/O result should be returned through the return value argument.
return buffer; // return the pointer to the allocated area.
}
//-----------------------------------------------------------
// FUNCTION rio_write:
// If appending to the file, create a record descriptor and fill-in the values.
// Write the descriptor to the index file and the supplied data to the data file for the requested length.
// If updating a record, read the record descriptor, check to see if the new record fits in the allocated area and rewrite.
// Return an error otherwise.
// PARAMETER USAGE :
// int fd : the file descriptor
// const void *buf : the buffer to be written
// int count : requested length
// FUNCTION CALLED :
// int8_t decodeifd(int16_t d)
// int8_t decodedfd(int16_t d)
//-----------------------------------------------------------
int rio_write(int fd, const void *buf, int count)
{
int index_fd, data_fd; // file descriptors
int r, w, data_w; // read error checker
record_descriptor rd; // record descriptor
index_fd = decodeifd(fd); // decrypt index file descriptor
data_fd = decodedfd(fd); // decrypt data file descriptor
r = read(index_fd, &rd, sizeof(rd)); // read in the record
if (r < 0)
{
fprintf(stderr, "rio_write (read index [to check if record_descriptor exists]): %s\n", strerror(EIO));
return -1;
}; // error check
if (r > 0)
{
int length = rd.length; // the size of the data block
if (length < count)
{
fprintf(stderr, "rio_write: %s\n", strerror(ENOMEM));
return -1;
}
}
else
{ // we are at the end of the index file || file is empty
int check = lseek(index_fd, 0, SEEK_END); // check to see if the file is empty (newly created)
if (check > 0)
{ // normal case
lseek(index_fd, -sizeof(record_descriptor), SEEK_END);
r = read(index_fd, &rd, sizeof(rd)); // read in the record
if (r < 0)
{
fprintf(stderr, "rio_write (read index to make new record_descriptor): %s\n", strerror(EIO));
return -1;
}; // error check
int position = rd.position; // the position of the data in the datafile
int length = rd.length; // the size of the data block
rd.position = position + length;
rd.length = count;
}
else
{ // special case for empty file
rd.position = 0;
rd.length = count;
}
w = write(index_fd, &rd, sizeof(record_descriptor));
if (w < 0)
{
fprintf(stderr, "rio_write (write index): %s\n", strerror(EIO));
return -1;
}; // error check
lseek(data_fd, rd.position, SEEK_SET); // seek to position in data file
data_w = write(data_fd, buf, count);
if (data_w < 0)
{
fprintf(stderr, "rio_write (write data): %s\n", strerror(EIO));
return -1;
}; // error check
return data_w;
}
rd.length = count;
lseek(index_fd, -sizeof(record_descriptor), SEEK_CUR);
w = write(index_fd, &rd, sizeof(record_descriptor));
if (w < 0)
{
fprintf(stderr, "rio_write (write index): %s\n", strerror(EIO));
return -1;
}; // error check
data_w = write(data_fd, buf, count);
if (data_w < 0)
{
fprintf(stderr, "rio_write (write data): %s\n", strerror(EIO));
return -1;
}; // error check
return w;
}
//-----------------------------------------------------------
// FUNCTION rio_lseek:
// Seek both files to the beginning of the requested record so that the next I/O is performed at the requested position.
// whence assumes the same values as lseek whence argument.
// PARAMETER USAGE :
// int fd : the file descriptor
// int offset : the offset of the index file
// int whence : the "mode" of the seek
// FUNCTION CALLED :
// int8_t decodeifd(int16_t d)
// int8_t decodedfd(int16_t d)
//-----------------------------------------------------------
int rio_lseek(int fd, int offset, int whence)
{
int index_fd, data_fd; // file descriptors
int s1, s2, r; // error values
record_descriptor rd;
index_fd = decodeifd(fd); // decrypt index file descriptor
data_fd = decodedfd(fd); // decrypt data file descriptor
s1 = lseek(index_fd, (offset) * sizeof(record_descriptor), whence); // seek the index file to offset
r = read(index_fd, &rd, sizeof(rd)); // read in the record
if (r < 0)
{
fprintf(stderr, "rio_lseek (SEEK_SET): %s\n", strerror(EIO));
return -1;
}; // error check
s1 = lseek(index_fd, (offset) * sizeof(record_descriptor), whence); // seek back to the index file because you read it in the previous step
int position = rd.position; // the position of the data in the datafile
s2 = lseek(data_fd, position, SEEK_SET); // seek to the position in the datafile @position
return s1 / sizeof(record_descriptor);
}
//-----------------------------------------------------------
// FUNCTION rio_close:
// Close both files.
// PARAMETER USAGE :
// int fd : the file descriptor
// FUNCTION CALLED :
// int8_t decodeifd(int16_t d)
// int8_t decodedfd(int16_t d)
//-----------------------------------------------------------
int rio_close(int fd)
{
int index_fd, data_fd; // file descriptors
index_fd = decodeifd(fd); // decrypt index file descriptor
data_fd = decodedfd(fd); // decrypt data file descriptor
int r1 = close(data_fd);
if (r1 < 0)
{
fprintf(stderr, "rio_close (datafile): %s\n", strerror(EIO));
return -1;
};
int r2 = close(index_fd);
if (r2 < 0)
{
fprintf(stderr, "rio_close (indexfile): %s\n", strerror(EIO));
return -1;
};
return r1;
}
//-----------------------------------------------------------
// FUNCTION encodefd:
// takes the file descriptor of both inputs and turns it into a single file descriptor
// PARAMETER USAGE :
// int d1 : the data file descriptor
// int d2 : the index file descriptor
// FUNCTION CALLED :
// none
//-----------------------------------------------------------
int16_t encodefd(int d1, int d2)
{
int16_t d = (((d1 & 0xff) << 8) | (d2 & 0xff)); // 16 bit handle
return d;
}
//-----------------------------------------------------------
// FUNCTION decodedfd:
// returns the data file descriptor
// PARAMETER USAGE :
// int16_t d : the file descriptor
// FUNCTION CALLED :
// none
//-----------------------------------------------------------
int8_t decodedfd(int16_t d)
{
int8_t d1 = (d >> 8); // take the top 8 bits
return d1;
}
//-----------------------------------------------------------
// FUNCTION decodeifd:
// returns the index file descriptor
// PARAMETER USAGE :
// int16_t d : the file descriptor
// FUNCTION CALLED :
// none
//-----------------------------------------------------------
int8_t decodeifd(int16_t d)
{
int8_t d2 = (d & 0xff); // take the bottom 8 bits
return d2;
}
//-----------------------------------------------------------
// FUNCTION printb:
// prints a 32 bit binary number
// PARAMETER USAGE :
// unsigned : the number
// FUNCTION CALLED :
// none
//-----------------------------------------------------------
void printb(unsigned n)
{
unsigned i;
for (i = 1 << 31; i > 0; i = i / 2)
{
(n & i) ? printf("1") : printf("0");
}
printf("\n");
}
//-----------------------------------------------------------
// FUNCTION readbyte:
// reads 1 byte from stdin and does error checking
// PARAMETER USAGE :
// none
// FUNCTION CALLED :
// ssize_t read(int fildes, void *buf, size_t nbyte)
// int fprintf(FILE * restrict stream, const char * restrict format, ...);
// char * strerror(int errnum);
//-----------------------------------------------------------
unsigned char readbyte(int fp)
{
int r;
unsigned char byte;
r = read(fp, &byte, sizeof(byte));
if (r < 0)
{
fprintf(stderr, "readbyte: %s\n", strerror(EIO));
exit(-1);
};
if (r == 0)
{
eof = 0;
};
return byte;
}

29
recordio.h Executable file
View File

@ -0,0 +1,29 @@
#ifndef RECORDIO_H_
#define RECORDIO_H_
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
typedef struct
{
int position;
int length;
} record_descriptor;
int rio_open(const char *pathname, int flags, mode_t mode);
void *rio_read(int fd, int *return_value);
int rio_write(int fd, const void *buf, int count);
int rio_lseek(int fd, int offset, int whence);
int rio_close(int fd);
int16_t encodefd(int d1, int d2);
int8_t decodedfd(int16_t d);
int8_t decodeifd(int16_t d);
void printb(unsigned n);
#endif /* RECORDIO_H_ */