void cbc_md(FILE *outf, f_dctx alg[1], const unsigned long blen, const unsigned long klen) { unsigned long j, k; unsigned char pt[32], ct[64], key[32], dummy; block_clear(key, klen); // clear key: KEY[0] block_clear(ct, 2 * blen); // clear ct: IV[0] ct + blen: CT[0] for(j = 0; j < 400; j++) // 400 Monte Carlo tests { block_out(test_no, &dummy, outf, j); // output test number block_out(key_val, key, outf, klen); // output key block_out(iv_val, ct, outf, blen); // output initialisation vector block_out(ct_val, ct + blen, outf, blen); // output ciphertext f_dec_key(alg, key, klen); // set key for(k = 0; k < 5000; ++k) // 10000 encryptions, two at a time { do_dec(alg, ct + blen, pt, 1); // do block decryption block_xor(ct, pt, blen); // do CBC chaining do_dec(alg, ct, pt, 1); // do block decryption block_xor(ct + blen, pt, blen); // do CBC chaining } block_out(pt_val, ct + blen, outf, blen); // output plaintext // compile next key as defined by NIST block_xor(key, ct + 2 * blen - klen, klen); } }
void ecb_md(FILE *outf, f_dctx alg[1], const unsigned long blen, const unsigned long klen) { unsigned long j, k; unsigned char pt[32], ct[64], key[32], dummy; block_clear(pt, blen); // clear initial plaintext and key block_clear(key, klen); block_copy(ct + blen, pt, blen); // copy plaintext into upper half // of double length ciphertext block for(j = 0; j < 400; j++) // 400 Monte Carlo tests { block_out(test_no, &dummy, outf, j); // output test number block_out(key_val, key, outf, klen); // output key block_out(ct_val, pt, outf, blen); // output plaintext f_dec_key(alg, key, klen); // set key for(k = 0; k < 5000; ++k) // 10000 decryptions alternating { // upper and lower blocks in ct do_dec(alg, ct + blen, ct, 1); do_dec(alg, ct, ct + blen, 1); } // compile next key as defined by NIST block_xor(key, ct + 2 * blen - klen, klen); block_out(pt_val, ct + blen, outf, blen); // output ciphertext block_copy(pt, ct + blen, blen); // set ciphertext as next plaintext } }
SimAir::SimAir(Simulation *sim_) : sim(sim_), airSimNeeded(false) { airSimulator = AirSimulator_async::create(1); setManipData(currentData); block_clear(); blockh_clear(); }
void ecb_vt(FILE *outf, f_ectx alg[1], const unsigned long blen, const unsigned long klen) { unsigned long j; unsigned char pt[32], ct[32], key[32], dummy; block_clear(key, klen); // all zero key block_out(key_val, key, outf, klen); // output key value f_enc_key(alg, key, klen); // set key value for(j = 0; j <= 8 * blen; ++j) // test vectors include { // an all zero one block_out(test_no, &dummy, outf, j); // output test number block_clear(pt, blen); // set all zero plain text if(j) // set bit (j-1) if j <> 0 *(pt + (j - 1) / 8) = 0x80 >> (j - 1) % 8; block_out(pt_val, pt, outf, blen); // output plaintext do_enc(alg, pt , ct, 1); // do encryption block_out(ct_val, ct, outf, blen); // output ciphertext } }
void ecb_vk(FILE *outf, f_ectx alg[1], const unsigned long blen, const unsigned long klen) { unsigned long j; unsigned char pt[32], ct[32], key[32], dummy; block_clear(pt, blen); // all zero plaintext block_out(pt_val, pt, outf, blen); // output plaintext for(j = 0; j <= 8 * klen; ++j) // 129, 193 or 257 tests { block_out(test_no, &dummy, outf, j); // output test number block_clear(key, klen); // set all zero key if(j) // set bit (j-1) if j <> 0 *(key + (j - 1) / 8) = 0x80 >> (j - 1) % 8; block_out(key_val, key, outf, klen); // output key value f_enc_key(alg, key, klen); // set key value do_enc(alg, pt , ct, 1); // alg.encrypt block_out(ct_val, ct, outf, blen); // output ciphertext } }
void g_clearGrid() { int x, y; block * b; debug_msg("[g_clearGrid]: starting...\n"); //set grid array to NULL for ( x = 0; x < SIZE_X; x++ ) { for ( y = 0; y < SIZE_Y; y++ ) { b = g_getBlockAtPos(x, y); //debug_msg("before if/else branches\n"); if ( b == NULL ) { //printf("[g_clearGrid]: no block located at (%d, %d)\n", x, y); } else { if ( !block_clear(b) ) { //printf("[g_clearGrid]: block failed to clear! Clearing parent tetromino first...\n"); tetro_clear(block_getParent(b)); if ( !block_clear(b) ) debug_msg("[g_clearGrid]: block STILL failed to clear! WTF?\n"); else { game.pos[x][y] = NULL; //printf("[g_clearGrid]: game.pos[%d][%d] set to NULL!\n", x, y); } } else { game.pos[x][y] = NULL; //printf("[g_clearGrid]: game.pos[%d][%d] set to NULL!\n", x, y); } //debug_msg("after if/else branches\n"); } } } }
void ecb_vkn(FILE *outf, f_ectx alg[1], const unsigned long blen, const unsigned long klen) { unsigned long j; unsigned char pt[32], ct[32], key[32], *bp, dummy; block_clear(pt, blen); // all zero plaintext block_out(pt_val, pt, outf, blen); // output plaintext block_clear(key, klen); for(j = 0; j < 16 * klen; ++j) { block_out(test_no, &dummy, outf, j); // output test number block_out(key_val, key, outf, klen); // output key value f_enc_key(alg, key, klen); // set key value do_enc(alg, pt , ct, 1); // alg.encrypt block_out(ct_val, ct, outf, blen); // output ciphertext bp = key + klen - 1 - j / 8; if(j < 8 * klen) *bp |= (*bp << 1) | 1; else *(bp + klen) = *(bp + klen) << 1; } }
// Writes an inode to disk. static void inode_write(unsigned int inode_n, inode * n){ unsigned int locin_block_index = inode_get_block_index(inode_n); unsigned int real_block_index = inode_get_block(inode_n); block b; block_clear(&b); block_read((void *)&b, real_block_index); inode * inodes = (inode *) &b; int i = 0; for (; i < FS_INODE_SIZE / sizeof(int); i++) { ((int *)&inodes[locin_block_index])[i] = ((int*)n)[i]; } block_write((void *)&b, real_block_index); }
// Deletes the internal nodes of a block when deleting the file. // The internal nodes are the blocks used to make the indirects void delete_internal_inodes(int log_block) { int indirects = inode_get_indir_level(log_block); if (indirects == 0) { bitmap_write(bm_blocks, n.data_blocks[log_block] - 1, 0); } int i1_delete = 1; int i2_delete = 1; int i3_delete = 1; int i1_ptr; int i2_ptr; int i3_ptr; int * data = (int *) &bi; block_clear(&bi); if (indirects >= 1) { data_read_block(&bi, (i1_ptr = n.data_blocks[inode_get_dir_block(log_block)]) ); i1_delete = inode_get_1indir_block(log_block) == 0; if (indirects >= 2) { data_read_block(&bi, (i2_ptr = data[inode_get_1indir_block(log_block)]) ); i2_delete = inode_get_2indir_block(log_block) == 0; if (indirects >= 3) { i3_ptr = data[inode_get_1indir_block(log_block)]; i3_delete = inode_get_3indir_block(log_block) == 0; if (i3_delete) { bitmap_write(bm_blocks, i3_ptr - 1, 0); } } i2_delete = i2_delete && i3_delete; if (i2_delete) { bitmap_write(bm_blocks, i2_ptr - 1, 0); } } i1_delete = i1_delete && i2_delete; if (i1_delete) { bitmap_write(bm_blocks, i1_ptr - 1, 0); } } }
// Removes an entry from a folder unsigned int folder_rem_direntry(unsigned int file_inode, unsigned int folder_inode) { inode_read(folder_inode, &n); int index = 0; int max_log_block = n.blocks / 2; if (!max_log_block) { max_log_block = 1; } dir_op_offset = 0; block_clear(&b); dir_entry * old_dot = NULL; dir_entry * dot = NULL; // Iterates dir entries while (index < max_log_block + 1) { old_dot = dot; dot = iterate_dir_entry(&b); if (dot == NULL) { if (index == max_log_block) { break; } log_block_read(&n,&index); dir_op_offset = 0; dot = NULL; index++; } else { int i = 0; ; int match = file_inode == dot->inode; if (match) { if (old_dot != NULL) { old_dot->rec_len += dot->rec_len; dot->inode = 0; dot->name_len = 0; // Sets as deleted } else { dot->name_len = 0; // Sets as deleted } int to_write = index - 1; log_block_write(&n, &to_write); break; } } } return 0; }
// Tells the name of the inode, by reading it's parent char * fs_iname(int inode, int folder_inode) { inode_read(folder_inode, &n); *iname = 0; int index = 0; int max_log_block = n.blocks / 2; if (!max_log_block) { max_log_block = 1; } dir_op_offset = 0; block_clear(&b); dir_entry * old_dot = NULL; dir_entry * dot = NULL; // Iterates dir entries while (index < max_log_block + 1) { old_dot = dot; dot = iterate_dir_entry(&b); if (dot == NULL) { if (index == max_log_block) { break; } log_block_read(&n,&index); dir_op_offset = 0; dot = NULL; index++; } else { int i = 0; ; if (inode == dot->inode) { int match = 1; int i = 0; int len = dot->name_len; for(; i < len; ++i) { iname[i] = dot->name[i]; } iname[i] = 0; return iname; } } } return 0; }
// Tells if an name is inside the folder entries unsigned int fs_indir(char * name, int folder_inode) { inode_read(folder_inode, &n); int index = 0; int max_log_block = n.blocks / 2; if (!max_log_block) { max_log_block = 1; } dir_op_offset = 0; block_clear(&b); dir_entry * old_dot = NULL; dir_entry * dot = NULL; // Iterates dir entries while (index < max_log_block + 1) { old_dot = dot; dot = iterate_dir_entry(&b); if (dot == NULL) { if (index == max_log_block) { break; } log_block_read(&n,&index); dir_op_offset = 0; dot = NULL; index++; } else { int i = 0; ; int name_len = strlen(name); if (name_len == dot->name_len) { int match = 1; for (;name[i] && match; i++) { match = name[i] == dot->name[i]; } if (match) { return dot->inode; } } } } return 0; }
// Writes to a file, as simple as unix unsigned int fs_write_file(int inode, char * data, int size) { inode_clear(&n); // Clear the inode to take off the trash inode_read(inode, &n); // Read the current inode. int log_block = n.blocks / 2; block_clear(&b); // Prepare to read the data, clear it. int i = 0; int block_index = n._last_write_offset; log_block_read(&n, &log_block); // Set up the point where we'll write char * block = (char *) &b; // Write until we reach end for (; i < size; i++) { block[block_index] = data[i]; if (block_index == FS_BLOCK_SIZE - 1) { log_block_write(&n, &log_block); log_block++; // Iterate if necessary. log_block_read(&n, &log_block); block_index = 0; } else { block_index++; } } n._last_write_offset = block_index; log_block_write(&n, &log_block); // Save the last bits n.blocks = log_block * 2; // Update the inodes inode_write(inode,&n); fs_bitmaps_write_all(); // Persist the changes in the FS return i; }
// Makes a new directory unsigned int fs_mkdir(char * name, unsigned int parent_inode) { unsigned int inode_id = 0; if ((inode_id = fs_indir(name, parent_inode))) { return 0; } inode_id = bitmap_first_valued(bm_inodes, FS_INODE_BITMAP_SIZE, 0) + 1; if (!parent_inode) { parent_inode = inode_id; } int log_block; if (parent_inode != inode_id) { inode_read(parent_inode, &n); if(!fs_has_perms(&n, ACTION_WRITE)) { return ERR_PERMS; } log_block = n.blocks / 2; block_clear(&b); dir_op_offset = 0; log_block_read(&n, &log_block); add_dir_entry(&n, EXT2_FT_DIR, inode_id, name, &log_block); log_block_write(&n, &log_block); inode_write(parent_inode, &n); } bitmap_write(bm_inodes, inode_id - 1, 1); inode_clear(&n); if(!fs_done) { n.uid = 0; } else { n.uid = current_ttyc()->uid; } n.mode = EXT2_S_IFDIR; n.size = 0; n.blocks = 0; // Beware! This represents the SECTORS! log_block = n.blocks / 2; block_clear(&b); dir_op_offset = 0; add_dir_entry(&n, EXT2_FT_DIR, inode_id, ".", &log_block); add_dir_entry(&n, EXT2_FT_DIR, parent_inode, "..", &log_block); log_block_write(&n, &log_block); n.blocks = (log_block) * 2; n.i_file_acl = 511; n._dir_inode = parent_inode; n._last_write_offset = dir_op_offset; inode_write(inode_id, &n); fs_bitmaps_write_all(); return inode_id; }
// Opens a file unsigned int fs_open_file(char * name, unsigned int folder_inode, int mode, int type) { unsigned int inode_id = 0; if(strcmp(name, "/") == 0 && strlen(name) == strlen("/")) { return 1; // root } if(name[0] == 0) { inode_id = current_ttyc()->pwd; } else { inode_id = fs_indir(name, folder_inode); } if (inode_id) { if (mode & O_CREAT) { int _rm_res = fs_rm(inode_id, 0); if(_rm_res < 0) { return _rm_res; } } else if(mode & O_NEW) { inode_read(inode_id, &n); if(n.mode == EXT2_S_IFLNK) { return n.data_blocks[0]; } return inode_id; } else { inode_read(inode_id, &n); int can = 1; if((mode & O_RD) && !fs_has_perms(&n, ACTION_READ)) { can = 0; } if((mode & O_WR) && !fs_has_perms(&n, ACTION_WRITE)) { can = 0; } if(can || !fs_done) { if(n.mode == EXT2_S_IFLNK) { return n.data_blocks[0]; } return inode_id; } else { return ERR_PERMS; } } } else if (!(mode & (O_NEW | O_CREAT))) { return ERR_NO_EXIST; } inode_id = bitmap_first_valued(bm_inodes, FS_INODE_BITMAP_SIZE, 0) + 1; if (!folder_inode) { folder_inode = inode_id; } int log_block; if (folder_inode != inode_id) { inode_read(folder_inode, &n); if(!fs_has_perms(&n, ACTION_WRITE)) { return ERR_PERMS; } log_block = n.blocks / 2; block_clear(&b); dir_op_offset = 0; log_block_read(&n, &log_block); add_dir_entry(&n, EXT2_FT_DIR, inode_id, name, &log_block); log_block_write(&n, &log_block); inode_write(folder_inode, &n); } bitmap_write(bm_inodes, inode_id - 1, 1); inode_clear(&n); if(!fs_done) { n.uid = 0; } else { n.uid = current_ttyc()->uid; } n.mode = type; n.size = 0; n.blocks = 0; // Beware! This represents the SECTORS! n._last_write_offset = 0; n.i_file_acl = 511; n._dir_inode = folder_inode; inode_write(inode_id, &n); inode_clear(&n); if(n.mode == EXT2_S_IFLNK) { return n.data_blocks[0]; } return inode_id; }
// Filesystem Initialization void fs_init() { int i = 0; for (; i < sizeof(fs_data) / 4; i += 4) { ((int*)&dat)[i] = 0; } fs_sb_read(); sb = (super_block *) &dat.head._super; gbdt = (group_descriptor *) &dat.head._descriptors; // If the magic number is on then the fs is already loaded. if(sb->s_magic == 0xEF53) { fs_gbdt_read(); fs_bitmaps_init(); if (_FS_DEBUG) { inode_read(1, &n); int index = 0; int max_log_block = n.blocks / 2; if (!max_log_block) { max_log_block = 1; } dir_op_offset = 0; block_clear(&b); while (index < max_log_block + 1) { dir_entry * dot = iterate_dir_entry(&b); if (dot == NULL) { if (index == max_log_block) { break; } log_block_read(&n,&index); dir_op_offset = 0; index++; } else { int len = dot->name_len, i = 0; for (; i < len; i++) { printf("%c", dot->name[i]); } printf("\n"); } } } fs_bitmaps_write_all(); fs_gbdt_write(); fs_sb_write(); } else { printf("Preparing to start FS\n"); printf("Starting SB\n"); fs_sb_init(); printf("Starting GBDT\n"); fs_gbdt_init(); printf("Starting Bitmaps\n"); fs_bitmaps_init(); printf("Creating /\n"); int slash_inode = fs_mkdir("/", 1); printf("Creating /dev\n"); int dev_inode = fs_mkdir("dev", slash_inode); printf("Creating /home\n"); int home_inode = fs_mkdir("home", slash_inode); printf("Creating /root\n"); int root_inode = fs_mkdir("root", slash_inode); printf("Creating /etc\n"); int etc_inode = fs_mkdir("etc", slash_inode); printf("Creating /tmp\n"); int tmp_inode = fs_mkdir("tmp", slash_inode); printf("Creating /tmp/testfile\n"); int f1 = fs_open_reg_file("testfile", tmp_inode, O_NEW); printf("FS ended...\n"); printf("\tFree Blocks: %d\t Total Blocks: %d\n", bitmap_block_count(bm_blocks, FS_DATA_BITMAP_SIZE, 0), FS_DATA_BITMAP_SIZE); printf("\tFree Inodes: %d\t Total Inodes: %d\n", bitmap_block_count(bm_inodes, FS_INODE_BITMAP_SIZE, 0), FS_INODE_BITMAP_SIZE); fs_bitmaps_write_all(); fs_gbdt_write(); fs_sb_write(); } }
// MAGIC: Translates a logical block from a file (block 0 to N), to a physical block in the disk void make_ph_block(inode * n, int * ph_block, int * log_block) { int indirects = inode_get_indir_level(*log_block); // Gets the level of indirects inside the direction. int old_ph = * ph_block; int dirty = 0; * ph_block = n->data_blocks[inode_get_dir_block(*log_block)]; // If we've got no block, then we alloc one if(!* ph_block) { * ph_block = bitmap_first_valued(bm_blocks, FS_DATA_BITMAP_SIZE, 0) + 1; bitmap_write(bm_blocks, (* ph_block) - 1, 1); n->data_blocks[inode_get_dir_block(*log_block)] = * ph_block; dirty = 1; } if (indirects > 0) { block_clear(&bi); if (!dirty) { // If it's dirty, then probably it's new and we want the block to be absolutely clear data_read_block(&bi, * ph_block); } dirty = 0; indirect_block_data = (int *) &bi; old_ph = * ph_block; * ph_block = indirect_block_data[inode_get_1indir_block(*log_block)]; // If we've got no block, then we alloc one if(!* ph_block) { bitmap_write(bm_blocks, old_ph - 1, 1); * ph_block = bitmap_first_valued(bm_blocks, FS_DATA_BITMAP_SIZE, 0) + 1; bitmap_write(bm_blocks, (* ph_block) - 1, 1); indirect_block_data[inode_get_1indir_block(*log_block)] = * ph_block; data_write_block(&bi, old_ph); dirty = 1; } if (indirects > 1) { block_clear(&bi); if (!dirty) { // If it's dirty, then probably it's new and we want the block to be absolutely clear data_read_block(&bi, * ph_block); } dirty = 0; old_ph = * ph_block; * ph_block = indirect_block_data[inode_get_2indir_block(*log_block)]; // If we've got no block, then we alloc one if(!* ph_block) { bitmap_write(bm_blocks, old_ph - 1, 1); * ph_block = bitmap_first_valued(bm_blocks, FS_DATA_BITMAP_SIZE, 0) + 1; bitmap_write(bm_blocks, (* ph_block) - 1, 1); indirect_block_data[inode_get_2indir_block(*log_block)] = * ph_block; data_write_block(&bi, old_ph); dirty = 1; } if (indirects > 2) { block_clear(&bi); if (!dirty) { // If it's dirty, then probably it's new and we want the block to be absolutely clear data_read_block(&bi, * ph_block); } dirty = 0; old_ph = * ph_block; * ph_block = indirect_block_data[inode_get_3indir_block(*log_block)]; // If we've got no block, then we alloc one if(!* ph_block) { bitmap_write(bm_blocks, old_ph - 1, 1); * ph_block = bitmap_first_valued(bm_blocks, FS_DATA_BITMAP_SIZE, 0) + 1; bitmap_write(bm_blocks, (* ph_block) - 1, 1); indirect_block_data[inode_get_3indir_block(*log_block)] = * ph_block; data_write_block(&bi, old_ph); } } } } }
void g_onDownBlocked() { int rowTop = -1; int rowBottom = -1; short i, j, k; short x = -1, y = -1; int count = 0; //SDL_Surface * blockFlash; SDL_Surface * flash1; SDL_Surface * flash2; block * b; int flashCount; short fullRows[4] = { -1, -1, -1, -1 }; debug_msg("[g_onDownBlocked]!\n"); //calculate / move down lines here //only check the rows that the tetromino is/was at when it stopped //the above blocks only move down the number of rows equal to those cleared tetro_getRows(game.current, &rowTop, &rowBottom); //printf("[g_onDownBlocked]: rowTop: %d, rowBottom: %d\n", rowTop, rowBottom); if ( !tetro_clear(game.current) ) { debug_msg("[g_onDownBlocked]: game.current failed to clear!\n"); } for ( i = rowBottom; i <= rowTop; i++ ) { if ( g_checkFullRow(i) ) { //printf("[g_onDownBlocked]: full row at %d!\n", i); fullRows[count] = i; count++; game.lines++; } else { //printf("[g_onDownBlocked]: no full row at %d!\n", i); } } //printf("[g_onDownBlocked]: number of rows filled = %d\n", count); switch (count) { case 1: game.score += SCORE_MODIFIER_ONE_LINES * (game.level+1); break; case 2: game.score += SCORE_MODIFIER_TWO_LINES * (game.level+1); break; case 3: game.score += SCORE_MODIFIER_THREE_LINES * (game.level+1); break; case 4: game.score += SCORE_MODIFIER_FOUR_LINES * (game.level+1); break; } //calculate level here game.level = game.lines/10; if (game.level > MAX_LEVEL) game.level = MAX_LEVEL; //full line(s) exist, flash them then remove, then drop above blocks down if ( count > 0 ) { s_playSound(lineClear); debug_msg("[g_onDownBlocked]: start flashing\n"); //k = index for a row to flash //i = current x position //j = y position (row). fullRows[k] //flash1 = g_loadBlockImage(block_getType(b)); flash1 = g_loadImage("./pictures/BLOCK_FLASH1.bmp"); flash2 = g_loadImage("./pictures/BLOCK_FLASH2.bmp"); for ( flashCount = 0; flashCount < FLASH_FRAMES; flashCount++ ) { for ( k = 0; k < count; k++ ) { for ( i = 0; i < SIZE_X; i++ ) { b = g_getBlockAtPos(i, fullRows[k]); g_getImageCoords(i, fullRows[k], &x, &y); if ( flashCount % 2 == 1 ) g_addSurface(x, y, flash1, screen, NULL); else g_addSurface(x, y, flash2, screen, NULL); //g_addSurface(x, y, blockFlash, screen, NULL); } } SDL_Flip(screen); SDL_Delay(FLASH_INTERVAL); } SDL_FreeSurface(flash1); SDL_FreeSurface(flash2); debug_msg("[g_onDownBlocked]: finished flashing\n"); //remove all those blocks for ( k = 0; k < count; k++ ) { for ( i = 0; i < SIZE_X; i++ ) { b = g_getBlockAtPos(i, fullRows[k]); g_removeBlockFromPos(b); if ( block_clear(b) ) { //printf("[g_onDownBlocked]: block at (%d, %d) removed\n", i, fullRows[k]); } else { //printf("[g_onDownBlocked]: no block removed at (%d, %d)\n", i, fullRows[k]); } } } //move downt he above blocks g_dropAboveBlocksDown((fullRows[0])+1, count); } else s_playSound(downBlock); //no line clear so just play stacking sound game.current = game.next; game.next = NULL; game.next = tetro_create(TETRO_RANDOM); if ( !tetro_moveToStart(game.current) ) { //printf("[g_onDownBlocked]: GAME OVER!\n"); //g_clear(REASON_LOSS); game.state = STATE_LOSS; //on frame -1 do nothing, frame 0 pauses briefly so you can see the last tetromino that couldnt get in, //then the screen fills up rapidly game.lossFrame = -1; game.lossCurrentRow = 0; s_playSound(gameOver); } }
// Used to move a file unsigned int fs_mv(char * name, char * newname, int from_inode) { int i1 = fs_open_file(name, from_inode, O_WR | O_RD, EXT2_S_IFREG); if(i1 < 0) { return i1; // If there's an error with the first name then there's nothing to do actually. } int i2 = fs_indir(newname, from_inode); if(i2 == 0) { folder_rem_direntry(i1, n._dir_inode); inode_read(from_inode, &n); int log_block = n.blocks / 2; block_clear(&b); dir_op_offset = 0; log_block_read(&n, &log_block); add_dir_entry(&n, EXT2_FT_DIR, i1, newname, &log_block); log_block_write(&n, &log_block); n.blocks = log_block * 2; inode_write(from_inode, &n); return 1; } else { inode_read(i2, &n); if(!fs_has_perms(&n, ACTION_READ)) { return ERR_PERMS; } if(!(n.mode & EXT2_S_IFDIR)) { return ERR_INVALID_TYPE; } if (fs_indir(name, i2)) { return ERR_REPEATED; } int log_block = n.blocks / 2; block_clear(&b); dir_op_offset = 0; log_block_read(&n, &log_block); add_dir_entry(&n, EXT2_FT_DIR, i1, name, &log_block); log_block_write(&n, &log_block); n.blocks = log_block * 2; inode_write(i2, &n); inode_read(i1, &n); folder_rem_direntry(i1, n._dir_inode); inode_read(i1, &n); folder_rem_direntry(n._dir_inode, i1); log_block_read(&n, &log_block); add_dir_entry(&n, EXT2_FT_DIR, i2, "..", &log_block); log_block_write(&n, &log_block); n._dir_inode = i2; inode_write(i1, &n); } return i1; }