[제3장] 파일 사용하기
=================================================================
* Subject : [제3장] 파일 사용하기
* Writer: w0rm9 (research.hackerschool.org)
* Date: 2004/01/16
=================================================================
/* 책에 나와있던 gets, puts...등의 함수들은 생략했습니다.
* 스터디 시간에 하지 않았던 부분이라서..
*/
0x01. 저수준 파일 액세스
프로그램이 시작될 때 가지는 세 개의 파일 기술자
0 : 표준입력
1 : 표준출력
2 : 표준에러
■ write
사용법)
#include <unistd.h>
size_t write(int fildes, const void *buf, size_t nbytes);
=> buf를 nbytes만큼 fildes와 관련된 파일에 기록
테스트)
[w0rm9@work FILE]$ cat write.c
#include <unistd.h>
#include <stdio.h>
int main()
{
write(1, "wiseguys output!!\n", 18);
write(2, "wiseguys error!!\n", 17);
exit(0);
}
[w0rm9@work FILE]$ gcc -o write write.c
[w0rm9@work FILE]$ ./write
wiseguys output!!
wiseguys error!!
■ read
사용법)
#include <unistd.h>
size_t read(int fildes, void *buf, size_t nbytes);
=> fildes와 관련된 파일로부터 nbytes 바이트까지 데이터를 읽어서 buf에 저장
테스트)
[w0rm9@work FILE]$ cat read.c
#include <unistd.h>
#include <stdio.h>
int main()
{
char buf[100];
int nread;
nread = read(0, buf, 100);
write(1, buf , nread);
}
[w0rm9@work FILE]$ gcc -o read read.c
[w0rm9@work FILE]$ ./read
wiseguys~
wiseguys~
■ open
사용법)
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
int open(const char *path, int oflags);
int open(const char *path, int oflags, mode_t mode);
=> paht를 oflags와 mode에 관련하여 연다.
□ oflags의 필수적인 파일 액세스 모드
O_RDONLY 읽기 전용 상태로 연다.
O_WRONLY 쓰기 전용 상태로 연다.
O_RDWR 읽기와 쓰기 상태로 연다.
□ oflags의 선택적인 모드
O_APPEND 파일의 마지막에 데이터를 추가한다.
O_TRUNC 기존의 내용을 제거하고, 파일의 길이를 0으로 설정한다.
O_CREAT 필요하다면 mode에 주저진 상태로 파일을 생성한다.
O_EXCL O_CREAT와 함께 사용되며, 파일이 이미 존재하면 실해할 것이다.
□ O_CREAT 플래그를 사용할때, 세 파라미터로 사용해야할 플래그
S_IRUSR 소유자 읽기 허용
S_IWUSR 소유자 쓰기 허용
S_IXUSR 소유자 실행 허용
S_IRGRP 그룹 읽기 허용
S_IWGRP 그룹 쓰기 허용
S_IXGRP 그룹 실행 허용
S_IROTH 기타 읽기 허용
S_IWOTH 기타 쓰기 허용
S_IXOTH 기타 실행 허용
테스트)
[w0rm9@work FILE]$ cat open.c
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
int main()
{
int one, two;
one = open("file.one", O_CREAT|O_EXCL, S_IRUSR|S_IRGRP|S_IROTH);
if(one==-1)
printf("exist\n");
two = open("file.two", O_CREAT, S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
exit(0);
}
[w0rm9@work FILE]$ touch file.one
[w0rm9@work FILE]$ gcc -o open open.c
[w0rm9@work FILE]$ ./open
exist
[w0rm9@work FILE]$ ls -al file.*
-rw-rw-r-- 1 w0rm9 w0rm9 0 1월 16 02:19 file.one
-r-xr-xr-x 1 w0rm9 w0rm9 0 1월 16 02:10 file.two
■ close
사용법)
#include <unistd.h>
int close(int fildes);
=> fildes와 파일의 관계를 정리하기 위해 close를 사용
■ lseek
사용법)
#include <unistd.h>
#include <sys/types.h>
off_t lseek(int fildes, off_t offset, int whence);
=> files의 읽기/쓰기 포인터를 whence를 기준으로 offset을 지정
□ whence에 올 수 있는 것들
SEEK_SET offset은 절대 위치이다.
SEEK_CUR offset은 현대 위치에 상대적이다.
SEEK_END offset은 파일의 마지막에 상대적이다.
■ fstat, stat 그리고 lstat
사용법)
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
int fstat(int fildes, struct stat *buf);
int stat(const char *path, struct stat *buf);
int lstat(const char *path, struct stat *buf);
=> fstat : 파일 기술자와 관련된 파일에 대한 상태 정보를 반환
stat : 링크가 참조하는 파일에 대한 정보를 반환
lstat : 링크자체에 대한 정보를 반환
struct stat {
unsigned short st_dev; //파일이 존재하는 장치
unsigned short __pad1;
unsigned long st_ino; //파일과 관련된 inode
unsigned short st_mode; //파일 허용 권한과 파일 형태 정보
unsigned short st_nlink; //파일에 대한 하드 링크의 수
unsigned short st_uid; //파일 소유자의 사용자 식별자
unsigned short st_gid; //파일 소유자의 그룹 식별자
unsigned short st_rdev;
unsigned short __pad2;
unsigned long st_size;
unsigned long st_blksize;
unsigned long st_blocks;
unsigned long st_atime; //마지막 액세스 시간
unsigned long __unused1;
unsigned long st_mtime; //내용에 대한 마지막 변경 시간
unsigned long __unused2;
unsigned long st_ctime; //허용 권한, 소유자, 그룹, 내용에 대한 마지막 변경 시간
unsigned long __unused3;
unsigned long __unused4;
unsigned long __unused5;
};
테스트)
[w0rm9@work FILE]$ cat stat.c
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
int main(int argc, char **argv)
{
int file;
struct stat buf;
file = open(argv[1], O_RDONLY);
fstat(file, &buf);
printf("fstat => uid: %d, gid: %d\n", buf.st_uid, buf.st_gid);
stat(argv[1], &buf);
printf("stat => uid: %d, gid: %d\n", buf.st_uid, buf.st_gid);
lstat(argv[1], &buf);
printf("lstat => uid: %d, gid: %d\n", buf.st_uid, buf.st_gid);
}
[w0rm9@work FILE]$ ln -s /bin/sh stat.test
[w0rm9@work FILE]$ gcc -o stat stat.c
[w0rm9@work FILE]$ ./stat stat.test
fstat => uid: 0, gid: 0
stat => uid: 0, gid: 0
lstat => uid: 519, gid: 519
[w0rm9@work FILE]$ id
uid=519(w0rm9) gid=519(w0rm9) groups=519(w0rm9)
0x02. 표준 I/O 라이브러리
프로그램이 시작될 때 열리는 세 개의 파일 스트림
stdin : 표준입력
stdout : 표준출력
stderr : 표준에러
■ fopen
사용법)
#include <stdio.h>
FILE *fopen(const char *filename, const char *mode);
=> filename에 지정된 파일을 mode에 관련하여 열고 스트림에 관련시킨다.
□ mode
"r" 또는 "rb" 읽기 전용으로 연다.
"w" 또는 "wb" 쓰기 상태로 열고, 길이를 0으로 줄인다.
"a" 또는 "ab" 쓰기 상태로 열고, 파일의 마지막에 추가한다.
"r+" 또는 "rb+" 또는 "r+b" 갱신(읽기 + 쓰기) 상태로 연다.(b는 바이너리파일)
"w+" 또는 "wb+" 또는 "w+b" 갱신 상태로 열고, 길이를 0으로 줄인다.
"a+" 또는 "ab+" 또는 "a+b" 갱신 상태로 열고, 파일의 마지막에 추가한다.
■ fread
사용법)
#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);
=> stream으로 부터 레코드 크기 size와 개수 nitems에 의한 지정만큼 ptr로 읽어들인다.
■ fwrite
사용법)
#include <stdio.h>
size_t fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream);
=> ptr에 지정된 데이터 버퍼로부터 stream에 기록한다.
■ fclose
사용법)
#include <stdio.h>
int fclose(FILE *stream);
테스트)
[w0rm9@work FILE]$ cat fread.c
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp1, *fp2;
size_t nfp1;
char buf[BUFSIZ+1];
fp1 = fopen("fread.c", "r");
fp2 = fopen("fwrite.test", "w");
nfp1 = fread(buf, sizeof(char), BUFSIZ, fp1);
fwrite(buf, sizeof(char), nfp1, fp2);
fclose(fp1);
fclose(fp2);
}
[w0rm9@work FILE]$ gcc -o fread fread.c
[w0rm9@work FILE]$ ./fread
[w0rm9@work FILE]$ cat fwrite.test
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp1, *fp2;
size_t nfp1;
char buf[BUFSIZ+1];
fp1 = fopen("fread.c", "r");
fp2 = fopen("fwrite.test", "w");
nfp1 = fread(buf, sizeof(char), BUFSIZ, fp1);
fwrite(buf, sizeof(char), nfp1, fp2);
fclose(fp1);
fclose(fp2);
}
■ fflush
사용법)
#include <stdio.h>
int fflush(FILE *stream);
=> 스트림을 강제 방출한다.
■ perror
사용법)
#include <stdio.h>
void perror(const char *s);
테스트)
[w0rm9@work FILE]$ cat perror.c
#include <errno.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
FILE *fp;
fp = fopen("xxxxx", "r");
if(!fp) perror("오 노우..");
}
[w0rm9@work FILE]$ gcc -o perror perror.c
[w0rm9@work FILE]$ ./perror
오 노우..: No such file or directory
__eof__
