header.c
unknown
plain_text
2 years ago
13 kB
9
Indexable
#include "header.h"
header *create_header(struct stat sb, char *path){
struct header *curr_header;
struct passwd *file_pwd;
struct group *file_group;
char *size8_buff, *size12_buff, *name_buff;
int chksum_val, linkname_len;
/* Initialize header */
curr_header = malloc(sizeof(header));
if(curr_header == NULL){
perror("malloc");
exit(EXIT_FAILURE);
}
/* Initialize string buffers */
size8_buff = malloc(sizeof(char) * (MODE_SIZE + 1));
if(size8_buff == NULL){
perror("malloc");
exit(EXIT_FAILURE);
}
size12_buff = malloc(sizeof(char) * (FILESIZE_SIZE + 1));
if(size12_buff == NULL){
perror("malloc");
exit(EXIT_FAILURE);
}
/* Call function that packs name and prefix fields */
if(pack_name_and_prefix(path, curr_header) == -1){
free(curr_header);
free(size8_buff);
free(size12_buff);
return NULL;
}
/* Write mode as an octal num and store in header */
if(snprintf(size8_buff, MODE_SIZE, "%07o", (unsigned int) sb.st_mode) < 0){
perror("word overflow");
}
curr_header->mode = strdup(size8_buff);
if(curr_header->mode == NULL){
perror("strdup");
exit(EXIT_FAILURE);
}
/* Write uid as an octal num and store in header */
if(snprintf(size8_buff, UID_SIZE, "%07o", (unsigned int) sb.st_uid) < 0){
perror("word overflow");
}
curr_header->uid = strdup(size8_buff);
if(curr_header->uid == NULL){
perror("strdup");
exit(EXIT_FAILURE);
}
/* Write gid as an octal num and store in header */
if(snprintf(size8_buff, GID_SIZE, "%07o", (unsigned int) sb.st_gid) < 0){
perror("word overflow");
}
curr_header->gid = strdup(size8_buff);
if(curr_header->gid == NULL){
perror("strdup");
exit(EXIT_FAILURE);
}
/* Write size as an octal num and store in header */
if(snprintf(size12_buff, FILESIZE_SIZE, "%011o",
(unsigned int) sb.st_size) < 0){
perror("word overflow");
}
curr_header->size = strdup(size12_buff);
if(curr_header->size == NULL){
perror("strdup");
exit(EXIT_FAILURE);
}
/* Write mtime as an octal num and store in header */
if(snprintf(size12_buff, MTIME_SIZE, "%011o", (unsigned int) sb.st_mtime)
< 0){
perror("word overflow");
}
curr_header->mtime = strdup(size12_buff);
if(curr_header->mtime == NULL){
perror("strdup");
exit(EXIT_FAILURE);
}
if(S_ISREG(sb.st_mode)){
curr_header->typeflag = '0';
}
else if(S_ISDIR(sb.st_mode)){
curr_header->typeflag = '5';
}
else if (S_ISLNK(sb.st_mode)){
curr_header->typeflag = '2';
}
else{
curr_header->typeflag = '\0';
}
/* Adding linkname field */
if(S_ISLNK(sb.st_mode)){
/* Malloc space for name buff */
name_buff = malloc(sizeof(char) * (LINKNAME_SIZE + 1));
if(name_buff == NULL){
perror("malloc");
exit(EXIT_FAILURE);
}
/* Get the file name, on error return NULL */
if((linkname_len = readlink(path, name_buff, LINKNAME_SIZE)) == -1){
perror("readlink");
free(curr_header);
perror("strdup");
exit(EXIT_FAILURE);
}
/* Write mtime as an octal num and store in header */
if(snprintf(size12_buff, MTIME_SIZE, "%011o", (unsigned int) sb.st_mtime)
< 0){
perror("word overflow");
}
curr_header->mtime = strdup(size12_buff);
if(curr_header->mtime == NULL){
perror("strdup");
exit(EXIT_FAILURE);
}
if(S_ISREG(sb.st_mode)){
curr_header->typeflag = '0';
}
else if(S_ISDIR(sb.st_mode)){
curr_header->typeflag = '5';
}
else if (S_ISLNK(sb.st_mode)){
curr_header->typeflag = '2';
}
else{
curr_header->typeflag = '\0';
}
/* Adding linkname field */
if(S_ISLNK(sb.st_mode)){
/* Malloc space for name buff */
name_buff = malloc(sizeof(char) * (LINKNAME_SIZE + 1));
if(name_buff == NULL){
perror("malloc");
exit(EXIT_FAILURE);
}
/* Get the file name, on error return NULL */
if((linkname_len = readlink(path, name_buff, LINKNAME_SIZE)) == -1){
perror("readlink");
free(curr_header);
free(size8_buff);
free(size12_buff);
return NULL;
}
/* Set name buff to header field */
name_buff[linkname_len] = '\0';
curr_header->linkname = strdup(name_buff);
if(curr_header->linkname == NULL){
perror("strdup");
exit(EXIT_FAILURE);
}
free(name_buff);
}
else{
curr_header->linkname = NULL;
}
/* Adding constant header fields */
curr_header->magic = strdup("ustar");
if(curr_header->magic == NULL){
perror("strdup");
exit(EXIT_FAILURE);
}
curr_header->version = strdup("00");
if(curr_header->version == NULL){
perror("strdup");
exit(EXIT_FAILURE);
}
curr_header->devmajor = NULL;
curr_header->devminor = NULL;
/* Get user password for user name */
file_pwd = getpwuid(sb.st_uid);
if(file_pwd == NULL){
perror("getpwuid");
exit(EXIT_FAILURE);
}
/* Get group for group name */
file_group = getgrgid(sb.st_gid);
if(file_group == NULL){
perror("getgrgid");
exit(EXIT_FAILURE);
}
/* Assign user name and group name */
curr_header->uname = strdup(file_pwd->pw_name);
if(curr_header->uname == NULL){
perror("strdup");
exit(EXIT_FAILURE);
}
curr_header->gname = strdup(file_group->gr_name);
if(curr_header->gname == NULL){
perror("strdup");
exit(EXIT_FAILURE);
}
/* Write chksum as an octal num and store in header */
chksum_val = get_chksum_val(curr_header);
if(snprintf(size8_buff, CHKSUM_SIZE, "%07o", chksum_val) < 0){
perror("word overflow");
}
curr_header->chksum = strdup(size8_buff);
if(curr_header->chksum == NULL){
perror("strdup");
exit(EXIT_FAILURE);
}
free(size8_buff);
free(size12_buff);
return curr_header;
}
int pack_name_and_prefix(char *path, header *curr_header){
char *name_buff, *prefix_buff;
size_t path_len;
int i;
prefix_buff = malloc(sizeof(char) * PREFIX_SIZE);
if(prefix_buff == NULL){
perror("malloc");
exit(EXIT_FAILURE);
}
name_buff = malloc(sizeof(char) * NAME_SIZE);
if(name_buff == NULL){
perror("malloc");
exit(EXIT_FAILURE);
}
path_len = strlen(path);
/* Pack name and prefix fields */
if(path_len >= MAX_NAME_LEN){
perror("file name too long");
return -1;
}
else if(path_len < NAME_SIZE){
/* If name fits in name block */
if((curr_header->name = strdup(path)) == NULL){
perror("strdup");
exit(EXIT_FAILURE);
}
curr_header->prefix = NULL;
}
else if(path_len == NAME_SIZE){
/* If name is exactly 100 chars decide if it goes in prefix or name */
for(i = 0; i < NAME_SIZE; i++){
if(path[i] == '\0'){
curr_header->name = NULL;
if((curr_header->prefix = strdup(path)) == NULL){
perror("strdup");
exit(EXIT_FAILURE);
}
}
else if(path[i] == '/'){
if((curr_header->name = strdup(path)) == NULL){
perror("strdup");
exit(EXIT_FAILURE);
}
curr_header->prefix = NULL;
break;
}
}
}
else{
/* Split name at first slash, return -1 if name is too long */
for(i = path_len - NAME_SIZE; i < path_len; i++){
if(path[i] == '/'){
/* Split the path and copy each part to its respective field */
strncpy(prefix_buff, path, i);
strncpy(name_buff, &path[i + 1], path_len - i);
/* Add null char to prefix */
prefix_buff[i] = '\0';
/* Realloc prefix to exact length */
if((prefix_buff = realloc(prefix_buff, i + 1)) == NULL){
perror("realloc");
exit(EXIT_FAILURE);
}
/* Realloc name to exact length */
if((name_buff = realloc(name_buff, path_len - i)) == NULL){
perror("realloc");
exit(EXIT_FAILURE);
}
/* Set name and prefix fields */
curr_header->name = name_buff;
curr_header->prefix = prefix_buff;
return 0;
}
}
/* Name to long, return -1 */
perror("unable to construct header.");
free(prefix_buff);
free(name_buff);
return -1;
}
free(prefix_buff);
free(name_buff);
return 0;
}
unsigned int get_chksum_val(struct header *file_header){
unsigned int chksum_val = 0;
int i;
chksum_val += (unsigned int) file_header->typeflag;
for(i = 0; i < strlen(file_header->uid); i++){
chksum_val += (unsigned int) file_header->uid[i];
}
for(i = 0; i < strlen(file_header->gid); i++){
chksum_val += (unsigned int) file_header->gid[i];
}
for(i = 0; i < strlen(file_header->mtime); i++){
chksum_val += (unsigned int) file_header->mtime[i];
}
for(i = 0; i < strlen(file_header->mode); i++){
chksum_val += (unsigned int) file_header->mode[i];
}
for(i = 0; i < strlen(file_header->magic); i++){
chksum_val += (unsigned int) file_header->magic[i];
}
for(i = 0; i < strlen(file_header->size); i++){
chksum_val += (unsigned int) file_header->size[i];
}
if(file_header->prefix != NULL){
for(i = 0; i < strlen(file_header->prefix); i++){
chksum_val += (unsigned int) file_header->prefix[i];
}
}
if(file_header->name != NULL){
for(i = 0; i < strlen(file_header->name); i++){
chksum_val += (unsigned int) file_header->name[i];
}
}
if(file_header->linkname != NULL){
for(i = 0; i < strlen(file_header->linkname); i++){
chksum_val += (unsigned int) file_header->linkname[i];
}
}
for(i = 0; i < strlen(file_header->uname); i++){
chksum_val += (unsigned int) file_header->uname[i];
}
for(i = 0; i < strlen(file_header->gname); i++){
chksum_val += (unsigned int) file_header->gname[i];
}
return chksum_val;
}
/*this function verifies a header, exits on failure, void on success*/
/*DIFFERENT CHECKS BASED ON -S OPTION*/
void verify_header(header *curr_header){
if(strcmp(curr_header->version, "00") != 0){
perror("Wrong version");
exit(EXIT_FAILURE);
}
if(strcmp(curr_header->magic, "ustar") != 0){
perror("Wrong magic number");
exit(EXIT_FAILURE);
}
/*ADD CHKSUM CHECK*/
}
/* Takes curr path and curr file name and appends them with a / in between */
char *create_full_path(char *parent_path, char *file_name, mode_t file_mode){
char *full_path;
size_t parent_path_len, file_name_len;
int i;
parent_path_len = strlen(parent_path);
file_name_len = strlen(file_name);
/* Malloc string of size path and file name with 2 spaces for null and / */
if(S_ISDIR(file_mode)){
full_path = malloc(parent_path_len + file_name_len + 2);
}
else if(S_ISREG(file_mode) || S_ISLNK(file_mode)){
full_path = malloc(parent_path_len + file_name_len + 1);
}
if(full_path == NULL){
perror("malloc");
exit(EXIT_FAILURE);
}
/* Copy curr path over */
for(i = 0; i < parent_path_len; i++){
full_path[i] = parent_path[i];
}
/* Copy file name over */
for(i = 0; i < file_name_len; i++){
full_path[parent_path_len + i] = file_name[i];
}
/* Add null terminating character and slash */
if(S_ISDIR(file_mode)){
full_path[parent_path_len + file_name_len] = '/';
full_path[parent_path_len + file_name_len + 1] = '\0';
}
else if(S_ISREG(file_mode) || S_ISLNK(file_mode)){
full_path[parent_path_len + file_name_len] = '\0';
}
return full_path;
}Editor is loading...
Leave a Comment