stuffy/src/stuffy.c

247 lines
7.6 KiB
C
Raw Normal View History

2022-11-08 20:37:57 -06:00
#include <fcntl.h>
2022-11-02 15:29:00 -05:00
#include <stdio.h>
#include <stdlib.h>
2022-11-08 20:37:57 -06:00
#include <string.h>
2022-11-02 15:29:00 -05:00
#include <unistd.h>
2022-11-08 20:37:57 -06:00
#include <sys/types.h>
2022-11-02 15:29:00 -05:00
#include "stuffy.h"
2022-11-10 18:30:35 -06:00
// Put a module header into a HeaderStruct and read (skip) module data
// Returns size of data read when reading a module header
int ReadSingleModule(int fd, ModuleStruct* module)
{
int readSize;
long long int moduleSize;
readSize = read(fd, &(module->moduleHeader), sizeof(module->moduleHeader));
2022-11-10 18:30:35 -06:00
moduleSize = (long long) module->moduleHeader.moduleInfo.st_size;
module->moduleData = malloc(moduleSize);
readSize = read(fd, module->moduleData, moduleSize);
return readSize;
}
// Put a module header into a HeaderStruct and read (skip) module data
// Returns size of data read when reading a module header
int WriteSingleModule(int fd, ModuleStruct* module, char* filename)
{
int writeSize;
long long int moduleSize;
moduleSize = (long long) module->moduleHeader.moduleInfo.st_size;
module->moduleData = malloc(moduleSize);
int fdInput = open(filename, O_RDONLY);
if (fdInput < 0)
return 0;
read(fdInput, module->moduleData, moduleSize);
close(fdInput);
writeSize = write(fd, &(module->moduleHeader), sizeof(module->moduleHeader));
writeSize = write(fd, module->moduleData, moduleSize);
return writeSize;
2022-11-10 18:30:35 -06:00
}
// Checks if operation went ok, if not then prints message and exits
void SafetyCheck(int status, char* message)
{
if (status)
{
fprintf(stderr, "%s\n", message);
exit(1);
}
return;
}
// Strip path from filename for adding to archive
char* StripFilename(char* filename)
{
int nameStartPosition = -1;
for (int i = 0; i < strlen(filename); i++)
if (filename[i] == '/')
nameStartPosition = i+1;
if (nameStartPosition == -1)
nameStartPosition = 0;
int copySize = strlen(filename) - nameStartPosition;
char* newFilename = malloc(copySize + 1);
strncpy(newFilename, &filename[nameStartPosition], copySize);
strcat(newFilename, "\0");
return newFilename;
}
// Overhead function for archive operations
2022-11-02 15:29:00 -05:00
void Stuffy(int argc, char* argv[])
{
int archiveAction = StuffyArgument(argc, argv);
if (archiveAction < 0)
{
fprintf(stderr, "Usage: stuffy.out [OPTION] [ARCHIVE] [FILE]");
exit(1);
}
StuffyAction(argv, archiveAction);
return;
}
2022-11-10 18:30:35 -06:00
// Checks for argument, if argument is found then returns argument number.
// Returns -1 if not found
2022-11-02 15:29:00 -05:00
int StuffyArgument(int argc, char* argv[])
{
for (int i = 1; i < argc; i++)
{
if ((argv[i][0] == '-') && (argv[i][1] == 'a'))
return 0;
if ((argv[i][0] == '-') && (argv[i][1] == 'r'))
return 1;
if ((argv[i][0] == '-') && (argv[i][1] == 'l'))
return 2;
if ((argv[i][0] == '-') && (argv[i][1] == 'e'))
return 3;
}
return -1;
}
2022-11-10 18:30:35 -06:00
// Redirects program to necessary action function
2022-11-02 15:29:00 -05:00
void StuffyAction(char* argv[], int archiveAction)
{
2022-11-08 20:37:57 -06:00
if (archiveAction == 0)
AddToArchive(argv[2], argv[3]);
if (archiveAction == 1)
RemoveFromArchive(argv[2], argv[3]);
if (archiveAction == 2)
ListArchive(argv[2]);
if (archiveAction == 3)
ExtractArchive(argv);
2022-11-10 22:10:49 -06:00
return;
2022-11-08 20:37:57 -06:00
}
2022-11-10 18:30:35 -06:00
// Checks if filename is found in a header of archive
int IsFileArchived(char* archiveName, char* filename)
2022-11-08 20:37:57 -06:00
{
2022-11-10 18:30:35 -06:00
ModuleStruct module;
ssize_t readSize;
char* newFilename = StripFilename(filename);
int archiveFile = open(archiveName, O_RDONLY | O_CREAT, 0644);
SafetyCheck((archiveFile < 0), "Archive failed to open.");
do
2022-11-08 20:37:57 -06:00
{
2022-11-10 18:30:35 -06:00
readSize = ReadSingleModule(archiveFile, &(module));
free(module.moduleData);
if (strcmp(module.moduleHeader.moduleName, filename) == 0)
2022-11-10 18:30:35 -06:00
{
free(newFilename);
close(archiveFile);
2022-11-08 20:37:57 -06:00
return 1;
2022-11-10 18:30:35 -06:00
}
} while (readSize > 0);
free(newFilename);
close(archiveFile);
2022-11-08 20:37:57 -06:00
return 0;
2022-11-02 15:29:00 -05:00
}
2022-11-10 18:30:35 -06:00
// Check through archive for file, if in archive then inform user
// Adds file to archive and can be repeatedly used to add more to the archive
// If file is already in archive, then exit, let user know, and suggest removing
// file already inside the archive
void AddToArchive(char* archiveName, char* filename)
2022-11-02 15:29:00 -05:00
{
2022-11-10 22:10:49 -06:00
char* filenameCleaned = StripFilename(filename);
if (IsFileArchived(archiveName, filenameCleaned))
{
printf("File already exists in archive, try removing file first.");
return;
}
if (access(filename, F_OK))
{
printf("%s not found.", filename);
return;
}
2022-11-08 20:37:57 -06:00
int archiveFile = open(archiveName, O_RDWR | O_CREAT, 0644);
2022-11-10 18:30:35 -06:00
SafetyCheck((archiveFile < 0), "Archive failed to open.");
ssize_t readSize;
ModuleStruct module;
do
readSize = ReadSingleModule(archiveFile, &(module));
while (readSize > 0);
strcpy(module.moduleHeader.moduleName, filenameCleaned);
stat(filename, &(module.moduleHeader.moduleInfo));
WriteSingleModule(archiveFile, &module, filename);
free(filenameCleaned);
2022-11-10 18:30:35 -06:00
free(module.moduleData);
return;
2022-11-02 15:29:00 -05:00
}
2022-11-10 18:30:35 -06:00
// Check through archive for file, if file exists with name, remove it
// If file not in archive, print "somefile was not found."
void RemoveFromArchive(char* archiveName, char* filename)
2022-11-02 15:29:00 -05:00
{
ssize_t readSize;
2022-11-10 18:30:35 -06:00
long long int moduleSize;
char* newFileName;
strcpy(newFileName, filename);
strcat(newFileName, ".tmp");
int archiveFile = open(archiveName, O_RDWR | O_CREAT, 0644);
2022-11-10 18:30:35 -06:00
SafetyCheck((archiveFile < 0), "Archive failed to open.");
SafetyCheck(IsFileArchived(archiveName, filename),
strcat("Failed to find ", newFileName));
ModuleStruct module;
int newArchiveFile = open(newFileName, O_WRONLY | O_CREAT, 0644);
SafetyCheck((newArchiveFile < 0), "New archive failed to open.");
do
{
2022-11-10 18:30:35 -06:00
readSize = ReadSingleModule(archiveFile, &(module));
write(newArchiveFile, &module.moduleHeader, sizeof(module.moduleHeader));
write(newArchiveFile, &module.moduleData, moduleSize);
}
2022-11-10 18:30:35 -06:00
while (readSize > 0);
close(archiveFile);
close(newArchiveFile);
SafetyCheck(remove(archiveName), "Old archive failed removal.");
SafetyCheck(rename(newFileName, archiveName),
"New archive failed name change.");
return;
2022-11-02 15:29:00 -05:00
}
2022-11-10 18:30:35 -06:00
// List names and sizes of files stored in archive
// Last line prints total size of all files in archive
2022-11-02 15:29:00 -05:00
void ListArchive(char* archiveName)
{
2022-11-08 20:37:57 -06:00
int archiveFile = open(archiveName, O_RDONLY);
ssize_t readSize;
2022-11-10 18:30:35 -06:00
SafetyCheck((archiveFile < 0), "Archive failed to open.");
ModuleStruct module;
2022-11-10 22:10:49 -06:00
readSize = ReadSingleModule(archiveFile, &module);
while (readSize > 0)
2022-11-08 20:37:57 -06:00
{
printf("Name: %s | Size: %ld\n", module.moduleHeader.moduleName,
module.moduleHeader.moduleInfo.st_size);
2022-11-10 22:10:49 -06:00
readSize = ReadSingleModule(archiveFile, &module);
2022-11-08 20:37:57 -06:00
}
return;
2022-11-02 15:29:00 -05:00
}
int Test_ListArchive(char* archiveName)
{
struct stat statArchive;
int archiveFile = open(archiveName, O_RDONLY);
ssize_t readSize;
long int sizeTotal = 0;
if (archiveFile < 0)
return 0;
ModuleStruct module;
stat(archiveName, &statArchive);
do
{
readSize = ReadSingleModule(archiveFile, &module);
if (readSize > 0)
{
sizeTotal += sizeof(module.moduleHeader);
sizeTotal += module.moduleHeader.moduleInfo.st_size;
}
}
while (readSize > 0);
return (statArchive.st_size == sizeTotal);
}
2022-11-10 18:30:35 -06:00
// Extract data of name file from archive to stdout, which is then redirected
// Extracted data remains in archive
2022-11-08 20:37:57 -06:00
void ExtractArchive(char* argv[])
2022-11-02 15:29:00 -05:00
{
printf("'ExtractArchive()' function is still broken.\n");
return;
2022-11-02 15:29:00 -05:00
}