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;
}
Exemple #3
0
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!");
}
Exemple #4
0
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;
}
Exemple #5
0
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;
}
Exemple #6
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);
}
Exemple #7
0
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;
}
Exemple #9
0
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);
}
Exemple #10
0
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;	
}
Exemple #11
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;
}
Exemple #12
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;
}
Exemple #13
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;
}
Exemple #14
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;
}