static void sprintf_de_head( char *buf, struct reiserfs_de_head *deh ) { if( deh ) sprintf( buf, "[offset=%d dir_id=%d objectid=%d location=%d state=%04x]", deh_offset(deh), deh_dir_id(deh), deh_objectid(deh), deh_location(deh), deh_state(deh) ); else sprintf( buf, "[NULL]" ); }
void print_directory_item (FILE * fp, reiserfs_filsys_t fs, struct buffer_head * bh, struct item_head * ih) { int i; int namelen; struct reiserfs_de_head * deh; char * name; /* static char namebuf [80];*/ if (!I_IS_DIRECTORY_ITEM (ih)) return; //printk ("\n%2%-25s%-30s%-15s%-15s%-15s\n", " Name", "length", "Object key", "Hash", "Gen number", "Status"); reiserfs_warning (fp, "%3s: %-25s%s%-22s%-12s%s\n", "###", "Name", "length", " Object key", " Hash", "Gen number"); deh = B_I_DEH (bh, ih); for (i = 0; i < ih_entry_count (ih); i ++, deh ++) { if (dir_entry_bad_location (deh, ih, i == 0 ? 1 : 0)) { reiserfs_warning (fp, "%3d: wrong entry location %u, deh_offset %u\n", i, deh_location (deh), deh_offset (deh)); continue; } if (i && dir_entry_bad_location (deh - 1, ih, ((i - 1) == 0) ? 1 : 0)) /* previous entry has bad location so we can not calculate entry length */ namelen = 25; else namelen = name_length (ih, deh, i); name = name_in_entry (deh, i); reiserfs_warning (fp, "%3d: \"%-25.*s\"(%3d)%20K%12d%5d, loc %u, state %x %s\n", i, namelen, name, namelen, /* this gets converted in print_short_key() */ (struct key *)&(deh->deh_dir_id), GET_HASH_VALUE (deh_offset(deh)), GET_GENERATION_NUMBER (deh_offset(deh)), deh_location (deh), deh_state(deh), fs ? (is_properly_hashed (fs, name, namelen, deh_offset (deh)) ? "" : "(BROKEN)") : "??"); } }
/* preconditions: reiserfs_read_super already executed, therefore * INFO block is valid * returns: 0 if error, nonzero iff we were able to find the file successfully * postconditions: on a nonzero return, INFO->fileinfo contains the info * of the file we were trying to look up, filepos is 0 and filemax is * the size of the file. */ static int reiserfs_open_file( char *dirname ) { struct reiserfs_de_head *de_head; char *rest, ch; __u32 dir_id, objectid, parent_dir_id = 0, parent_objectid = 0; char linkbuf[PATH_MAX]; /* buffer for following symbolic links */ int link_count = 0; int mode; errnum = 0; dir_id = cpu_to_le32(REISERFS_ROOT_PARENT_OBJECTID); objectid = cpu_to_le32(REISERFS_ROOT_OBJECTID); while ( 1 ) { DEBUG_F( "dirname=%s\n", dirname ); /* Search for the stat info first. */ if ( !search_stat( dir_id, objectid ) ) return 0; DEBUG_F( "sd_mode=0%o sd_size=%Lu\n", sd_mode((struct stat_data *) INFO->current_item ), sd_size(INFO->current_ih, INFO->current_item )); mode = sd_mode((struct stat_data *)INFO->current_item); /* If we've got a symbolic link, then chase it. */ if ( S_ISLNK( mode ) ) { int len = 0; DEBUG_F("link count = %d\n", link_count); DEBUG_SLEEP; if ( ++link_count > MAX_LINK_COUNT ) { DEBUG_F("Symlink loop\n"); errnum = FILE_ERR_SYMLINK_LOOP; return 0; } /* Get the symlink size. */ INFO->file->len = sd_size(INFO->current_ih, INFO->current_item); /* Find out how long our remaining name is. */ while ( dirname[len] && !isspace( dirname[len] ) ) len++; if ( INFO->file->len + len > sizeof ( linkbuf ) - 1 ) { errnum = FILE_ERR_LENGTH; return 0; } /* Copy the remaining name to the end of the symlink data. Note * * that DIRNAME and LINKBUF may overlap! */ memmove( linkbuf + INFO->file->len, dirname, len + 1 ); INFO->fileinfo.k_dir_id = dir_id; INFO->fileinfo.k_objectid = objectid; INFO->file->pos = 0; if ( !next_key() || reiserfs_read_data( linkbuf, INFO->file->len ) != INFO->file->len ) { DEBUG_F("reiserfs_open_file - if !next_key || reiserfs_read_data\n"); DEBUG_SLEEP; errnum = FILE_IOERR; return 0; } DEBUG_F( "symlink=%s\n", linkbuf ); DEBUG_SLEEP; dirname = linkbuf; if ( *dirname == '/' ) { /* It's an absolute link, so look it up in root. */ dir_id = cpu_to_le32(REISERFS_ROOT_PARENT_OBJECTID); objectid = cpu_to_le32(REISERFS_ROOT_OBJECTID); } else { /* Relative, so look it up in our parent directory. */ dir_id = parent_dir_id; objectid = parent_objectid; } /* Now lookup the new name. */ continue; } /* if we have a real file (and we're not just printing * * possibilities), then this is where we want to exit */ if ( !*dirname || isspace( *dirname ) ) { if ( !S_ISREG( mode ) ) { errnum = FILE_ERR_BAD_TYPE; return 0; } INFO->file->pos = 0; INFO->file->len = sd_size(INFO->current_ih, INFO->current_item); INFO->fileinfo.k_dir_id = dir_id; INFO->fileinfo.k_objectid = objectid; return next_key(); } /* continue with the file/directory name interpretation */ while ( *dirname == '/' ) dirname++; if ( !S_ISDIR( mode ) ) { errnum = FILE_ERR_NOTDIR; return 0; } for ( rest = dirname; ( ch = *rest ) && !isspace( ch ) && ch != '/'; rest++ ) ; *rest = 0; while ( 1 ) { char *name_end; int num_entries; if ( !next_key() ) return 0; if ( INFO->current_ih->ih_key.k_objectid != objectid ) break; name_end = INFO->current_item + ih_item_len(INFO->current_ih); de_head = ( struct reiserfs_de_head * ) INFO->current_item; num_entries = ih_entry_count(INFO->current_ih); while ( num_entries > 0 ) { char *filename = INFO->current_item + deh_location(de_head); char tmp = *name_end; if( deh_state(de_head) & (1 << DEH_Visible)) { int cmp; /* Directory names in ReiserFS are not null * terminated. * We write a temporary 0 behind it. * NOTE: that this * may overwrite the first block in * the tree cache. * That doesn't hurt as long as we * don't call next_key * () in between. */ *name_end = 0; cmp = strcmp( dirname, filename ); *name_end = tmp; if ( cmp == 0 ) goto found; } /* The beginning of this name marks the end of the next name. */ name_end = filename; de_head++; num_entries--; } } errnum = FILE_ERR_NOTFOUND; *rest = ch; return 0; found: *rest = ch; dirname = rest; parent_dir_id = dir_id; parent_objectid = objectid; dir_id = de_head->deh_dir_id; /* LE */ objectid = de_head->deh_objectid; /* LE */ } }