디바이스 read한 뒤 파싱하면 이상한 값이...
글쓴이: you / 작성시간: 토, 2003/06/28 - 3:49오후
요즘 거의 매일 질문올리는 사람입니다. -_-;;
너그러이 봐주시고요 ^^
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
main()
{
int fd, index=0, i, j, total=0;
char buf[512];
unsigned char data[4+1];
fd=open("/dev/fd0", O_RDONLY);
lseek(fd, 1024, SEEK_SET);
read(fd, buf, 512);
for(i=3; i>=0; i--)
data[i]=*((unsigned char *)buf + index++);
data[4]='\0';
for(i=0, j=3; i<4; i++, j--){
printf("%02x", data[i]);
total+=data[i]<<8*j;
}
printf("\n%u\n", total);
}
위의 코드는
플로피를 ext2로 포맷한뒤에
그 첫번째 블록그룹에서 수퍼블록의 일부를 read하고
그 첫번째 필드(4바이트) - inode의 총수- 를 파싱해서 hex와 dec로 출력합니다.
테스트 결과 잘 작동합니다.
(inode의 총 수가 144(?)였덩가? hex로는 0xb8입니다.)
근데 문제는
이걸 실제코드에 적용했을때입니다.
여기서 file system unique id 같은 출력하는 부분은 무시하시구요...
(다른 FS라서리...)
int parse_dump(char *dev, char *file)
{
char buf[BUFSIZE];
int fdin, n;
FILE *fpout;
if((fdin=open(dev, O_RDONLY))<0){
fprintf(stderr, "open error - read\n");
return(1);
}
if((fpout=fopen(file, "w"))==NULL){
fprintf(stderr, "fopen error - write\n");
return(2);
}
if((n=read(fdin, buf, BUFSIZE))<0){
fprintf(stderr, "read error\n");
return 10;
}
fprintf(fpout, "file system unique id : 0x");
parse(buf, sizeof(long), fpout);
fprintf(fpout, "number of blocks in this file system : 0x");
parse(buf, sizeof(long), fpout);
중략...
close(fdin);
fclose(fpout);
return 0;
}
void parse(void *Data, int nBytes, FILE *fpout)
{
int i, j, index=0, total=0x0;
unsigned char Buffer[0x8 + 1];
for(i=nBytes-1; i>=0; i--)
Buffer[i]=*((unsigned char *)Data + index++);
Buffer[nBytes]='\0';
for(i=0, j=nBytes-1; i<nBytes; i++, j--){
fprintf(fpout, "%02x", Buffer[i]);
total+=Buffer[i]<<8*j;
}
fprintf(fpout, "\t%u\n", total);
}
이렇게 해서 플로피의 수퍼블록을 읽어들이면
이상한 값이 파싱됩니다.
Quote:
file system unique id : 0x30303030 808464432
number of blocks in this file system : 0x30303030 808464432
number of free blocks in this file system : 0x20384220 540557856
logical block size, bytes : 0x30203030 807415856
number of blocks in a block group : 0x2030 8240
첫번째 필드인 inode 총수 - 위에는 unique id로 되있는데 그건 다른 FS라서 그런거구요, 테스트는 ext2로 했으므로 inode총수입니다 - 는 0x30303030(?)인가? 로 되고
나머지 필드들도 거의 이값 비슷하게 됩니다.
위의 테스트 코드에서는 잘되는데
왜 여기선 안되는지 도저히 모르겠네요
아.
그리고 read()한 다음에 함수-parse()- 호출해서 offset이 계속 그대로 있으므로 모든 필드가 같은 값일거라 생각해서
수정해봤습니다.
void parse(int fdin, int nBytes, FILE *fpout)
{
int i, j, index=0, total=0x0;
unsigned char Buffer[0x8 + 1], Data[0x8 + 1];
if(read(fdin, Data, nBytes)<0){
fprintf(stderr, "read error\n");
exit(-1);
}
for(i=nBytes-1; i>=0; i--)
Buffer[i]=*((unsigned char *)Data + index++);
Buffer[nBytes]='\0';
for(i=0, j=nBytes-1; i<nBytes; i++, j--){
fprintf(fpout, "%02x", Buffer[i]);
total+=Buffer[i]<<8*j;
}
fprintf(fpout, "\t%u\n", total);
}
read()를 함수내에서 계속 호출하므로 offset은 계속 전진하지 않나요?
그럼에도 결과는 별 차이 없었습니다.
아무래도 다른 문제가 있는것 같은데 도저히 모르겠네요 ㅠㅠ
허접한 소스지만
잘 부탁드립니다.
Forums:


EXT2 의 SuperBlock Structure
/* * Structure of the super block */ struct ext2_super_block { __u32 s_inodes_count; /* Inodes count */ __u32 s_blocks_count; /* Blocks count */ __u32 s_r_blocks_count; /* Reserved blocks count */ __u32 s_free_blocks_count; /* Free blocks count */ __u32 s_free_inodes_count; /* Free inodes count */ __u32 s_first_data_block; /* First Data Block */ __u32 s_log_block_size; /* Block size */ __s32 s_log_frag_size; /* Fragment size */ __u32 s_blocks_per_group; /* # Blocks per group */ __u32 s_frags_per_group; /* # Fragments per group */ __u32 s_inodes_per_group; /* # Inodes per group */ __u32 s_mtime; /* Mount time */ __u32 s_wtime; /* Write time */ __u16 s_mnt_count; /* Mount count */ __s16 s_max_mnt_count; /* Maximal mount count */ __u16 s_magic; /* Magic signature */ __u16 s_state; /* File system state */ __u16 s_errors; /* Behaviour when detecting errors */ __u16 s_minor_rev_level; /* minor revision level */ __u32 s_lastcheck; /* time of last check */ __u32 s_checkinterval; /* max. time between checks */ __u32 s_creator_os; /* OS */ __u32 s_rev_level; /* Revision level */ __u16 s_def_resuid; /* Default uid for reserved blocks */ __u16 s_def_resgid; /* Default gid for reserved blocks */ /* * These fields are for EXT2_DYNAMIC_REV superblocks only. * * Note: the difference between the compatible feature set and * the incompatible feature set is that if there is a bit set * in the incompatible feature set that the kernel doesn't * know about, it should refuse to mount the filesystem. * * e2fsck's requirements are more strict; if it doesn't know * about a feature in either the compatible or incompatible * feature set, it must abort and not try to meddle with * things it doesn't understand... */ __u32 s_first_ino; /* First non-reserved inode */ __u16 s_inode_size; /* size of inode structure */ __u16 s_block_group_nr; /* block group # of this superblock */ __u32 s_feature_compat; /* compatible feature set */ __u32 s_feature_incompat; /* incompatible feature set */ __u32 s_feature_ro_compat; /* readonly-compatible feature set */ __u8 s_uuid[16]; /* 128-bit uuid for volume */ char s_volume_name[16]; /* volume name */ char s_last_mounted[64]; /* directory where last mounted */ __u32 s_algorithm_usage_bitmap; /* For compression */ /* * Performance hints. Directory preallocation should only * happen if the EXT2_COMPAT_PREALLOC flag is on. */ __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/ __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */ __u16 s_padding1; __u32 s_reserved[204]; /* Padding to the end of the block */ };이 코드를 보시면 알겠지만, EXT2 의 경우에는 SuperBlock 의 첫번째 필드가
Inode Count 이지요.
struct reiserfs_super_block { __u32 s_block_count; __u32 s_free_blocks; /* free blocks count */ __u32 s_root_block; /* root block number */ __u32 s_journal_block; /* journal block number */ __u32 s_journal_dev; /* journal device number */ /* Since journal size is currently a #define in a header file, if ** someone creates a disk with a 16MB journal and moves it to a ** system with 32MB journal default, they will overflow their journal ** when they mount the disk. s_orig_journal_size, plus some checks ** while mounting (inside journal_init) prevent that from happening */ /* great comment Chris. Thanks. -Hans */ __u32 s_orig_journal_size; __u32 s_journal_trans_max ; /* max number of blocks in a transaction. */ __u32 s_journal_block_count ; /* total size of the journal. can change over time */ __u32 s_journal_max_batch ; /* max number of blocks to batch into a trans */ __u32 s_journal_max_commit_age ; /* in seconds, how old can an async commit be */ __u32 s_journal_max_trans_age ; /* in seconds, how old can a transaction be */ __u16 s_blocksize; /* block size */ __u16 s_oid_maxsize; /* max size of object id array, see get_objectid() commentary */ __u16 s_oid_cursize; /* current size of object id array */ __u16 s_state; /* valid or error */ char s_magic[12]; /* reiserfs magic string indicates that file system is reiserfs */ __u32 s_hash_function_code; /* indicate, what hash function is being use to sort names in a directory*/ __u16 s_tree_height; /* height of disk tree */ __u16 s_bmap_nr; /* amount of bitmap blocks needed to address each block of file system */ __u16 s_version; /* I'd prefer it if this was a string, something like "3.6.4", and maybe 16 bytes long mostly unused. We don't need to save bytes in the superblock. -Hans */ __u16 s_reserved; __u32 s_inode_generation; __u32 s_flags; /* Right now used only by inode-attributes, if enabled */ unsigned char s_uuid[16]; /* filesystem unique identifier */ unsigned char s_label[16]; /* filesystem volume label */ char s_unused[88] ; /* zero filled by mkreiserfs and * reiserfs_convert_objectid_map_v1() * so any additions must be updated * there as well. */ } __attribute__ ((__packed__));이건 ReiserFS 의 SuperBlock Structure 입니다. 보시다시피,
첫번째 4 Byte 가 Inode Count 가 아닌, Block Count 입니다.
파일시스템이 틀린 경우에 적용되질 않는다고 하셨기에,
한번 다른 파일시스템의 SuperBlock 를 본 겁니다만,
이런식으로 SuperBlock Structure 가 파일시스템마다 틀리기 때문에,
다른 파일시스템에 그대로 적용하기는 힘들 겁니다.
Portable 하게 하기 위해서는 차라리 저 Structure 의 필드값을 사용하는게
나을듯 싶습니다.
PS) 저 코드들은 다 커널소스상에 include/linux/ 안에 있습니다.
EXT2 SuperBlock Structure 는 ext2_fs.h 안에,
ReiserFS SuperBlock Structure 는 reiserfs_fs_sb.h 안에 있습니다.
리눅스상에서 지원하는 다른 파일시스템 역시 비슷한 식으로
Structure 를 만들어서 접근할테니, 커널소스상에 헤더들을 보면
많은 도움이 될듯 싶네요.
댓글 달기