본문 바로가기

UNIX_LINUX_C_C++

unix 파일구조/파일탐색

파일은 자신을 나타내기 위해서 수많은 정보를 가지고 있다. 파일이름, 파일크기, 파일의 권한, 파일의 종류(디바이스인지, 링크인지, 소켓인지, 일반파일인지)등 이다. 이번기사는 파일의 상태를 가져오는 방법에 대해서 논의 하고자 한다.


Unix 에서는 디렉토리, 장치, 소켓, FIFO 등 모든것이 파일로 존재한다. 그러므로 우선 우리는 작업을 하고자 하는 파일이 어던 종류의 파일인지를 먼저 판단할수 있어야 한다. Unix 상에서 "ls -al" 을 이용하면 아래와 같은 결과물을 볼수 있을것이다.
[yundream@localhost test]# ls -al
...
-rw-r--r-- 1 root root 249 9월 10 11:25 wc.1
drwxr-xr-x 2 root root 4096 12월 5 18:01 web_install
srwxr-xr-x 1 root root 0 1월 14 18:05 loging_socket
...



위의 결과에서 가장 앞부분 10자리가 그 파일의 특성과 권한을 나타내는데, 그중 제일 앞부분이 파일의 종류를 나타내고, 우리는 가장 앞부분의 한바이트의 문자를 이용해서 어떤 종류의 파일인지를 알아낼수 있다.
Unix 에서 자주 사용하는 파일의 종류를 아래 테이블에 정리해 두었으니 참고 바란다.
- 일반 파일
s 소켓파일
d 디렉토리
p FIFO
l 심볼링 링크된 파일
b 블럭 디바이스
c 캐릭터 디바이스



파일 정보 가져오기 #
파일의 정보는 stat(2)를 통해서 가지고 오며, 가지고온 정보는 struct stat 구조체에 저장된다. stat 구조체는 다음과 같은 내용을 가지고 있다.

  1. structstat
  2. {
  3. dev_tst_dev;/*device*/
  4. ino_tst_ino;/*inode*/
  5. mode_tst_mode;/*protection*/
  6. nlink_tst_nlink;/*numberofhardlinks*/
  7. uid_tst_uid;/*userIDofowner*/
  8. gid_tst_gid;/*groupIDofowner*/
  9. dev_tst_rdev;/*devicetype(ifinodedevice)*/
  10. off_tst_size;/*totalsize,inbytes*/
  11. unsignedlongst_blksize;/*blocksizeforfilesystemI/O*/
  12. unsignedlongst_blocks;/*numberofblocksallocated*/
  13. time_tst_atime;/*timeoflastaccess*/
  14. time_tst_mtime;/*timeoflastmodification*/
  15. time_tst_ctime;/*timeoflastchange*/
  16. };

위의 구조체의 정보는 inode 테이블을 참조해서 가지고오며, 우리가 필요로 하는(그 이상의) 상세한 정보를 가져온다는 것을 알수 있을것이다. inode 테이블에 대한 내용을 원한다면 /usr/src/linux/include/fs.h 의 sturct inode 를 참조하면 된다.


그럼 간단한 예제 프로그램을 만들어 보겠다. 이 프로그램은 아규먼트로 파일이름을 받아서 그 파일의 정보를 되돌려주는 프로그램으로, 파일의 권한, 퍼미션, 파일의 크기, 마지막에 수정된 날짜, 파일의 종류 등을 되돌려줄것이며, 존재하지 않는 파일의 경우 적절한 에러메시지를 출력하고 종료하게 될것이다.
이 예제의 이름은 file_info 로 하겠다.

  1. #include <unistd.h>
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <unistd.h>
  5. #include<stdio.h>
  6. #include<pwd.h>
  7. #include<grp.h>
  8. intmain(intargc,char**argv)
  9. {
  10. intreturn_stat;
  11. char*file_name;
  12. structstatfile_info;
  13. structpasswd*my_passwd;
  14. structgroup*my_group;
  15. mode_tfile_mode;
  16. if(argc!=2)
  17. {
  18. printf("Usage:./file_info[filename]\n");
  19. exit(0);
  20. }
  21. file_name=argv[1];
  22. if((return_stat=stat(file_name,&file_info))==-1)
  23. {
  24. perror("Error:");
  25. exit(0);
  26. }
  27. file_mode=file_info.st_mode;
  28. printf("파일이름:%s\n",file_name);
  29. printf("=======================================\n");
  30. printf("파일타입:\n");
  31. if(S_ISREG(file_mode))
  32. {
  33. printf("정규파일\n");
  34. }
  35. elseif(S_ISLNK(file_mode))
  36. {
  37. printf("심볼릭링크\n");
  38. }
  39. elseif(S_ISDIR(file_mode))
  40. {
  41. printf("디렉토리\n");
  42. }
  43. elseif(S_ISCHR(file_mode))
  44. {
  45. printf("문자디바이스\n");
  46. }
  47. elseif(S_ISBLK(file_mode))
  48. {
  49. printf("블럭디바이스\n");
  50. }
  51. elseif(S_ISFIFO(file_mode))
  52. {
  53. printf("FIFO\n");
  54. }
  55. elseif(S_ISSOCK(file_mode))
  56. {
  57. printf("소켓\n");
  58. }
  59. my_passwd=getpwuid(file_info.st_uid);
  60. my_group=getgrgid(file_info.st_gid);
  61. printf("OWNER:%s\n",my_passwd->pw_name);
  62. printf("GROUP:%s\n",my_group->gr_name);
  63. printf("FILESIZEIS:%d\n",file_info.st_size);
  64. printf("마지막읽은시간:%d\n",file_info.st_atime);
  65. printf("마지막수정시간:%d\n",file_info.st_mtime);
  66. printf("하드링크된파일수:%d\n",file_info.st_nlink);
  67. }

완벽하진 않지만 그럭저럭 작동하는 프로그램이다.


프로그램은 아마 설명이 필요 없을 정도로 간단할것이다. 단지 마지막의 file_info.st_nlink (하드링크) 부분이 약간 헷갈릴 것이다. 하드링크란 보통 C 의 link(2) 함수와 쉘 코멘드인 link 에 -d 옵션을 줌으로서 만들어 진다. cp 를 이용한 복사와 하드링크를 혼동하지 말라, cp 를 이용한 복사는 자신만의 inode 를 가지는 전혀 새로운 파일을 만들지만, 하드링크의 경우 동일한 inode 를 가지고 파일이름을 만든다. 하드링크는 inode 를 가지고 파일이름을 만들므로 서로 다른 파일시스템 사이로 연결할수는 없다.
그 이유는 inode 가 해당 파일시스템에서만 유일하기 때문으로 여러개의 파일시스템을 사용할경우 다른 쪽 파일시스템에서 그 inode 가 유일함을 보장할수 없기 때문이다.


stat 는 너무 복잡합니다. 더 간단한 함수는 없을까요?
우리가 어떤 프로그램을 만들때, 우리는 종종 그 프로그램이 사용하는 파일(설정파일, 데이타 파일)들이 존재하는지 등을 검사할 필요가 있다. 이때에도 위의 stat 를 이용해서 해결 할수 있지만, 왠지 복잡하다는 생각이든다.
이때는 access(2) 를 사용하면된다.


access 는 검사할 파일에 대하여 4가지 항목, 읽을수 있는지(R_OK), 쓸수 있는지 (W_OK), 실행가능 한지 (X_OK), 존재하는 파일인지(F_OK) 등에 대한 정보를 돌려준다.

#include

  1. #include
  2. intmain(intargc,char**argv)
  3. {
  4. if(access(argv[1],F_OK)!=0)
  5. perror("파일이존재하지않음:");
  6. else
  7. printf("파일존재함\n");
  8. }

--------------------------------------------------------------------------

파일탐색

main(int argc,char *argv[])
{
DIR *dp; // 선언부
struct dirent *ds;
struct stat sb;
char path[512];
dp=opendir(DIRPATH); // OPEN 여기서는 /proc 임 = DIRPATH
if (argc != 2 &&argc != 3 )
usage();
len = strlen(argv[1]);
memcpy(pidstr,argv[1],len);
if (argc == 3) {
signo=atoi(argv[2]);
if (signo < 1 || signo > 35)
usage();
}
for(;;) {
if ((ds = readdir(dp)) == NULL) // 여기서 리드..
break;
sprintf(path,"%s/%s",DIRPATH,ds->d_name);
if (stat(path,&sb) < 0)
continue;
if (!S_ISREG(sb.st_mode))
continue;
PrintPrpsinfo(path);
}
exit(0);
}