리눅스는 다중 사용자 OS이기 때문에 각 파일의 접근 가능 정도를 아는 것이 중요하다.
리눅스는 파일에 대한 정보를 얻어올 수 있는 stat 구조체를 제공한다.
stat 구조체에 있는 field들은 다음과 같다
struct stat {
dev_t st_dev; /* 장치파일의 위치 및 여부 device id */
ino_t st_ino; /* 파일의 inode 번호 */
mode_t st_mode; /* file permission 정보 */
nlink_t st_nlink; /* 하드링크의 갯수 */
uid_t st_uid; /* user id */
gid_t st_gid; /* group id */
dev_t st_rdev; /* 장치파일(inode)를 기술 */
off_t st_size; /* 해당 파일의 총 크기*/
blksize_t st_blksize; /* 효율적인 I/O 파일 시스템 위한 블럭 사이즈*/
blkcnt_t st_blocks; /* 할당된 블럭 사이즈 */
};
이 중 st_mode 필드를 이용해 file permission 정보를 알 수 있다.
또한 st_mode 에 적용할 수 있는 mask 들이 define 되어 있기 때문에 가져다 쓸 수 있다.
stat 구조체를 이용해 파일 정보를 불러오기 위해서는 지정된 파일에 대한 정보를 반환하는 함수들이 필요하다.
stat 구조체는 이 함수들의 인자로도 쓰인다.
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char* path, struct stat* buf);
int fstat(int filedes, struct stat *buf);
int lstat(const char* path, struct stat* buf);
이 함수들은 지정된 파일에 대한 정보를 반환한다. 접근 권한은 따로 필요 없지만 파일이 위치하는 디렉토리의 읽기 권한은 필요하다.
stat과 lstat은 첫번째 인자로 pathname을 받으며 stat 구조체에 그 정보를 저장한다
fstat의 경우 해당하는 파일의 디스크립터를 받아 stat 구조체에 정보를 저장한다.
lstat은 인자로 받은 경로가 Symbolic Link인 경우 링크 파일 자체의 정보를 가져다 주지만, stat은 링크가 가리키는 파일의 정보를 가져다 준다.
다음은 해당 구조체와 함수를 이용해 리눅스 파일의 permission까지 복사하도록 코드를 작성해보았다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <stdlib.h> #include <fcntl.h> #define BUF_SIZE 1000 void error_handling(char* message); int main(int argc, char* argv[]) { int org_fd, cp_fd; char buf[BUF_SIZE]; struct stat in_file_stat; int file_permission = 0; int read_size = 0; int count = 0; if(argc != 3){ printf("Usage : %s <origin file> <copy file>\n",argv[0]); exit(1); } stat(argv[1], &in_file_stat); file_permission=in_file_stat.st_mode; org_fd=open(argv[1],O_CREAT|O_RDONLY,0777); cp_fd=open(argv[2],O_CREAT|O_WRONLY,file_permission); if(org_fd==-1 || cp_fd==-1) error_handling("open() error!"); while(1){ read_size = read(org_fd, buf, BUF_SIZE); if(read_size == -1) { error_handling("read() error!"); } else if(read_size < BUF_SIZE){ puts(buf); ++count; write(cp_fd,buf, read_size); printf("EOF\n"); break; } puts(buf); ++count; write(cp_fd,buf,BUF_SIZE); } printf("read&write call : %d\n",count); close(org_fd); close(cp_fd); return 0; } void error_handling(char *message) { fputs(message, stderr); fputc('\n', stderr); exit(1); } | cs |