first commit
This commit is contained in:
commit
a6dac2e2dc
|
@ -0,0 +1,9 @@
|
||||||
|
all: ctar utar dump
|
||||||
|
|
||||||
|
ctar: ctar.c; gcc -o ctar ctar.c
|
||||||
|
|
||||||
|
utar: utar.c; gcc -o utar utar.c
|
||||||
|
|
||||||
|
dump: dumparchiveheader.c; gcc -o dump dumparchiveheader.c
|
||||||
|
|
||||||
|
clean:; rm -f ctar ; rm -f utar ; rm -f dump
|
|
@ -0,0 +1,3 @@
|
||||||
|
A simple `tar` and `untar` program
|
||||||
|
|
||||||
|
Also includes a `dump` program to check if the archive header is valid
|
|
@ -0,0 +1,549 @@
|
||||||
|
#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>
|
||||||
|
|
||||||
|
#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) <archive file name> <file name> \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 <archive file name> 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 <archive file name> <file name>\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) <archive file name> <file name>\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
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "tar.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char *name = argv[1]; // name of archive
|
||||||
|
int numberoffiles = argc - 3;
|
||||||
|
char buffer[300]; // character buffer for write
|
||||||
|
int fp, r, i, p;
|
||||||
|
|
||||||
|
if (argc != 2)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: Usage: dah filename \n", strerror(5));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
fp = open(name, O_RDONLY, 0644); // opens file; creates it if it does not exist;
|
||||||
|
if (fp < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "cannot open %s because of %s\n", name, strerror(5));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
write(1, "\n", 1);
|
||||||
|
|
||||||
|
hdr header;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
r = read(fp, &header, sizeof(hdr));
|
||||||
|
if (r != sizeof(hdr))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: file is not the size of a header object\n", strerror(5));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
else if (header.magic != 0x63746172)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: header does not include the magic number [magic number is: %x]\n", strerror(5), header.magic);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
printf("magic number is: %x\n", header.magic);
|
||||||
|
printf("The end of file pointer is at: %i\n", header.eop);
|
||||||
|
printf("number of used blocks are: %i\n", header.block_count);
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
printf("The filesize of block [%i] is %i\n", i, header.file_size[i]);
|
||||||
|
}
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
printf("Is block [%i] deleted? (1=true, 0=false): %i\n", i, header.deleted[i]);
|
||||||
|
}
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
printf("The filename in block [%i] is %i\n", i, header.file_name[i]);
|
||||||
|
}
|
||||||
|
printf("The next header is at: %i\n", header.next);
|
||||||
|
|
||||||
|
if (header.next < 0)
|
||||||
|
{
|
||||||
|
printf("End of headers\n");
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = header.next;
|
||||||
|
lseek(fp, header.next, SEEK_SET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(r);
|
||||||
|
close(fp);
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef TAR_
|
||||||
|
#define TAR_
|
||||||
|
|
||||||
|
#define true 1
|
||||||
|
#define false 0
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int magic; /* This value must be 0x63746172 */
|
||||||
|
int eop; /* End of file pointer */
|
||||||
|
int block_count; /* Number of entries in the block which are in use */
|
||||||
|
int file_size[8]; /* File size in bytes for files 1..8 */
|
||||||
|
char deleted[8]; /* Contains binary one at position i if i-th entry was deleted */
|
||||||
|
int file_name[8]; /* pointer to the name of the file. */
|
||||||
|
int next; /* pointer to the next header block */
|
||||||
|
} hdr;
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,122 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "tar.h"
|
||||||
|
|
||||||
|
int fileexists(char *fname);
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char *name = argv[1]; // name of archive
|
||||||
|
char buffer[300]; // character buffer for sprintf
|
||||||
|
int fp, r, i, j, p, w; // counters and pointers
|
||||||
|
|
||||||
|
if (argc != 2)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s:\n Usage: utar filename \n", strerror(5));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileexists(name) == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "archive doesnt exist%s\n", strerror(2));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
fp = open(name, O_RDONLY, 0644); // opens file; creates it if it does not exist;
|
||||||
|
if (fp < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "cannot open %s because of %s\n", argv[2], strerror(5));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
hdr header;
|
||||||
|
int tempfp;
|
||||||
|
char byte;
|
||||||
|
char f_name[sizeof(short int)];
|
||||||
|
short int l;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
|
||||||
|
r = read(fp, &header, sizeof(hdr));
|
||||||
|
if (r != sizeof(hdr))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: file is not the size of a header object\n", strerror(5));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
else if (header.magic != 0x63746172)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: header does not include the magic number [magic number is: %x]\n", strerror(5), header.magic);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < header.block_count; i++)
|
||||||
|
{
|
||||||
|
if (header.deleted[i] == 1)
|
||||||
|
{
|
||||||
|
// skip it
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lseek(fp, header.file_name[i], SEEK_SET);
|
||||||
|
read(fp, (char *)&l, sizeof(short int));
|
||||||
|
read(fp, f_name, l);
|
||||||
|
|
||||||
|
if (fileexists(f_name))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s\n", strerror(17));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
tempfp = open(f_name, O_RDWR | O_CREAT, 0644); // creates the new file;
|
||||||
|
for (j = 0; j < header.file_size[i]; j++)
|
||||||
|
{
|
||||||
|
r = read(fp, &byte, sizeof(byte));
|
||||||
|
if (r < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: file %s could not be read from archive\n", f_name, strerror(5));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
w = write(tempfp, &byte, sizeof(byte));
|
||||||
|
if (w < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: file %s could not be written to file\n", f_name, strerror(5));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header.next < 0)
|
||||||
|
{
|
||||||
|
printf("Untared Successfully\n");
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = header.next;
|
||||||
|
lseek(fp, header.next, SEEK_SET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fileexists(char *fname)
|
||||||
|
{
|
||||||
|
if (open(fname, O_RDONLY, 0644) < 0)
|
||||||
|
{
|
||||||
|
return false; // file doesn't exist
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true; // file exists
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue