header.c
unknown
plain_text
a year ago
8.7 kB
8
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, error, 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((error = 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); /* 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); /* 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); /* 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); /* 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(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); free(name_buff); } else{ curr_header->linkname = NULL; } /* Adding constant header fields */ curr_header->magic = strdup("ustar"); curr_header->version = strdup("00"); 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); curr_header->gname = strdup(file_group->gr_name); /* 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); 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; }
Editor is loading...
Leave a Comment