Created
March 19, 2014 17:43
-
-
Save ahmpro/9647221 to your computer and use it in GitHub Desktop.
Simple file archiver. Make for lab in MAI(Russia).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* File: zupper.c | |
* Copyright 2014 L1S & ahmpro | |
*/ | |
#include <stdio.h> | |
#include <dirent.h> | |
#include <fcntl.h> | |
#include <string.h> | |
#include <sys/stat.h> | |
#include <sys/types.h> | |
#include <unistd.h> | |
#include <stdlib.h> | |
#define BUF_SIZE 8192 | |
struct zup_attr { | |
char name_file[128]; | |
unsigned long protection; | |
long long size_file; | |
}; | |
int error_out(int in_fd, int out_fd, struct zup_attr *my_attr, DIR *pDir) | |
{ | |
if (in_fd != 0) | |
close(in_fd); | |
if (!out_fd != 0) | |
close(out_fd); | |
if (my_attr != NULL) | |
free(my_attr); | |
closedir(pDir); | |
return 0; | |
} | |
int zupping(char **argv) | |
{ | |
int in_fd = 0, out_fd = 0; | |
char buf[BUF_SIZE]; | |
int FN = -1;/*files number*/ | |
int stat_d; | |
int ret_out, ret_in; | |
DIR *pDir = NULL; | |
struct dirent *pDirent; | |
struct zup_attr *my_attr, *temp_attr; | |
struct stat attrib; | |
long META_SIZE; | |
printf("Zupping\npath = [%s]\nfile = [%s]\n", argv[1], argv[2]); | |
pDir = opendir(argv[1]); | |
if (pDir == NULL) { | |
printf("Cannot open directory '%s'`\n", argv[1]); | |
return 0; | |
} | |
out_fd = open(argv[2], O_WRONLY | O_CREAT, 0644); | |
if (out_fd == -1) { | |
printf("Error in openning the output file\n"); | |
return error_out(in_fd, out_fd, NULL, pDir); | |
} | |
my_attr = (struct zup_attr *) malloc(1); | |
while ((pDirent = readdir(pDir)) != NULL) { | |
if (strcmp(pDirent->d_name, ".") != 0 | |
&& strcmp(pDirent->d_name, "..") != 0) { | |
chdir(argv[1]); | |
in_fd = open((pDirent->d_name), O_RDONLY); | |
if (in_fd == -1) { | |
printf("Error in openning the input file\n"); | |
return error_out(in_fd, out_fd, my_attr, pDir); | |
} else { | |
stat_d = fstat(in_fd, &attrib); | |
if (stat_d == 0) { | |
FN++; | |
my_attr[FN].size_file = attrib.st_size; | |
my_attr[FN].protection = attrib.st_mode; | |
strcpy(my_attr[FN].name_file, pDirent->d_name); | |
temp_attr = (struct zup_attr *) realloc(my_attr, FN+1); | |
if (temp_attr == NULL) | |
return error_out(in_fd, out_fd, my_attr, pDir); | |
my_attr = temp_attr; | |
while ((ret_in = read(in_fd, &buf, BUF_SIZE)) > 0) { | |
ret_out = write(out_fd, &buf, ret_in); | |
if (ret_out != ret_in) { | |
printf("Error in writing file [%s]\n", | |
pDirent->d_name); | |
return error_out(in_fd, out_fd, my_attr, pDir); | |
} | |
} | |
printf("zupped file [%s]\n", my_attr[FN].name_file); | |
} else { | |
printf("stat not readed\n"); | |
return error_out(in_fd, out_fd, my_attr, pDir); | |
} | |
close(in_fd); | |
} | |
} | |
} | |
META_SIZE = sizeof(struct zup_attr)*(FN+1); | |
ret_out = write(out_fd, my_attr, META_SIZE); | |
if (ret_out != META_SIZE) { | |
printf("Error in writing meta\n"); | |
return error_out(in_fd, out_fd, my_attr, pDir); | |
} | |
ret_out = write(out_fd, &FN, sizeof(int)); | |
if (ret_out != sizeof(int)) { | |
printf("Error in writing amount files\n"); | |
return error_out(in_fd, out_fd, my_attr, pDir); | |
} | |
error_out(in_fd, out_fd, my_attr, pDir); | |
printf("Zupping complete\n"); | |
return 0; | |
} | |
int unzupping(char **argv) | |
{ | |
int Temp, i; | |
int in_fd = 0, out_fd = 0; | |
char buf[BUF_SIZE]; | |
int FN; | |
int ret_out, ret_in; | |
struct zup_attr *my_attr; | |
long META_SIZE; | |
printf("Unzupping\nfile = [%s]\npath = [%s]\n", argv[1], argv[2]); | |
in_fd = open(argv[1], O_RDONLY); | |
if (in_fd == -1) { | |
printf("Error in openning the input file[%s]\n", argv[1]); | |
return error_out(in_fd, out_fd, NULL, NULL); | |
} | |
if (lseek(in_fd, (-sizeof(int)), SEEK_END) == -1) { | |
printf("Seek Failed to read FN\n"); | |
return error_out(in_fd, out_fd, NULL, NULL); | |
} | |
ret_in = read(in_fd, &FN, sizeof(int)); | |
if (ret_in != sizeof(int)) { | |
printf("Error in reading FN\n"); | |
return error_out(in_fd, out_fd, NULL, NULL); | |
} | |
my_attr = (struct zup_attr *) malloc(FN+1); | |
META_SIZE = sizeof(struct zup_attr)*(FN+1); | |
if (lseek(in_fd, -(META_SIZE+sizeof(int)), SEEK_END) == -1) { | |
printf("Seek Failed to META\n"); | |
return error_out(in_fd, out_fd, my_attr, NULL); | |
} | |
ret_in = read(in_fd, my_attr, META_SIZE); | |
if (ret_in != META_SIZE) { | |
printf("Meta not readed\n"); | |
return error_out(in_fd, out_fd, my_attr, NULL); | |
} | |
if (lseek(in_fd, 0L, SEEK_SET) == -1) { | |
printf("Seek Failed to BEGIN\n"); | |
return error_out(in_fd, out_fd, my_attr, NULL); | |
} | |
Temp = mkdir(argv[2], 0777); | |
if (Temp == -1) { | |
printf("Cannot create directory '%s'`\n", argv[2]); | |
return error_out(in_fd, out_fd, my_attr, NULL); | |
} | |
if (chdir(argv[2]) != 0) { | |
printf("Error change directory\n"); | |
error_out(in_fd, out_fd, my_attr, NULL); | |
} | |
for (i = 0; i <= FN; i++) { | |
out_fd = open(my_attr[i].name_file, | |
O_WRONLY | O_CREAT, | |
my_attr[i].protection); | |
if (out_fd == -1) { | |
printf("Error in openning the output file\n"); | |
return error_out(in_fd, out_fd, my_attr, NULL); | |
} | |
Temp = my_attr[i].size_file; | |
while (Temp > 0) { | |
ret_in = read(in_fd, &buf, Temp > BUF_SIZE?BUF_SIZE:Temp); | |
ret_out = write(out_fd, &buf, ret_in); | |
if (ret_out != ret_in) { | |
printf("Error in writing file [%s]\n", | |
my_attr[i].name_file); | |
} | |
Temp = Temp-BUF_SIZE; | |
} | |
printf("unzupped file [%s]\n", my_attr[i].name_file); | |
close(out_fd); | |
} | |
close(in_fd); | |
free(my_attr); | |
printf("Unzupping complete\n"); | |
return 0; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
if (argc != 3) { | |
printf("Usage: %s <dirname>\n", argv[0]); | |
return 1; | |
} | |
if (strstr(argv[1], ".zup") == NULL) | |
zupping(argv); | |
else | |
unzupping(argv); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment