/** Extract files stored in a tarball archive * * tarName: tarball's pathname * * On success, it returns EXIT_SUCCESS; upon error it returns EXIT_FAILURE. * (macros defined in stdlib.h). * * HINTS: First load the tarball's header into memory. * After reading the header, the file position indicator will be located at the * tarball's data section. By using information from the * header --number of files and (file name, file size) pairs--, extract files * stored in the data section of the tarball. * */ int extractTar(char tarName[]) { FILE *tarFile, *outFile; int numFiles,i = 0; stHeaderEntry *header; if (!(tarFile = fopen(tarName, "r"))){ //If we don't have read permission on the .tar file return (EXIT_FAILURE); } //Extracts the name, size and number of files from the .tar header. readHeader(tarFile, &header, &numFiles); for (; i<numFiles; i++){ if (!(outFile = fopen(header[i].name, "w"))){ //If we don't have write permission in the 'extracting' folder. return (EXIT_FAILURE); } copynFile(tarFile, outFile, header[i].size); fclose(outFile); } fclose(tarFile); free(header); return (EXIT_SUCCESS); }
int extractTarDirectory(char* tarName,char* directory) { char *filepath = malloc(strlen(directory) + 1 + strlen(tarName) + 2); filepath = strcpy(filepath, directory); filepath = strcat(filepath, "/"); filepath = strcat(filepath, tarName); if(DEVELOPING == 1) printf("Filepath is %s \n", filepath); // First check if the directory exists. if (0 != access(directory, F_OK)) { if(DEVELOPING == 1) printf("Can't create file at %s\n", directory); return EXIT_FAILURE; } // At this point we know the directory exists. // So create a file if(DEVELOPING == 1) printf("Oh yes. The directory exists :-)\n"); FILE *tarFile = NULL; // file manager stHeaderEntry *stHeader; // Array of structs for header int nr_files = 0, index = 0, copiedBytes = 0; if((tarFile = fopen(tarName, "r")) == NULL) { if(DEVELOPING == 1) printf("Yo! %s file doesn't exit \n", tarName); return (EXIT_FAILURE); // File doesn't exit or there was a problem } if (readHeader(tarFile, &stHeader, &nr_files) == -1) { if(DEVELOPING == 1) printf("We couldn't load the header \n"); return (EXIT_FAILURE); } // Returns in stHeader the array of struct (name/size) for each file and in nr_files the total num of files in the .mtar // Write the content to the outputFile for (index = 0; index < nr_files; index++) { char *destFilename = malloc(strlen(directory) + 1 + strlen(tarName) + 2); destFilename = strcpy(filepath, directory); destFilename = strcat(filepath, "/"); destFilename = strcat(filepath, stHeader[index].name); FILE *destinationFile = NULL; if ((destinationFile = fopen(destFilename, "w")) == NULL) { return EXIT_FAILURE; } // Try to open the output file | return error if we couldn't create the file else { copiedBytes = copynFile(tarFile, destinationFile, stHeader[index].size); // Write nBytes to the output file (where nBytes is obtained when reading the .mtar header) if (copiedBytes == -1) { return EXIT_FAILURE; } } // copied nBytes to output file if(fclose(destinationFile) != 0) { return EXIT_FAILURE; } // close the file } if (fclose(tarFile) == EOF) { return (EXIT_FAILURE); } // Try close file. Return an error if wasn't possible if (DEVELOPING == 1) printf("Yeah. Extract a directory\n"); return 0; }
/** Extract files stored in a tarball archive * * tarName: tarball's pathname * * On success, it returns EXIT_SUCCESS; upon error it returns EXIT_FAILURE. * (macros defined in stdlib.h). * * HINTS: First load the tarball's header into memory. * After reading the header, the file position indicator will be located at the * tarball's data section. By using information from the * header --number of files and (file name, file size) pairs--, extract files * stored in the data section of the tarball. * */ int extractTar(char tarName[]) { FILE *tarFile = NULL; // file manager FILE *destinationFile = NULL; stHeaderEntry *stHeader; // Array of structs for header int nr_files = 0, index = 0, copiedBytes = 0; if((tarFile = fopen(tarName, "r") ) == NULL) { if(DEVELOPING == 1) printf("Yo! %s file doesn't exit \n", tarName); return (EXIT_FAILURE); // File doesn't exit or there was a problem } if (readHeader(tarFile, &stHeader, &nr_files) == -1) { if(DEVELOPING == 1) printf("We couldn't load the header \n"); return (EXIT_FAILURE); } // Returns in stHeader the array of struct (name/size) for each file and in nr_files the total num of files in the .mtar // Write the content to the outputFile for (index = 0; index < nr_files; index++) { if ((destinationFile = fopen(stHeader[index].name, "w")) == NULL) { return EXIT_FAILURE; } // Try to open the output file | return error if we couldn't create the file else { copiedBytes = copynFile(tarFile, destinationFile, stHeader[index].size); // Write nBytes to the output file (where nBytes is obtained when reading the .mtar header) if (copiedBytes == -1) { return EXIT_FAILURE; } } // copied nBytes to output file if(fclose(destinationFile) != 0) { return EXIT_FAILURE; } // close the file } // DEBUG STUFF if(DEVELOPING == 1) { printf("Number of files is %d\n", nr_files); for (index = 0; index <nr_files;index++) { printf("File %s size is %d bytes\n", stHeader[index].name, stHeader[index].size); } } // FREE MEMORY for (index = 0; index <nr_files; index++) { free(stHeader[index].name); } free(stHeader); // Delete main struct if (fclose(tarFile) == EOF) { return (EXIT_FAILURE); } // Try close file. Return an error if wasn't possible return (EXIT_SUCCESS); }
/** Extract files stored in a tarball archive * * tarName: tarball's pathname * * On success, it returns EXIT_SUCCESS; upon error it returns EXIT_FAILURE. * (macros defined in stdlib.h). * * HINTS: First load the tarball's header into memory. * After reading the header, the file position indicator will be located at the * tarball's data section. By using information from the * header --number of files and (file name, file size) pairs--, extract files * stored in the data section of the tarball. * */ int extractTar(char tarName[]) { if(!esTar(tarName)){ printf("Incorrect file extension\n"); return EXIT_FAILURE; } //COMPROBACION DE QUE EL ARCHIVO .mtar EXISTE FILE *tarFile, *f; if((tarFile = fopen(tarName,"r")) == NULL){ printf("The file %s doesn't exist\n", tarName); return EXIT_FAILURE; } int nFiles, i=0; stHeaderEntry *header; //OBTENCION DE LOS DATOS DE LA CABECERA readHeader(tarFile, &header, &nFiles); //Obtencion de la cabecera del archivo .mtar //CREACION Y COPIADO DEL CONTENIDO DEL ARCHIVO .mtar EN CADA UNO DE LOS ARCHIVOS CONTENIDOS for (i=0; i < nFiles; i++) { f = fopen(header[i].name, "w"); if((copynFile(tarFile, f, header[i].size)) != header[i].size){ fclose(f); printf("The %s file has been copied incorrectly\n", header[i].name); return EXIT_FAILURE; } fclose(f); } fclose(tarFile); return 0; }
/** Creates a tarball archive * * nfiles: number of files to be stored in the tarball * filenames: array with the path names of the files to be included in the tarball * tarname: name of the tarball archive * * On success, it returns EXIT_SUCCESS; upon error it returns EXIT_FAILURE. * (macros defined in stdlib.h). * * HINTS: First reserve room in the file to store the tarball header. * Move the file's position indicator to the data section (skip the header) * and dump the contents of the source files (one by one) in the tarball archive. * At the same time, build the representation of the tarball header in memory. * Finally, rewind the file's position indicator, write the number of files as well as * the (file name,file size) pairs in the tar archive. * * Important reminder: to calculate the room needed for the header, a simple sizeof * of stHeaderEntry will not work. Bear in mind that, on disk, file names found in (name,size) * pairs occupy strlen(name)+1 bytes. * */ int createTar(int nFiles, char *fileNames[], char tarName[]) { if(!esTar(tarName)){ printf("Incorrect file extension\n"); return EXIT_FAILURE; } FILE *tarFile = fopen(tarName,"w"), *f; stHeaderEntry *header = (stHeaderEntry*)malloc(nFiles * sizeof(stHeaderEntry)); // Reservamos espacio para las cabeceras int i; char caracter, *buffer; //COMPROBACION DE LA EXISTENCIA DE TODOS LOS ARCHIVOS for(i = 0; i < nFiles; i++){ //si alguno no se puede abrir ya no se ejecuta mas programa if((f=fopen(fileNames[i], "r"))==NULL){ printf("The file %s doesn't exist\n", fileNames[i]); return EXIT_FAILURE; } else fclose(f); } //CREACION DEL HEADER for(i = 0; i < nFiles; i++){ //Rellenamos las cabeceras if((header[i].name = (char*)malloc(strlen(fileNames[i]))) == NULL) return EXIT_FAILURE; strcpy(header[i].name, fileNames[i]); //Copiamos el valor de filenames a header[i] } //AVANZAR CURSOR HASTA DEJAR ESPACIO PARA EL HEADER fseek(tarFile, sizeof(int)+1, SEEK_SET); //Dejamos espacio para nFiles for(i = 0; i < nFiles; i++){ //Dejamos espacio para el nombre y el entero del tamaño fseek(tarFile, strlen(header[i].name)+1, SEEK_CUR); //+1 para el \0 del nombre fseek(tarFile, sizeof(int)+1, SEEK_CUR); //+1 para el \0 del tamanio } //EMPEZAMOS A ESCRIBIR LOS DATOS DE LOS FICHEROS for(i = 0; i < nFiles; i++){ FILE *fichero = fopen(header[i].name, "r"); fseek(fichero, 0, SEEK_END); //Desplazamos el cursor hasta el final del fichero para obtener el numero de bytes del mismo header[i].size = ftell(fichero); //Lo guardamos en la estructura de la cabecera y volvemos a poner el cursor al principio fseek(fichero, 0, SEEK_SET); if((copynFile(fichero, tarFile, header[i].size)) != header[i].size){ //Copiamos el contenido del archivo al mtar y si el tamaño fclose(fichero); //que devuelve no es igual al que tenia que haber copiado printf("The %s file has been copied incorrectly\n", header[i].name);//entonces devuelve error return EXIT_FAILURE; } fclose(fichero); } //VOLVEMOS A PONER EL CURSOR AL COMIENZO rewind(tarFile); //ESCRIBIMOS EL HEADER fwrite(&nFiles, sizeof(int),1, tarFile); fputc('\0',tarFile); for(i = 0; i < nFiles; i++){ fwrite(header[i].name, 1, strlen(header[i].name), tarFile); fputc('\0',tarFile); fwrite(&header[i].size, sizeof(int),1, tarFile); fputc('\0',tarFile); } free(header); fclose(tarFile); return 0; }
/** Creates a tarball archive * * nfiles: number of files to be stored in the tarball * filenames: array with the path names of the files to be included in the tarball * tarname: name of the tarball archive * * On success, it returns EXIT_SUCCESS; upon error it returns EXIT_FAILURE. * (macros defined in stdlib.h). * * HINTS: First reserve room in the file to store the tarball header. * Move the file's position indicator to the data section (skip the header) * and dump the contents of the source files (one by one) in the tarball archive. * At the same time, build the representation of the tarball header in memory. * Finally, rewind the file's position indicator, write the number of files as well as * the (file name,file size) pairs in the tar archive. * * Important reminder: to calculate the room needed for the header, a simple sizeof * of stHeaderEntry will not work. Bear in mind that, on disk, file names found in (name,size) * pairs occupy strlen(name)+1 bytes. * */ int createTar(int nFiles, char *fileNames[], char tarName[]) { FILE *tarFile, *inFile; int headerSize = sizeof(int); stHeaderEntry *header; if (nFiles <=0){ //This shouldn't happen, but we never know. return (EXIT_FAILURE); } if (!(tarFile = fopen(tarName, "w"))){ //If we try to execute from a folder with read only permissions. return (EXIT_FAILURE); } if (!(header = malloc(sizeof(stHeaderEntry)*nFiles))){ //If we can't allocate memory we fail. fclose(tarFile); remove(tarName); return(EXIT_FAILURE); } int i = 0; //We calculate how much memory we need for the header for(; i<nFiles; i++){ headerSize += sizeof(unsigned int); headerSize += sizeof(char)*((strlen(fileNames[i]))+1); } fseek(tarFile, headerSize, SEEK_SET); //Open the tarFile after the header i=0; for (; i<nFiles; i++){ /** * We dump every file's name, size (calculated with the * reading pointer) into our allocated header, and the * content from the the original file into the .tar. */ if ((inFile = fopen(fileNames[i], "r+"))==NULL){ fclose(tarFile); remove(tarName); return(EXIT_FAILURE); } header[i].name = fileNames[i]; fseek(inFile, 0L, SEEK_END); header[i].size = ftell(inFile); fseek(inFile, 0L, SEEK_SET); copynFile(inFile,tarFile,header[i].size); } //The number of files is written at the start of the file fseek(tarFile, 0L, SEEK_SET); fwrite(&nFiles, sizeof(int), 1, tarFile); i=0; for(; i<nFiles; i++){ /** * Lastly, the headear is copied into the file, following * the number of files, and before the actual files. */ fwrite(header[i].name, strlen(fileNames[i])+1, 1, tarFile); fwrite(&header[i].size, sizeof(unsigned int), 1, tarFile); } fclose(tarFile); free(header); return(EXIT_SUCCESS); }
int createTar(int nFiles, char *fileNames[], char tarName[]) { FILE * inputFile; // Used for reading each .txt file FILE * outputFile; // Used for writing in the output file. int copiedBytes = 0, stHeaderBytes = 0, index = 0; stHeaderEntry *stHeader; // Pointer to the program header struct. // Create a stHeader in the heap with the correct size stHeader = malloc(sizeof(stHeaderEntry) * nFiles); // Allocate memory for an array of stHeader Structs stHeaderBytes += sizeof(int); // One integer for the number of files (written at the beginning of the file) stHeaderBytes += nFiles*sizeof(unsigned int); // other int for each struct to store the bytes (aka size) of the file for (index=0; index < nFiles; index++) { stHeaderBytes+=strlen(fileNames[index])+1; // Sum the bytes for each filename (+1 for the '\0' character) } outputFile = fopen(tarName, "w"); // Open the name.mtar file for writing the header and data of the files. fseek(outputFile, stHeaderBytes, SEEK_SET); // Move Outputfile pointer to the "data" section (leaving space for the header we'll write at the end of this function) for (index=0; index < nFiles; index++) { if ((inputFile = fopen(fileNames[index], "r")) == NULL) { if(DEVELOPING == 1) printf("Yo! File: %s doesn't exist\n", fileNames[index]); return (EXIT_FAILURE); } // Try to open the file. EXIT_FAILURE will be returned if errors copiedBytes = copynFile(inputFile, outputFile, INT_MAX); // Copy N bytes to the output file (INT_MAX == huge number to ensure you copy all the character) if (copiedBytes == -1) { if (DEVELOPING == 1) printf("Copied bytes in the create tar is: %d\n", copiedBytes); return EXIT_FAILURE; } else { stHeader[index].size = copiedBytes; // Set the size from the copiedBytes for each struct. stHeader[index].name = malloc(sizeof(fileNames[index]) + 1); // Heap space for the name char + '\0' character strcpy(stHeader[index].name, fileNames[index]); // Copy one string to the struct entry if (DEVELOPING == 1) printf("File %s size is %d bytes\n", stHeader[index].name, stHeader[index].size); } if (fclose(inputFile) == EOF) return EXIT_FAILURE; // Wasn't possible to close the file. Return and error } // Now move the file pointer to the beggining of the file in order to write: number of files + the header for each file if (fseek(outputFile, 0, SEEK_SET) != 0) return (EXIT_FAILURE); // wasn't possible to move the pointer to the beginning of the file. Returns and error else fwrite(&nFiles, sizeof(int), 1, outputFile); // write Number of Files in the output .tar // Write header for each struct // Documentation: http://www.tutorialspoint.com/c_standard_library/c_function_fwrite.htm for (index = 0; index < nFiles; index++) { fwrite(stHeader[index].name, strlen(stHeader[index].name)+1, 1, outputFile); // Important add one when saving the length for the name (for the '\0' character) fwrite(&stHeader[index].size, sizeof(unsigned int), 1, outputFile); // Write one byte // printf("%d\n", stHeader[index].size); } // FREE MEMORY. First, delete the char *names pointer. // Then erase all the structs. for (index=0; index < nFiles; index++) { free(stHeader[index].name); // Free the filenames array of characters } free(stHeader); // Free the struct created in heap if (fclose(outputFile) == EOF) { return (EXIT_FAILURE); } // Try close file. Return an error if wasn't possible printf("mtar file created successfully\n"); return (EXIT_SUCCESS); }