디바이스 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
이 코드를 보시면 알겠지만, EXT2 의 경우에는 SuperBlock 의 첫번째 필드가
Inode Count 이지요.
이건 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 를 만들어서 접근할테니, 커널소스상에 헤더들을 보면
많은 도움이 될듯 싶네요.
댓글 달기