더 많은 정보를 담은 리눅스 교재를 배포했습니다. 아래의 페이지에서 리눅스 교재를 받아가세요.
https://reakwon.tistory.com/233
파일 정보 얻어오기
파일에 대한 정보를 얻어올때는 lstat시스템 콜을 사용하면 됩니다. 사실 stat, lstat, fstat등 여러가지 시스템 콜이 있는데요, 가장 간단하게 사용할 수 있는 시스템 콜이기 때문에 여기서는 lstat을 사용하겠습니다.
우선 lstat에 관한 시스템 콜 원형부터 보겠습니다.
int lstat(const char *filename, struct stat * buf);
lstat은 두개의 인자를 받게 되어있군요.
filename : 말 그대로 파일의 이름입니다. 하지만 경로를 명시하지 않을때는 현재 디렉토리를 기준으로 파일을 찾습니다. 절대경로나 상대경로를 줄 수 있다는 점은 알고 잇으세요.
buf : 파일의stat구조체를 저장합니다. stat??
무엇일까요. 구조체부터 보도록 하지요. vi 편집기를 사용한다면 lstat에서 3+K(shift)를 입력하면 시스템 콜을 볼 수 있습니다. 조금 더 밑으로 내려가다 보면 stat구조체를 만나볼 수 있게 되는데요. 아래와 같습니다.
struct stat
{
dev st_dev; /* device */
ino_t st_ino; /* inode */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device type (if inode device) */
off_t st_size; /* total size, in bytes */
unsigned long st_blksize; /* blocksize for filesystem I/O */
unsigned long st_blocks; /* number of blocks allocated *.
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last change */
}
음.. 파일에 대한 여러정보를 알 수 있군요.
st_ino는 inode를 말하는 것이고 st_mode는 파일이 디렉토리인가, 단순 파일인가, 케릭터 디바이스인가를 알 수 있는 것이겠구요.
uid, gid도 알 수 있고 파일의 사이즈도 알 수 있습니다. 더군다나 파일이 언제 수정되고 접근되었는지에 대한 시간 정보도 알 수 있군요! 굿!!
그 중에서 ls명령어에 사용되는 st_mode는 어떤 파일의 타입인지 저장되어 있습니다. 어떤 파일 타입인지 알아보기 위해서 매크로 함수를 제공하는데요. 이것에 대해서 조금 더 알아보기 위해서 표로 준비해보았습니다.
모드 | 설명 |
S_ISLNK(m) | 심볼릭 링크 파일인지 확인합니다. |
S_ISREG(m) | 단순 파일인지 확인합니다. |
S_ISDIR(m) | 디렉토리인지 확인합니다. |
S_ISCHR(m) | 문자 디바이스인지 확인합니다. |
S_ISBLK(m) | 블록 디바이스인지 확인합니다. |
S_ISFIFO(m) | FIFO파일인지 확인합니다. 선입선출 구조의 파일인지 확인하는 것이죠. |
S_ISSOCK(m) | 네트워크 통신에 필요한 소켓파일인지 확인합니다. |
반환값 : 성공시 0이 반환되고 실패시 -1이 반환됩니다. 에러가 발생했다면 적절한 값으로 설정된다고 하는데 에러에 대해서는 구글형님께 물어봅시다.
구현
이제 대충 알아보았으니 코드를 직접 짜보도록하겠습니다. 우선 코드부터 보시죠.
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#define BUF_SIZE 1024
void printType(const char *name,const struct stat *buf){
if(S_ISDIR(buf->st_mode))
printf("%s is DIR \n",name);
else if(S_ISREG(buf->st_mode))
printf("%s is FILE\n", name);
else if(S_ISSOCK(buf->st_mode))
printf("%s is SOCKET\n",name);
else if(S_ISCHR(buf->st_mode))
printf("%s is CHARACTER DEVICE\n",name);
else if(S_ISFIFO(buf->st_mode))
printf("%s is FIFO\n",name);
else if(S_ISBLK(buf->st_mode))
printf("%s is BLOCK DEVICE\n",name);
else if(S_ISLNK(buf->st_mode))
printf("%s is LINK\n",name);
}
void printTime(struct stat *buf){
struct tm *mtime;
mtime=localtime(&buf->st_mtime);
printf("%04d-%02d-%02d %02d:%02d\n",
mtime->tm_year+1900, mtime->tm_mon+1,
mtime->tm_mday, mtime->tm_hour,
mtime->tm_min);
}
void printFileSize(const char *name, struct stat *buf){
printf("%s size: %ld\n",name,buf->st_size);
}
int main(){
char filename_dir[128]="dir";
char filename_file[128]="aaa";
struct stat file;
struct stat dir;
lstat(filename_dir,&dir);
lstat(filename_file,&file);
printType(filename_dir,&dir);
printTime(&dir);
printFileSize(filename_dir,&dir);
printf("\n");
printType(filename_file,&file);
printTime(&file);
printFileSize(filename_file, &file);
}
# gcc lstat.c
# mkdir dir
# touch aaa
# vi aaa
ABCDEF
:wq
# ./a.out
dir is DIR
2018-11-19 00:06
dir size : 6
aaa is FILE
2018-11-19 00:46
aaa size : 7
'컴퓨터 > 운영체제(주로 리눅스)' 카테고리의 다른 글
[리눅스] 시그널(Signal) 3 sigpending, sigismember, sigsuspend (0) | 2018.12.31 |
---|---|
[리눅스] 시그널 (SIGNAL) 2 시그널 함수 sigprocmask, sigfillset, sigemptyset, sigaddset, sigdelset (11) | 2018.12.31 |
[리눅스] 시그널1 신호(SIGNAL)의 개념과 자세히 들여다 보기 - 시그널 핸들러 (0) | 2018.12.10 |
[리눅스] 프로세스 생성과 특징, 종료 (fork, wait), 예제 코드 (0) | 2018.12.10 |
[리눅스] 리눅스 파일 열기(open), 읽기(read), 쓰기(write) 구현 (5) | 2018.11.18 |