initial commit
This commit is contained in:
		
						commit
						ff957efd94
					
				| 
						 | 
					@ -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 ;
 | 
				
			||||||
| 
						 | 
					@ -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,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;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
| 
						 | 
					@ -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]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
		Loading…
	
		Reference in New Issue