void test1( int* pfailed) { stack_t myStack; char* scenario; int ret; *pfailed = 0; ret = stackCreate( NULL, 0 ); scenario = "creating an empty stack must fail\n"; checkResult( 0, (ret == -1), pfailed, scenario ); ret = stackCreate( &myStack, 0 ); scenario = "creating a stack of no length must fail\n"; checkResult( 1, (ret == -1), pfailed, scenario ); ret = stackCreate( &myStack, 65536 ); scenario = "creating a very big stack must fail\n"; checkResult( 2, (ret == -1), pfailed, scenario ); ret = stackCreate( &myStack, 1024 ); scenario = "creating the max-size stack must succeed\n"; checkResult( 3, (ret == 0), pfailed, scenario ); scenario = "status of the newly-created stack\n"; checkResult( 4, (myStack.state == STACK_CREATED), pfailed, scenario ); scenario = "new stack's index must be at the beginning\n"; checkResult( 5, (myStack.index == 0), pfailed, scenario ); scenario = "top element OK\n"; checkResult( 6, (myStack.max == 1024), pfailed, scenario ); scenario = "stack is non-empty\n"; checkResult( 7, (myStack.storage != (int *)0), pfailed, scenario ); ret = stackDestroy( NULL ); scenario = "destroying an empty stack must fail\n"; checkResult( 8, (ret == -1), pfailed, scenario ); ret = stackDestroy( &myStack ); scenario = "destroying the non-empty stack should be OK\n"; checkResult( 9, (ret == 0), pfailed, scenario ); scenario = "The destroyed stack should be in a non-created state\n"; checkResult( 10, (myStack.state != STACK_CREATED), pfailed, scenario ); if (*pfailed == 0) printf( "test1 passed.\n"); /* all 10 test cases succeeded ? */ else printf("test1 failed\n"); }
int queueDestroy(queue_t * queue){ stackDestroy((queue->s1)); stackDestroy((queue->s2)); return 1; }
void __CUT_TAKEDOWN__Explode(void) { int ret; ret = stackDestroy(&myStack_1); ASSERT((ret == 0), "Stack 1 Destruction."); ret = stackDestroy(&myStack_2); ASSERT((ret == 0), "Stack 2 Destruction."); printf("\n\n Cut test for stack Complete!"); }
void tableDestroy(tableT **tableP) { // destroy stacks -- please kill me, hashtag #pointermadness stackDestroy(&(*tableP)->att); stackDestroy(&(*tableP)->def); // destroy array free((*tableP)->beats); (*tableP)->beats = NULL; // free table memory and reset pointer free(*tableP); *tableP = NULL; }
int main(void) { stack my_stack; /* A stack */ int nums[10]; nums[0]=2; nums[1]=4; nums[2]=8; stackInit(&my_stack, 10); int i; for (i=0;i<3;i++) { push(&my_stack, nums[i]); } printf("\nPopped numbers are: "); while (!checkEmpty(&my_stack)) { printf("%d\n", pop(&my_stack)); } printf("\n"); stackDestroy(&my_stack); return 0; }
void RBDestroy(RBTree* tree){ Stack* stack = (Stack*)malloc(sizeof(Stack)); stackCreate(stack, 16); RBNode* current = tree->nil; do{ if(!stackEmpty(stack)){ current = stackTop(stack); stackPop(stack); }else{ current = tree->root; } if(current->right != tree->nil){ stackPush(stack, current->right); } if(current->left != tree->nil){ stackPush(stack, current->left); } free(current); }while(!stackEmpty(stack)); stackDestroy(stack); free(stack); free(tree->root); free(tree->nil); free(tree); }
int main() { stack s1; stackInit(&s1); stackPush(&s1, "Jag"); stackPush(&s1, "Hans"); stackPush(&s1, "John"); stackPush(&s1, "500"); printf("stack length: %d\n", stackLength(&s1)); printf("stack popped: %s\n", stackPop(&s1)); printf("stack popped: %s\n", stackPop(&s1)); printf("stack popped: %s\n", stackPop(&s1)); printf("stack length: %d\n", stackLength(&s1)); // how to convert an int to a string? char *str = malloc(10 * sizeof(char)); int num = 1250; sprintf(str, "%d", num); stackPush(&s1, str); str = malloc(10 * sizeof(char)); num = 1500; sprintf(str, "%d", num); stackPush(&s1, str); printf("stack length: %d\n", stackLength(&s1)); printf("stack popped: %s\n", stackPop(&s1)); printf("stack popped: %s\n", stackPop(&s1)); printf("stack popped: %s\n", stackPop(&s1)); stackDestroy(&s1); printf("stack length: %d\n", stackLength(&s1)); return 0; }
int* preorderTraversal(struct TreeNode* root, int* returnSize) { *returnSize = 0; if(NULL == root){ return NULL; } Stack* stack = (Stack*)malloc(sizeof(Stack)); stackCreate(stack, 16); int* result = (int*)malloc(sizeof(int)*16); struct TreeNode* current = NULL; do{ if(!stackEmpty(stack)){ current = stackTop(stack); stackPop(stack); }else{ current = root; } result[*returnSize] = current->val; *returnSize = *returnSize + 1; if(*returnSize > 16){ result = (int*)realloc(result, sizeof(int)*(*returnSize+16)); } if(current->right){ stackPush(stack, current->right); } if(current->left){ stackPush(stack, current->left); } }while(!stackEmpty(stack)); stackDestroy(stack); free(stack); return result; }
void postOrder(const char *str, Stack *st) { int i = 0, isBracket = 0; char tmpCh; Token tk; Stack stOp; stackCreate(&stOp); tk._varOp = '\0'; tk._num = 0; while (str[i] != '\0') { if (isLetter(str[i])) { tk._varOp = str[i]; stackPush(st, tk); } else if (isNumber(str[i])) { tk._varOp = '\0'; tk._num = tk._num * 10 + str[i] - '0'; if (str[i + 1] != '.' && !isNumber(str[i + 1])) { stackPush(st, tk); tk._num = 0; } } else if (isOp(str[i])) { tk._varOp = str[i]; if (str[i] == ')') isBracket = 1; else if (str[i] == '-' && (i == 0 || str[i - 1] == '(')) { tmpCh = tk._varOp; tk._varOp = '\0'; tk._num = 0; stackPush(st, tk); tk._varOp = tmpCh; } while (!stackEmpty(&stOp) && (isOpHigh(stackTop(&stOp)._varOp, str[i]) || isBracket)) { if (stackTop(&stOp)._varOp == '(') isBracket = 0; else stackPush(st, stackTop(&stOp)); stackPop(&stOp); } if (str[i] != ')') stackPush(&stOp, tk); } i++; } while (!stackEmpty(&stOp)) { stackPush(st, stackTop(&stOp)); stackPop(&stOp); } stackDestroy(&stOp); }
int main(void) { int action; char expr[255]; Node *root = NULL, *root2 = NULL; Stack stPost; while (1) { printf("Меню:\n"); printf("1) Ввести выражение\n"); printf("2) Печать исходного выражения\n"); printf("3) Печать преобразованного выражения\n"); printf("4) Печать исходного дерева\n"); printf("5) Печать преобразованного дерева\n"); printf("6) Выход\n"); printf("Выберите действие: "); scanf("%d", &action); switch (action) { case 1: { printf("Введите выражение: "); scanf("%s", expr); treeDestroy(&root); treeDestroy(&root2); stackCreate(&stPost); postOrder(expr, &stPost); treeBuild(&root, &stPost); stackDestroy(&stPost); root2 = treeCopy(&root); treeMoveMinus(&root2); break; } case 2: { printf("Исходное выражение: %s\n", expr); break; } case 3: { LKP(&root2); printf("\n"); break; } case 4: { if (root != NULL) { printf("Дерево исходного выражения\n"); PKL(&root, 0); } else printf("Дерево исходного выражения пусто\n"); break; } case 5: { if (root2 != NULL) { printf("Дерево преобразованного выражения\n"); PKL(&root2, 0); } else printf("Дерево преобразованного выражения пусто\n"); break; } case 6: break; default: { printf("Ошибка. Такого пункта меню не существует\n"); break; } } if (action == 6) break; } treeDestroy(&root); treeDestroy(&root2); return 0; }
int dcommand(int argc, char * argv[]){ struct stack * log = stackCreate(); #ifdef DEBUG printf("dcommand\n"); #endif // Get archive name from command line char * arkName = argv[2]; // File descriptor for existing archive int arkiv; // Make sure 'open' is working if(!strcmp(arkName, "-")){ // If archive name is '-' then read from std_in arkiv = STDIN_FILENO; } else if ((arkiv = open(arkName, O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR)) == -1){ snprintf(errDesc, ERR_STATUS_LENGTH, "opening initial archive %s", arkName); return -1; } /* Make new archive (temporary) to copy to * ... if it succeeds, we will keep temp archive * else we will unlink it. */ int newArkiv; char tmpName [PATH_MAX]; if(!strcmp(arkName, "-")){ newArkiv = STDOUT_FILENO; }else{ snprintf(tmpName, PATH_MAX, "%sXXXXXX", arkName); if ((newArkiv = mkstemp(tmpName)) == -1){ snprintf(errDesc, ERR_STATUS_LENGTH, "making new tmp archive with name %s", tmpName); return -1; } } // Variable to store filesize of current archive off_t fileSize; // Read through archive 'arkiv' // For each file, filesize is stored, then file's name, terminated by null char #ifdef DEBUG printf(" scanning through archive\n"); #endif dreadloop: while(read(arkiv, &fileSize, sizeof(off_t)) > 0){ // File's name char nameBuffer[PATH_MAX]; // Read into nameBuffer until null char int posInNameBuff = 0; while(read(arkiv, nameBuffer + posInNameBuff, 1) == 1 && nameBuffer[posInNameBuff++] != '\0'); // Do we have a valid file? if(strlen(nameBuffer) < 1){ // Abort mission. Roll back. snprintf(errDesc, ERR_STATUS_LENGTH, "reading file '%s' with name less than one char from archive %s", nameBuffer, arkName); return -1; } // Check if this file is in command line for(int i = 3; i < argc; i++){ // If 'zoo' is in command line, also check for 'zoo/' char asDirectoryName[PATH_MAX]; strcpy(asDirectoryName, argv[i]); if(asDirectoryName[strlen(asDirectoryName) - 1] != '/') strcat(asDirectoryName, "/"); if(!strcmp(nameBuffer, argv[i]) || !strcmp(nameBuffer, asDirectoryName) || checkIfParentDirectory(asDirectoryName, nameBuffer)){ #ifdef DEBUG printf(" it is listed in command line args, so skip it\n"); #endif // Skip ahead to next file if(lseek(arkiv, fileSize, SEEK_CUR) == -1){ // Couldn't skip ahead in file. Rollback. return -1; } stackAddFile(log, nameBuffer); goto dreadloop; } } // Not listed - so copy to new file // Add file size and name to archive if(archiveFileSizeAndName(nameBuffer, newArkiv, fileSize) == -1){ return -1; } // Add rest of file if(copyBytes(nameBuffer, arkiv, newArkiv, fileSize) == -1){ return -1; } } // Make sure that all the arg commands were deleted for (int i = 3; i < argc; i++){ if(!stackContainsChild(log, argv[i])){ fprintf(stderr, "Far: cannot find %s\n", argv[i]); } } // Done! Destory stack and switch files stackDestroy(log); char tmpBackupName[PATH_MAX]; snprintf(tmpBackupName, PATH_MAX, "%s.bak", arkName); if(arkiv != STDIN_FILENO && rename(arkName, tmpBackupName) == -1){ // Can't rename first file with .bak. Rollback. snprintf(errDesc, ERR_STATUS_LENGTH, "first step switching archives, renaming %s to %s", arkName, tmpBackupName); unlink(tmpName); return -1; } if(arkiv != STDIN_FILENO && rename(tmpName, arkName) == -1){ // Can't make tmpfile permanent. Rollback. snprintf(errDesc, ERR_STATUS_LENGTH, "second step switching archives, renaming %s to %s", tmpName, arkName); rename(tmpBackupName, arkName); if(arkiv != STDIN_FILENO) unlink(tmpName); return -1; } if(arkiv != STDIN_FILENO && close(arkiv) == -1){ // Can't close original archive. snprintf(errDesc, ERR_STATUS_LENGTH, "closing old archive file %s", arkName); return -1; } if(arkiv != STDIN_FILENO && close(newArkiv) == -1){ // Can't close original archive. snprintf(errDesc, ERR_STATUS_LENGTH, "closing archive file %s", tmpName); return -1; } if(arkiv != STDIN_FILENO && unlink(tmpBackupName) == -1){ snprintf(errDesc, ERR_STATUS_LENGTH, "unlinking original archive, renamed %s", tmpBackupName); } return 0; }
int xcommand (int argc, char *argv[]){ #ifdef DEBUG printf("xcommand\n"); #endif // Get archive name from command line char * arkName = argv[2]; // File descriptor for existing archive int arkiv; // Make sure 'open' is working if(!strcmp(arkName, "-")){ // If archive name is '-' then read from std_in arkiv = STDIN_FILENO; } else if ((arkiv = open(arkName, O_RDONLY, S_IRUSR | S_IWUSR)) == -1){ snprintf(errDesc, ERR_STATUS_LENGTH, "opening initial archive %s", arkName); return -1; } // Use a log so we can check for leftover names Stack filesAdded = stackCreate(); // Variable to store filesize of current archive off_t fileSize; // Read through archive 'arkiv' // For each file, filesize is stored, then file's name, terminated by null char #ifdef DEBUG printf(" scanning through archive\n"); #endif xreadloop: while(read(arkiv, &fileSize, sizeof(off_t)) > 0){ // File's name char nameBuffer[PATH_MAX]; // Read into nameBuffer until null char int posInNameBuff = 0; while(read(arkiv, nameBuffer + posInNameBuff, 1) == 1 && nameBuffer[posInNameBuff++] != '\0'); // Do we have a valid file? if(strlen(nameBuffer) < 1){ // Abort mission. Roll back. snprintf(errDesc, ERR_STATUS_LENGTH, "reading file '%s' with name less than one char from archive %s", nameBuffer, arkName); return -1; } // If this file is in command line args, or there are no command line args, extract int shouldExtract = 0; if (argc == 3) { #ifdef DEBUG printf(" three command line args, so extract it\n"); #endif shouldExtract = 1; }else{ #ifdef DEBUG printf(" scanning file %s, checking if it should be extracted\n", nameBuffer); #endif for(int i = 3; i < argc; i++){ // If 'zoo' is in command line, also check for 'zoo/' char asDirectoryName[PATH_MAX]; strcpy(asDirectoryName, argv[i]); if(asDirectoryName[strlen(asDirectoryName) - 1] != '/') strcat(asDirectoryName, "/"); if(!strcmp(nameBuffer, argv[i]) || !strcmp(nameBuffer, asDirectoryName) || checkIfParentDirectory(asDirectoryName, nameBuffer)){ #ifdef DEBUG printf(" it is listed in command line args, so extract it\n"); #endif shouldExtract = 1; } } } if(shouldExtract){ #ifdef DEBUG printf(" extract %s\n", nameBuffer); #endif if(extractFileFromArchive(nameBuffer, arkiv, fileSize) == -1){ // Couldn't extract. Rollback. stackAddFile(filesAdded, nameBuffer); fprintf(stderr, "Far: cannot extract %s\n", nameBuffer); }else{ stackAddFile(filesAdded, nameBuffer); goto xreadloop; } } // If we've gotten here, we don't have to extract it... skip to next file if(lseek(arkiv, fileSize, SEEK_CUR) == -1){ snprintf(errDesc, ERR_STATUS_LENGTH, "skipping past file %s of size %lld", nameBuffer, (long long) fileSize); return -1; } } // Make sure that all the arg commands were extracted for (int i = 3; i < argc; i++){ if(!stackContainsChild(filesAdded, argv[i])){ fprintf(stderr, "Far: cannot find %s\n", argv[i]); } } // Done extracting stackDestroy(filesAdded); if(close(arkiv) == -1){ // Can't close archive. snprintf(errDesc, ERR_STATUS_LENGTH, "closing archive file %s", arkName); return -1; } return 0; }
// Archive or update files supplied by command line int rcommand (int argc, char *argv[]){ #ifdef DEBUG printf("rcommand\n"); #endif // Get archive name from command line char * arkName = argv[2]; // File descriptor for existing archive int arkiv; // Make sure 'open' is workinging if(!strcmp(arkName, "-")){ // If archive name is '-' then read from std_in arkiv = STDIN_FILENO; } else if ((arkiv = open(arkName, O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR)) == -1){ snprintf(errDesc, ERR_STATUS_LENGTH, "opening initial archive %s", arkName); return -1; } /* Make new archive (temporary) to copy to * ... if it succeeds, we will keep temp archive * else we will unlink it. */ int newArkiv; char tmpName [PATH_MAX]; if(!strcmp(arkName, "-")){ newArkiv = STDOUT_FILENO; }else{ snprintf(tmpName, PATH_MAX, "%sXXXXXX", arkName); if ((newArkiv = mkstemp(tmpName)) == -1){ snprintf(errDesc, ERR_STATUS_LENGTH, "making new tmp archive with name %s", tmpName); return -1; } } // Use stack to log added files Stack filesAdded = stackCreate(); // Variable to store filesize of current archive off_t fileSize; // Read through archive 'arkiv' // For each file, filesize is stored, then file's name, terminated by null char #ifdef DEBUG printf(" scanning through archive\n"); #endif rreadloop: while(read(arkiv, &fileSize, sizeof(off_t)) > 0){ // File's name char nameBuffer[PATH_MAX]; // Read into nameBuffer until null char int posInNameBuff = 0; while(read(arkiv, nameBuffer + posInNameBuff, 1) == 1 && nameBuffer[posInNameBuff++] != '\0'); // Do we have a valid file? if(strlen(nameBuffer) < 1){ // Abort mission. Roll back. snprintf(errDesc, ERR_STATUS_LENGTH, "reading file with name less than one char from archive %s", arkName); stackDestroy(filesAdded); if(arkiv != STDIN_FILENO) unlink(tmpName); return -1; } #ifdef DEBUG printf(" scanning file %s, checking if it should be updated or moved\n", nameBuffer); #endif // If this file is in command line args, update it for(int i = 3; i < argc; i++){ // If 'zoo' is in command line, also check for 'zoo/' char asDirectoryName[PATH_MAX]; strcpy(asDirectoryName, argv[i]); if(asDirectoryName[strlen(asDirectoryName) - 1] != '/') strcat(asDirectoryName, "/"); if((!strcmp(nameBuffer, argv[i]) || !strcmp(nameBuffer, asDirectoryName) || checkIfParentDirectory(asDirectoryName, nameBuffer))){ // Update file and log it to avoid repeats #ifdef DEBUG printf(" it is listed in command line args, so try to update it\n"); #endif if(!fileOrDirExists(argv[i])){ // File does not exist, but not a fatal error. Log as to not repeat. fprintf(stderr, "Far: %s does not exist\n", argv[i]); continue; } if(archiveFileOrDirectoryAndLog(argv[i], filesAdded, newArkiv) == -1){ // Something went wrong if(arkiv != STDIN_FILENO) unlink(tmpName); stackDestroy(filesAdded); return -1; } #ifdef DEBUG printf(" skipping to next file\n"); #endif // Skip ahead to next file if(lseek(arkiv, fileSize, SEEK_CUR) == -1){ // Couldn't skip ahead in file. Rollback. if(arkiv != STDIN_FILENO) unlink(tmpName); stackDestroy(filesAdded); return -1; } goto rreadloop; } } #ifdef DEBUG printf(" %s is NOT in command line, so just move it to new archive\n", nameBuffer); #endif // If we're here, then file is NOT in command line - move it to new archive... if(moveArchiveAndLog(nameBuffer, filesAdded, arkiv, newArkiv, fileSize) == -1){ // Could not copy this archived file to new archive. Rollback. if(arkiv != STDIN_FILENO) unlink(tmpName); return -1; } } // Start adding command line args #ifdef DEBUG printf(" done scanning through existing archive, start adding command line files\n"); #endif for(int i = 3; i < argc; i++){ if(!fileOrDirExists(argv[i])){ // File does not exist. We already issued an error so don't repeat continue; } #ifdef DEBUG printf(" adding file from commandline: %s\n", argv[i]); #endif if(archiveFileOrDirectoryAndLog(argv[i], filesAdded, newArkiv) == -1){ if(arkiv != STDIN_FILENO) unlink (tmpName); return -1; } } // Done adding to archive. Switch old archive and temp archive stackDestroy(filesAdded); char tmpBackupName[PATH_MAX]; snprintf(tmpBackupName, PATH_MAX, "%s.bak", arkName); if(arkiv != STDIN_FILENO && rename(arkName, tmpBackupName) == -1){ // Can't rename first file with .bak. Rollback. snprintf(errDesc, ERR_STATUS_LENGTH, "first step switching archives, renaming %s to %s", arkName, tmpBackupName); return -1; } if(arkiv != STDIN_FILENO && rename(tmpName, arkName) == -1){ // Can't make tmpfile permanent. Rollback. snprintf(errDesc, ERR_STATUS_LENGTH, "second step switching archives, renaming %s to %s", tmpName, arkName); rename(tmpBackupName, arkName); unlink(tmpName); return -1; } if(arkiv != STDIN_FILENO && close(arkiv) == -1){ // Can't close original archive. snprintf(errDesc, ERR_STATUS_LENGTH, "closing old archive file %s", arkName); return -1; } if(arkiv != STDIN_FILENO && close(newArkiv) == -1){ // Can't close original archive. snprintf(errDesc, ERR_STATUS_LENGTH, "closing archive file %s", tmpName); return -1; } if(arkiv != STDIN_FILENO && unlink(tmpBackupName) == -1){ snprintf(errDesc, ERR_STATUS_LENGTH, "unlinking original archive, renamed %s", tmpBackupName); } return 0; }
// Scan through an archive and perform necessary commands based on // command line input. Return 0 if successful, -1 if failure. int scanArchive(int argc, char *argv[], int command){ // Get archive name from command line char * arkName = argv[2]; int arkiv; // Open existing archive if(!strcmp(arkName, "-")){ // If archive name is '-' then read from std_in arkiv = STDIN_FILENO; } else if (command == R && (arkiv = open(arkName, O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR)) == -1){ snprintf(errDesc, ERR_STATUS_LENGTH, "opening/creating initial archive %s", arkName); return -1; }else if ((arkiv = open(arkName, O_RDONLY, S_IRUSR | S_IWUSR)) == -1){ snprintf(errDesc, ERR_STATUS_LENGTH, "opening/creating initial archive %s", arkName); return -1; } /* Make new archive (temporary) to copy to * ... if it succeeds, we will keep temp archive * else we will unlink it. */ int newArkiv; char tmpName [PATH_MAX]; memset(tmpName, 0, PATH_MAX); // For D and R command, make a backup file if (command == D || command == R){ if(!strcmp(arkName, "-")){ newArkiv = STDOUT_FILENO; }else{ snprintf(tmpName, PATH_MAX, "%s.bak", arkName); if ((newArkiv = open(tmpName, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH)) == -1){ snprintf(errDesc, ERR_STATUS_LENGTH, "making new tmp archive with name %s", tmpName); return -1; } } } // Use stack to log added files Stack filesAdded = stackCreate(); // Variable to store filesize of current archive off_t fileSize; // Read through archive 'arkiv' // For each file, filesize is stored, then file's name, terminated by null char #ifdef DEBUG printf(" scanning through archive\n"); #endif scanloop: while(read(arkiv, &fileSize, sizeof(off_t)) > 0){ // Read into nameBuffer until null char detected in archive char nameBuffer[PATH_MAX]; int posInNameBuff = 0; while(read(arkiv, nameBuffer + posInNameBuff, 1) == 1 && nameBuffer[posInNameBuff++] != '\0'); // Do we have a valid file? if(strlen(nameBuffer) < 1){ // Abort mission. Roll back. snprintf(errDesc, ERR_STATUS_LENGTH, "reading file from archive %s", arkName); stackDestroy(filesAdded); if(arkiv != STDIN_FILENO) unlink(tmpName); return -1; } #ifdef DEBUG printf(" scanning file %s, checking if it should be updated or moved\n", nameBuffer); #endif // Should we extract the file at the end of this loop? int shouldExtract = (command == X && argc == 3); if (command == T){ printf("%8d %s\n", (int) fileSize, nameBuffer); }else{ // Is this file in command line args? for(int i = 3; i < argc; i++){ // If 'zoo' is in command line, also check for 'zoo/' char asDirectoryName[PATH_MAX]; strcpy(asDirectoryName, argv[i]); if(asDirectoryName[strlen(asDirectoryName) - 1] != '/') strcat(asDirectoryName, "/"); if((!strcmp(nameBuffer, argv[i]) || !strcmp(nameBuffer, asDirectoryName) || checkIfParentDirectory(asDirectoryName, nameBuffer))){ // It IS listed in command line args, or some derivative of it is if(command == R){ // Avoid feedback loop if(arkiv != STDIN_FILENO && strstr(argv[i], tmpName) != NULL){ continue; } // Avoid updating a file with directory and vice versa if((!isDir(argv[i]) && nameBuffer[strlen(nameBuffer) - 1] == '/') || (isDir(argv[i]) && nameBuffer[strlen(nameBuffer) - 1] != '/') || (!isDir(asDirectoryName) && checkIfParentDirectory(asDirectoryName, nameBuffer))){ continue; } // Replace file in new archive if(!fileOrDirExists(argv[i])){ if(moveArchiveAndLog(nameBuffer, filesAdded, arkiv, newArkiv, fileSize) == -1){ // Could not copy this archived file to new archive. Rollback. if(arkiv != STDIN_FILENO) unlink(tmpName); return -1; } goto scanloop; break; } // Make sure we log it with the right name char * properName = (!isDir(argv[i])) ? argv[i] : asDirectoryName; if(archiveFileOrDirectoryAndLog(properName, filesAdded, newArkiv) == -1){ // Couldn't log this file. Issue error and move on. fprintf(stderr, "Far: could not add %s\n", properName); if(moveArchiveAndLog(nameBuffer, filesAdded, arkiv, newArkiv, fileSize) == -1){ // Could not copy this archived file to new archive. Rollback. if(arkiv != STDIN_FILENO) unlink(tmpName); return -1; } goto scanloop; }else { if(lseek(arkiv, fileSize, SEEK_CUR) == -1){ // Couldn't skip ahead in file. Rollback. if(arkiv != STDIN_FILENO) unlink(tmpName); stackDestroy(filesAdded); return -1; } goto scanloop; } }else if (command == D){ // Skip ahead to next file if(lseek(arkiv, fileSize, SEEK_CUR) == -1){ return -1; }else { stackAddFile(filesAdded, argv[i]); goto scanloop; } }else if (command == X){ // Extract file from archive after we exit shouldExtract = 1; break; } } } } // Should we extract? if(shouldExtract){ #ifdef DEBUG printf(" extract %s\n", nameBuffer); #endif if(extractFileFromArchive(nameBuffer, arkiv, fileSize) == -1){ // Couldn't extract. Skip ahead to next file. //stackAddFile(filesAdded, nameBuffer); fprintf(stderr, "Far: cannot extract %s\n", nameBuffer); if(lseek(arkiv, fileSize, SEEK_CUR) == -1){ // Fatal error if(arkiv != STDIN_FILENO) unlink(tmpName); stackDestroy(filesAdded); return -1; }else{ goto scanloop; } }else{ // Successfully extracted file stackAddFile(filesAdded, nameBuffer); goto scanloop; } } if(command == T || command == X){ if(lseek(arkiv, fileSize, SEEK_CUR) == -1){ // Fatal error if(arkiv != STDIN_FILENO) unlink(tmpName); stackDestroy(filesAdded); return -1; }else{ // Move to next file goto scanloop; } }else if(command == R || command == D){ // Move this file to new archive if(moveArchiveAndLog(nameBuffer, filesAdded, arkiv, newArkiv, fileSize) == -1){ // Could not copy this archived file to new archive. Rollback. if(arkiv != STDIN_FILENO) unlink(tmpName); return -1; } } } if(command == R){ // Start adding command line args for(int i = 3; i < argc; i++){ if(arkiv != STDIN_FILENO && strstr(argv[i], tmpName) != NULL){ // Adding will cause a feedback loop somehow off_t size = 0; if(archiveFileSizeAndName(argv[i], newArkiv, size) == -1){ fprintf(stderr, "Far: could not archive %s\n", tmpName); } continue; } if(!fileOrDirExists(argv[i])){ fprintf(stderr, "Far: %s does not exist\n", argv[i]); continue; }else { char asDirectoryName[PATH_MAX]; strcpy(asDirectoryName, argv[i]); if(asDirectoryName[strlen(asDirectoryName) - 1] != '/') strcat(asDirectoryName, "/"); char * properName = (!isDir(argv[i])) ? argv[i] : asDirectoryName; if(archiveFileOrDirectoryAndLog(properName, filesAdded, newArkiv) == -1){ // Couldn't archive fprintf(stderr, "Far: could not archive %s\n", properName); continue; } } } } if(command == X || command == D){ for (int i = 3; i < argc; i++){ if(!stackContainsChild(filesAdded, argv[i])){ fprintf(stderr, "Far: cannot find %s\n", argv[i]); } } } // Done adding to archive. Switch old archive and temp archive stackDestroy(filesAdded); if(arkiv != STDIN_FILENO && close(arkiv) == -1){ // Can't close original archive. snprintf(errDesc, ERR_STATUS_LENGTH, "closing old archive file %s", arkName); return -1; } // Close additional files and switch for r and d commands if(command == R || command == D){ if(arkiv != STDIN_FILENO && unlink(arkName) == -1){ snprintf(errDesc, ERR_STATUS_LENGTH, "unlinking original archive %s", arkName); } if(arkiv != STDIN_FILENO && rename(tmpName, arkName) == -1){ // Can't make tmpfile permanent. Rollback. snprintf(errDesc, ERR_STATUS_LENGTH, "second step switching archives, renaming %s to %s", tmpName, arkName); unlink(tmpName); return -1; } if(arkiv != STDIN_FILENO && close(newArkiv) == -1){ // Can't close original archive. snprintf(errDesc, ERR_STATUS_LENGTH, "closing archive file %s", tmpName); return -1; } } return 0; }