#include #include #include #include #include #include #include #include #include "tar.h" int archiveexists(char *fname); int last_header_pointer; hdr head = {0x63746172, // head header for rewriting eop pointer sizeof(head), 0, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, -1}; hdr empty = {0x63746172, // empty header for copying sizeof(empty), 0, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, -1}; int main(int argc, char *argv[]) { if (argc < 2) { // check to see if inputs exist fprintf(stderr, "%s [No Input]:\n Usage: ctar (-a | -d) \n", strerror(5)); exit(EXIT_FAILURE); } char *f = argv[1]; // read the flag char *archivename = argv[2]; // name of archive int numberoffiles = argc - 3; // number of files to process char buffer[300]; // character buffer for sprintf int i, j, k, x; // loop counters int r; // read pointer int w; // write pointer int fp; // file pointer char *current_file; int Current_EOP; if (argc < 3 && strcmp(argv[1], "-a") == 0) { // check to see if arguments are correct for flag -a fprintf(stderr, "%s:\n Usage: ctar -a file1, file2, ... filen\n", strerror(5)); exit(EXIT_FAILURE); } else if (argc != 4 && strcmp(argv[1], "-d") == 0) { // check to see if arguments are correct for flag -d fprintf(stderr, "%s:\n Usage: ctar -d \n", strerror(5)); exit(EXIT_FAILURE); } else if (strcmp(argv[1], "-a") != 0 && strcmp(argv[1], "-d") != 0) { // check to see if the user has a valid flag fprintf(stderr, "%s [Unknown Flag]:\n Usage: ctar (-a | -d) \n", strerror(5)); exit(EXIT_FAILURE); } #ifdef DEBUG printf("numberoffiles = %d\n", numberoffiles); #endif if (archiveexists(archivename) == 0) { // if file does not exist fp = open(archivename, O_RDWR | O_CREAT, 0644); // opens file; creates it if it does not exist; if (strcmp(argv[1], "-a") == 0) { #ifdef DEBUG sprintf(buffer, "case -a (file doesn't exist)\n"); write(1, buffer, strlen(buffer)); #endif if (numberoffiles == 0) { // create an empty archive file w = write(fp, (char *)&head, sizeof(head)); if (w < 0) { fprintf(stderr, "%s\n", strerror(5)); exit(EXIT_FAILURE); } close(fp); return EXIT_SUCCESS; } else { // create an archive file with content #ifdef DEBUG sprintf(buffer, "create an archive with content\n"); write(1, buffer, strlen(buffer)); #endif int numberofheaders = (numberoffiles / 8) + 1; // calculate the number of headers hdr temp; int temp_sizeof_file; int temp_file_pointer; int temp_file_read; int temp_filename_pointer; int argv_pointer; int temp_header_pointer = 0; char byte; short int char_len_buf; // First write empty header to archive lseek(fp, 0, SEEK_SET); w = write(fp, (char *)&head, sizeof(head)); Current_EOP = sizeof(empty); for (i = 0; i < numberofheaders; i++) { // iterate through all headers #ifdef DEBUG printf("ITERATION:%i\n", i); #endif temp = empty; // sets the temp header to an empty hdr head.eop = Current_EOP; // write the eop to the head node for (j = 1; j <= 8; j++) { // reads 8 files at a time argv_pointer = (j + (i * 8)) + 2; if (argv_pointer - 2 > numberoffiles) { #ifdef DEBUG sprintf(buffer, "makes sure that the parser ends when the last file is read [file:%d]\n", argv_pointer - 2); write(1, buffer, strlen(buffer)); #endif close(fp); return EXIT_SUCCESS; // makes sure that the parser ends when the last file is read } if (i > 0) { #ifdef DEBUG printf("write new header : [header %i]\n", temp_header_pointer); #endif lseek(fp, temp_header_pointer, SEEK_SET); w = write(fp, (char *)&temp, sizeof(temp)); } current_file = argv[argv_pointer]; temp_file_pointer = open(current_file, O_RDWR, 0644); // opens file; if (temp_file_pointer < 0) { fprintf(stderr, "%s\n", strerror(5)); exit(EXIT_FAILURE); } temp_sizeof_file = 0; // reset file size counter // Create Filename, Write to archive Current_EOP = lseek(fp, 0, SEEK_END); temp_filename_pointer = Current_EOP; char_len_buf = strlen(argv[argv_pointer]); write(fp, (char *)&char_len_buf, sizeof(char_len_buf)); // write size Current_EOP = lseek(fp, 0, SEEK_END); #ifdef DEBUG sprintf(buffer, "file_name_size written to archive [file:%d]\n", argv_pointer - 2); write(1, buffer, strlen(buffer)); #endif write(fp, argv[argv_pointer], char_len_buf * sizeof(char)); // write title Current_EOP = lseek(fp, 0, SEEK_END); // Write file to archive temp_file_read = read(temp_file_pointer, &byte, sizeof(byte)); // read first byte Current_EOP = lseek(fp, 0, SEEK_END); temp_sizeof_file += sizeof(byte); // increment the size of file write(fp, &byte, sizeof(byte)); // write first byte #ifdef DEBUG sprintf(buffer, "Read first byte [file:%d]\n", argv_pointer - 2); write(1, buffer, strlen(buffer)); #endif int k = 1; while (temp_file_read > 0) { // iterate until it reaches end of file temp_file_read = read(temp_file_pointer, &byte, sizeof(byte)); // read all next bytes if (temp_file_read < 1) { break; // breaks to make sure the last byte isnt written twice } Current_EOP = lseek(fp, 0, SEEK_END); temp_sizeof_file += sizeof(byte); // increment the size of file #ifdef DEBUG sprintf(buffer, "Read %d-th byte [file:%d]\n", k, argv_pointer - 2); write(1, buffer, strlen(buffer)); #endif write(fp, &byte, sizeof(byte)); // write following byte(s) #ifdef DEBUG sprintf(buffer, "wrote %d-th byte [file:%d]\n", k, argv_pointer - 2); write(1, buffer, strlen(buffer)); #endif k++; } #ifdef DEBUG sprintf(buffer, "file written to archive [file:%d]\n", argv_pointer - 2); write(1, buffer, strlen(buffer)); #endif Current_EOP = lseek(fp, 0, SEEK_END); head.eop = Current_EOP; lseek(fp, 0, SEEK_SET); w = write(fp, (char *)&head, sizeof(head)); #ifdef DEBUG sprintf(buffer, "first header rewritten [file:%d]\n", argv_pointer - 2); write(1, buffer, strlen(buffer)); sprintf(buffer, "filename is: %s, written to archive [file:%d]\n", argv[argv_pointer], argv_pointer - 2); write(1, buffer, strlen(buffer)); #endif if (i < 1) { head.block_count = (head.block_count + 1); head.file_size[j - 1] = temp_sizeof_file; head.file_name[j - 1] = temp_filename_pointer; } else { temp.block_count = (temp.block_count + 1); temp.file_size[j - 1] = temp_sizeof_file; temp.file_name[j - 1] = temp_filename_pointer; } #ifdef DEBUG sprintf(buffer, "starting writing file to archive [file:%d]\n", argv_pointer - 2); write(1, buffer, strlen(buffer)); #endif if (w < 0) { fprintf(stderr, "%s\n", strerror(5)); exit(EXIT_FAILURE); } if (i > 0) { #ifdef DEBUG printf("write header %i data\n", i); #endif lseek(fp, temp_header_pointer, SEEK_SET); w = write(fp, (char *)&temp, sizeof(temp)); if (w < 0) { fprintf(stderr, "%s\n", strerror(5)); exit(EXIT_FAILURE); } } else { #ifdef DEBUG printf("write header %i data\n", i); #endif lseek(fp, 0, SEEK_SET); w = write(fp, (char *)&head, sizeof(head)); if (w < 0) { fprintf(stderr, "%s\n", strerror(5)); exit(EXIT_FAILURE); } } } if (i < 1) { head.next = head.eop; temp_header_pointer = head.eop; } else { temp.next = head.eop; temp_header_pointer = head.eop; } } close(fp); return EXIT_SUCCESS; } } close(fp); } else { // file already exist fp = open(archivename, O_RDWR, 0644); // opens file; creates it if it does not exist; if (strcmp(argv[1], "-a") == 0) { // add file(s) to an archive that already exists #ifdef DEBUG printf("case -a (file exists)\n"); #endif hdr header; int temp_sizeof_file; int temp_file_pointer; int temp_file_read; int temp_filename_pointer; char f_name[sizeof(short int)]; short int l; int p = 0; int poi; lseek(fp, 0, SEEK_SET); r = read(fp, &header, sizeof(hdr)); // load first header if (r != sizeof(hdr)) { fprintf(stderr, "%s: file is not the size of a header object", strerror(5)); exit(EXIT_FAILURE); } else if (header.magic != 0x63746172) { fprintf(stderr, "%s: header does not include the magic number", strerror(5)); exit(EXIT_FAILURE); } char byte; int char_len_buf; int not_finished_reading; int temp_header_pointer = 0; int number_of_headers; k = 0; while (k < argc - 3) { not_finished_reading = true; number_of_headers = 1; while (not_finished_reading) { if (header.block_count < 8) { // if it has 8 elements then the header is full and we must move to the next one for (j = 0; j < header.block_count; j++) { // search through all blocks in the header lseek(fp, header.file_name[j], SEEK_SET); read(fp, (char *)&l, sizeof(short int)); read(fp, f_name, l); if (header.deleted[j] == 1) { // do nothing because the file is already deleted } else { if (strcmp(argv[k + 3], f_name) == 0) { // check if the filename is the same as the input fprintf(stderr, "%s: file already exists\n", strerror(5)); exit(EXIT_FAILURE); } } } } if (header.next > 0) { number_of_headers++; p = header.next; temp_header_pointer = lseek(fp, header.next, SEEK_SET); r = read(fp, (char *)&header, sizeof(hdr)); } else { not_finished_reading = false; // first file has been iterated through } } #ifdef DEBUG sprintf(buffer, "file \"%s\" is not in archive: writing file\n", argv[k + 3]); write(1, buffer, strlen(buffer)); #endif current_file = argv[k + 3]; temp_sizeof_file = 0; // reset file size counter temp_file_pointer = open(current_file, O_RDWR, 0644); // opens file; // Create Filename, Write to archive Current_EOP = lseek(fp, 0, SEEK_END); temp_filename_pointer = Current_EOP; char_len_buf = strlen(argv[header.block_count]); #ifdef DEBUG sprintf(buffer, "char_len_buf=%i\n", char_len_buf); write(1, buffer, strlen(buffer)); #endif write(fp, &char_len_buf, sizeof(char_len_buf)); // write size Current_EOP = lseek(fp, 0, SEEK_END); #ifdef DEBUG sprintf(buffer, "file \"%s\" : writing filename\n", argv[header.block_count]); write(1, buffer, strlen(buffer)); #endif write(fp, argv[header.block_count], char_len_buf * sizeof(char)); // write title Current_EOP = lseek(fp, 0, SEEK_END); #ifdef DEBUG sprintf(buffer, "file \"%s\" : Write file to archive\n", argv[header.block_count]); write(1, buffer, strlen(buffer)); #endif // Write file to archive temp_file_read = read(temp_file_pointer, &byte, sizeof(byte)); // read first byte Current_EOP = lseek(fp, 0, SEEK_END); temp_sizeof_file += sizeof(byte); // increment the size of file write(fp, &byte, sizeof(byte)); // write first byte int x = 1; while (temp_file_read > 0) { // iterate until it reaches end of file temp_file_read = read(temp_file_pointer, &byte, sizeof(byte)); // read all next bytes if (temp_file_read < 1) { break; // breaks to make sure the last byte isnt written twice } #ifdef DEBUG sprintf(buffer, "Read %d-th byte [file:%d]\n", x, header.block_count - 2); write(1, buffer, strlen(buffer)); #endif write(fp, &byte, sizeof(byte)); // write following byte(s) Current_EOP = lseek(fp, 0, SEEK_END); temp_sizeof_file += sizeof(byte); // increment the size of file #ifdef DEBUG sprintf(buffer, "wrote %d-th byte [file:%d]\n", x, header.block_count - 2); write(1, buffer, strlen(buffer)); #endif x++; } header.file_size[header.block_count] = temp_sizeof_file; header.file_name[header.block_count] = temp_filename_pointer; header.block_count = (header.block_count + 1); #ifdef DEBUG printf("write header %i data\n", i); #endif lseek(fp, temp_header_pointer, SEEK_SET); w = write(fp, (char *)&header, sizeof(header)); if (w < 0) { fprintf(stderr, "%s\n", strerror(5)); exit(EXIT_FAILURE); } if (header.block_count == 8) { Current_EOP = lseek(fp, 0, SEEK_END); header = empty; #ifdef DEBUG printf("write header %i data\n", i); #endif lseek(fp, Current_EOP, SEEK_SET); w = write(fp, (char *)&header, sizeof(header)); if (w < 0) { fprintf(stderr, "%s\n", strerror(5)); exit(EXIT_FAILURE); } } k++; // get the next input } } else { // Delete the file #ifdef DEBUG printf("case -d\n"); #endif hdr header; char f_name[sizeof(short int)]; short int l; int p = 0; int poi; lseek(fp, 0, SEEK_SET); r = read(fp, (char *)&header, sizeof(hdr)); // load first header if (r != sizeof(hdr)) { fprintf(stderr, "%s: file is not the size of a header object", strerror(5)); exit(EXIT_FAILURE); } else if (header.magic != 0x63746172) { fprintf(stderr, "%s: header does not include the magic number", strerror(5)); exit(EXIT_FAILURE); } if (header.block_count == 0) { fprintf(stderr, "%s: Archive is empty\n", strerror(2)); exit(EXIT_FAILURE); } while (true) { for (i = 0; i < header.block_count; i++) { lseek(fp, header.file_name[i], SEEK_SET); read(fp, (char *)&l, sizeof(short int)); read(fp, f_name, l); if (strcmp(argv[3], f_name) == 0) { if (header.deleted[i] == 1) { // do nothing because the file is already deleted } else { header.deleted[i] = (char)1; // set found file to deleted poi = lseek(fp, p, SEEK_SET); w = write(fp, (char *)&header, sizeof(header)); if (w < 0) { fprintf(stderr, "%s\n", strerror(5)); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); } } } if (header.next < 0) { fprintf(stderr, "%s\n", strerror(2)); exit(EXIT_FAILURE); } else { p = header.next; lseek(fp, header.next, SEEK_SET); r = read(fp, (char *)&header, sizeof(hdr)); } } } close(r); close(fp); } return EXIT_SUCCESS; } int archiveexists(char *fname) { if (access(fname, F_OK) != -1) { return true; // file exists } else { return false; // file doesn't exist } }