/* * Pop: delete all element created at the current level */ void egeq_pop(egeq_t *egeq) { egeq_levstack_t *stack; uint32_t i; stack = &egeq->stack; assert(stack->current_level > 0); if (stack->current_level == stack->top_level) { assert(stack->nmarks > 0); i = stack->nmarks - 1; assert(stack->data[i].level == stack->current_level); remove_level(&egeq->bank, &egeq->htbl, stack->data[i].blk_id, stack->data[i].index); egeq_htbl_cleanup_if_needed(&egeq->htbl); pop_top_mark(stack); } stack->current_level --; }
void edit_or_remove(al_defs *al, char name[255]) { draw_background(al); al_draw_text(al->menu_font, al_map_rgb(150,150,150), al->width/2, 120, ALLEGRO_ALIGN_CENTRE, "Press E to edit, R to remove"); al_flip_display(); ALLEGRO_EVENT ev; bool quit=false; while(!quit) { al_wait_for_event(al->queue, &ev); if(ev.type==ALLEGRO_EVENT_KEY_DOWN) { switch(ev.keyboard.keycode){ case ALLEGRO_KEY_E: quit=true; edit_level(al, name); break; case ALLEGRO_KEY_R: quit=true; remove_level(name); } } } }
/************************************************************************* * TESTS ON SINGLE DATA STRUCTURES LIKE INODES * * - This procedure is the central routine for working on the directory * tree. A backtracking mechanism with no recursive procedure-overhead * is used to avoid memory allocation and stack overflow problems. * - It is called as "step 2" during the checking process after working * on unique data-structures and allocation all needed buffers for * tables etc. * - The root-inode was validated during a separate step in check_unique(). * * Parameter : root_de = The directory-entry of the local root which * has to be examined * root_bnr = The number of the directory block which keeps * the root entry * root_offs = The offset in this directory block * Return : TRUE : under all normal checking conditions * FALSE : if a fatal error occurs * *************************************************************************/ word check_inodes ( struct dir_elem *root_de, daddr_t root_bnr, word root_offs ) { word spare; /* # of entries in the direct. */ daddr_t bnr; /* For temporary storage */ word offset; word depth; /* To keep track about the dis- */ /* tance from the root-direct. */ struct buf *bpar; /* Points to the current parent */ /* directory - block */ struct buf *blpt; /* For symbolic-link reference- */ /* path block */ tree_e head; word first_time; /* Used to signal, if an entry */ /* is scanned the first time */ tree_e *parent; /* Pointer to the actual parent */ /* tree-element */ tree_e *tpt; /* Pointer to the actual wor- */ /* king element. */ struct dir_elem *de_pt; /* Used for temporary storage */ /*---------------------- Init operations ----------------------------*/ head.bnr = root_bnr; /* Init the head element */ head.offset = root_offs; head.parent_used = TRUE; /* Copy the root entry */ memcpy ( (void *) &head.de, (void *) root_de, sizeof (struct dir_elem) ); head.enxt = (tree_e *) NULL; /* Zero the head-pointers */ head.eprv = (tree_e *) NULL; head.lnxt = (tree_e *) NULL; head.lprv = (tree_e *) NULL; /* Clear the comparison struct */ memset ( &dir_cmp, 0, sizeof (struct dir_elem) ); strcpy ( path, "/" ); /* Set the name of the root */ strcat ( path, head.de.de_name ); /* of the filesystem */ spare = 0; /* No entry at the beginning */ first_time = TRUE; /* Start up value */ parent = &head; /* At the beginning the head */ tpt = &head; /* element is the only one. */ remove_de_hash (); /* Free previously used hash- */ /* table elements */ changes_de = 0; /* Nothing changed so far... */ depth = 0; /* We start on root-position */ /*--------------- Traverse the whole directory tree -----------------*/ for ( ;; ) { /* Get the next entry to check */ de_pt = get_next_entry ( &parent->de.de_inode, first_time, &bnr, &offset ); first_time = FALSE; /* We want to get all other en- */ /* tries from this directory */ /* We have got an entry ? */ if ( de_pt != (struct dir_elem *) NULL ) { strncpy (actual_path, path, 512); #if 0 IOdebug ("%sChecking %s / [%s]", S_INFO, path, de_pt->de_name); #endif /* An entry was extracted. Now */ /* check it's validity */ if ( validate_entry ( de_pt, path, UNKNOWN, TRUE ) ) { /* Put the entry name into the */ /* appropriate hash-queue */ append_de_hash ( de_pt->de_name ); /* We have to increment the */ spare++; /* total count of entries */ /*-------------- Storage of symbolic-link information ----------------*/ /* Was it a symbolic link ? */ if ( de_pt->de_inode.i_mode == Type_Link ) { /* Read the block with the re- */ /* ference path in buffer-cache */ blpt = bread ( 0, de_pt->de_inode.i_db[0], 1, SAVEA ); /* Append the link to the hash- */ /* table for symbolic links */ append_link_hash ( bnr, offset, parent->bnr, parent->offset, blpt->b_un.b_link->name); /* One more symbolic link found */ found_links++; /* The ref-block is not used */ /* anymore */ brelse ( blpt->b_tbp, TAIL ); } /*----- Appending new elements to the hierarchical directory-tree ----*/ if ( de_pt->de_inode.i_mode == Type_Directory ) { /* Increment the counter for */ /* the number of valid directo- */ /* ries in a cylinder group. */ add_dir ( bnr ); found_dirs++; if ( tpt == parent ) /* Add a new directory level */ tpt = append_level ( tpt ); else /* .. or a new entry */ tpt = append_entry ( tpt ); /* Save the entry's location */ tpt->bnr = bnr; tpt->offset = offset; /* Save the entry's content */ memcpy ( &tpt->de, de_pt, sizeof (struct dir_elem) ); /* At this time NOT used as a */ /* parent-dir */ tpt->parent_used = FALSE; #if DEBUG IOdebug (" check_inodes : New element created for %s (bnr= %d, off= %d)", tpt->de.de_name, tpt->bnr, tpt->offset ); #endif } /* Update the actual number of */ /* file checked. */ if ( de_pt->de_inode.i_mode == Type_File ) found_files++; } else /* If the validation does not */ { /* succeeds: */ /* We have to make a note, if */ /* /lost+found will be deleted ! */ if ( depth == 0 && ! strcmp ( de_pt->de_name, "lost+found" ) ) { IOdebug ("%sUnusable /lost+found-dir !", S_WARNING); lost_found = FALSE; } IOdebug ("%sThe entry is invalid and will be deleted!", S_SERIOUS); if ( ! no_corrections ) { /* We cannot make use anymore */ /* of the corrupted entry and */ /* delete it. */ memset ( (void *) de_pt, 0, sizeof (struct dir_elem) ); /* Note the deletion */ fst.deleted_inodes++; changes_de++; } } } /*------ After checking a complete directory with all entries: --------*/ else /* One directory fully scanned: */ { #if DEBUG IOdebug (" check_inodes : Have examined all entries. Change the directory"); IOdebug (" Current parent = %s 'used' = %d", parent->de.de_name, parent->parent_used); IOdebug (" Current entry = %s 'used' = %d", tpt->de.de_name, tpt->parent_used); #endif /*------- Go on with the last directory of the current sub-dir ------*/ if ( tpt->enxt == (tree_e *) NULL && tpt->lnxt == (tree_e *) NULL && tpt != parent && ! tpt->parent_used ) { #if DEBUG IOdebug (" check_inodes : Take the last sub-dir as parent directory"); #endif #if DEBUG IOdebug (" check_inodes : Spare value found = %d , counted = %d", parent->de.de_inode.i_spare, spare ); #endif /* Different # of entries ? */ if ( spare != parent->de.de_inode.i_spare ) { /* Save the new spare value */ /* Read the parent-directory */ #if DEBUG IOdebug (" check_inodes : Correct number of entries (spare value)"); #endif bpar = bread ( 0, parent->bnr, 1, SAVEA ); /* Change the entry */ if ( parent->bnr == 1 ) { /* Special handling for root */ bpar->b_un.b_sum->root_dir.de_inode.i_spare = spare; bpar->b_un.b_sum->root_dir.de_inode.i_size = spare * sizeof(struct dir_elem); } else { bpar->b_un.b_dir[parent->offset].de_inode.i_spare = spare; bpar->b_un.b_dir[parent->offset].de_inode.i_size = spare * sizeof(struct dir_elem); } /* ... and write it back. */ test_bwrite ( bpar ); } /* Prepare the tree-element */ /* for a new pass as "parent": */ parent = tpt; parent->parent_used = TRUE; first_time = TRUE; spare = 0; /* Append to the pathname-string*/ strcat ( path , "/" ); /* ... a new sub-dir branch */ strcat ( path , parent->de.de_name ); /* One level lower than the */ depth++; /* root-directory */ /* Clear the name-hash-table */ remove_de_hash (); /* Begin with the first entry.. */ continue; /* and scan again all entries. */ } /*-------------------- Backtracking conditions ----------------------*/ if ( tpt->enxt == (tree_e *) NULL && tpt->lnxt == (tree_e *) NULL && tpt == parent && tpt->parent_used ) { #if DEBUG IOdebug (" check_inodes : Use backtracking to get a new parent-dir"); #endif #if DEBUG IOdebug (" check_inodes : Spare value found = %d , counted = %d", parent->de.de_inode.i_spare, spare ); #endif /* Different # of entries ? */ if ( spare != parent->de.de_inode.i_spare ) { #if DEBUG IOdebug (" check_inodes : Correct number of entries (spare value)"); #endif /* Save the new spare value */ /* Read the directory block */ bpar = bread ( 0, parent->bnr, 1, SAVEA ); /* Change the entry */ if ( parent->bnr == 1 ) { /* Special handling for root */ bpar->b_un.b_sum->root_dir.de_inode.i_spare = spare; bpar->b_un.b_sum->root_dir.de_inode.i_size = spare * sizeof(struct dir_elem); } else { bpar->b_un.b_dir[parent->offset].de_inode.i_spare = spare; bpar->b_un.b_dir[parent->offset].de_inode.i_size = spare * sizeof(struct dir_elem); } /* ... and write it back. */ test_bwrite ( bpar ); } /* Look for a directory, which */ /* wasn't used as a "parent" */ do { /* THE MAIN EXIT-POINT ! */ if ( tpt->eprv == (tree_e *) NULL && tpt->lprv == (tree_e *) NULL ) return TRUE; /* The "move-back" operation */ if ( tpt->lprv != (tree_e *) NULL ) { /* Remove the lowest level */ parent = remove_level ( tpt ); depth--; } else /* Remove the last entry from */ /* the directory */ parent = remove_entry ( tpt ); /* Adjust the work-pointer */ tpt = parent; /* Cut the pathname string and */ *( strrchr ( path , '/' ) ) = '\0'; #if DEBUG IOdebug (" check_inodes : Backtracking to path = %s (depth: %d)", path, depth ); #endif } /* try it again until an unused */ /* dir-entry is found */ while ( tpt->parent_used ); /* Append the new sub-dir */ if ( tpt->de.de_name ) { strcat ( path, "/" ); strcat ( path, tpt->de.de_name ); } /* Prepare the tree-element as */ /* the new parent-directory */ tpt->parent_used = TRUE; first_time = TRUE; spare = 0; /* Clear the hash-table */ remove_de_hash (); /* ... and go to the beginning */ continue; /* Now we will examine the en- */ /* tries of the "new" directory.*/ } } } /* end of <for (;;)> */ }