<TIL> File Programming

이영민·2023년 3월 25일
0

2023_TABA_2기

목록 보기
1/3
post-thumbnail

1. mycreat

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#define MAX_BUF 64
char fname[] ="newfile";
char dummy[] ="TABA OS 2023 [leeyoungmin]\n";
int main(int argc, char *argv[]){
        //변수 선언
        int fd, read_size, write_size =0;
        char buf[MAX_BUF];

        fd = open(fname,O_RDWR | O_CREAT|O_TRUNC,0664);//1

        if(fd<0){
                printf("error: %d",errno);
        }
        write_size=write(fd,dummy,sizeof(dummy)); //2
        //error handling

        printf("write to file %s write size %d\n", fname, write_size);
        close(fd); //3
}
  • Makefile
    CC=gcc
    CFLAGS=-g
    LDFLAGS=-lpthread
    #LDLIBS=
    OBJS=mycreat.o
    TARGET=mycreat
    
    $(TARGET): $(OBJS)
            $(CC) -o $@ $(OBJS) $(LIBS)
    %.o: %.c %.h
            $(CC) $(CFLAGS) -c $(SRCS) $(HEARS)
    clean :
            rm -f *.o
            rm -f *.gch
            rm -f $(TARGET)

2. mycat

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#define MAX_BUF 64

int main(int argc,char* argv[]){
        char buf[MAX_BUF];
        int fd,r_size,w_size;
        //
        fd = open(argv[1],O_RDWR); //1
        if(fd<0){
                printf("error %d",errno);
        }
        r_size = read(fd,buf,MAX_BUF); //2

        while(1){
                r_size = read(fd, buf, MAX_BUF);
                if(r_size==0)
                        break;
                w_size = write(STDOUT_FILENO,buf,sizeof(buf));//3
        }
        close(fd);
}
  • Makefile
    CC=gcc
    CFLAGS=-g
    LDFLAGS=-lpthread
    #LDLIBS=
    OBJS=mycat.o
    TARGET=mycat
    
    $(TARGET): $(OBJS)
            $(CC) -o $@ $(OBJS) $(LIBS)
    %.o: %.c %.h
            $(CC) $(CFLAGS) -c $(SRCS) $(HEARS)
    clean :
            rm -f *.o
            rm -f *.gch
            rm -f $(TARGET)

3. mycp; Data copy

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#define MAX_BUF 64

int main(int argc,char* argv[]){
        int fd1, fd2;
        int r_size,w_size;
        char buf[MAX_BUF];

        if(argc != 3){ // argc[0]에 파일경로, 이름 이 두가지 정보가 들어왔을때 코드가 실행된다.
        printf("USAGE: %s file_name \n",argv[0]);
        exit(-1);
        } // test_2.c 에서 추가된 부분

        if(fd1<0 || fd2<0){
                printf("error: file not opened");
        }
        fd1 = open(argv[1],O_RDONLY); //1
        fd2 = open(argv[2],O_RDWR |O_CREAT,0666); //1-1

        while(1){
                r_size = read(fd1,buf,MAX_BUF); //2
                if(r_size==0){
                        break;
                }
                w_size = write(fd2,buf,r_size);//3
        }
        close(fd1);
        close(fd2);

}
  • Makefile
    CC=gcc
    CFLAGS=-g
    LDFLAGS=-lpthread
    #LDLIBS=
    OBJS=mycp.o
    TARGET=mycp
    
    $(TARGET): $(OBJS)
            $(CC) -o $@ $(OBJS) $(LIBS)
    %.o: %.c %.h
            $(CC) $(CFLAGS) -c $(SRCS) $(HEARS)
    clean :
            rm -f *.o
            rm -f *.gch
            rm -f $(TARGET)

4. mycp_adv.c ; 파일의 접근 권한까지 복사(+ fstat)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#define MAX_BUF 64
int main(int argc, char *argv[]){

        int fd_origin, fd_dest, read_size, write_size =0;
        char buf[MAX_BUF];

        struct stat *stat_origin=(struct stat *)malloc(sizeof(struct stat));
        mode_t flag_origin;
/*
        if (argc!=3){
                printf("USAGE: %s origin dest\n",argv[0]);
                exit(-1);
        }*/
        fd_origin = open(argv[1], O_RDONLY);
/*
        if(fd_origin<0){
                printf("fd_origin open: %d",errno);
        } */

        if(fstat(fd_origin,stat_origin) !=0){ // fd_origin에 저장된 파일 정보를 stat_origin 버퍼에 읽는다.
                printf("error: %d",errno);
        } //1

        flag_origin =stat_origin->st_mode; //fstat()을 통해 조사된 fd_orgin의 st_mode(;접근정보)를 알 수 있다.
				//2

        //read and write file
        printf("flag origin: %o \n",flag_origin);

        fd_dest = open(argv[2], O_RDWR|O_CREAT|O_SYNC, flag_origin);
        /*open error handling
        if(fd_dest<0){
                printf("fd_dest open: %d",errno);
        }*/
        //orgin file의 Data 카피
        while((read_size = read(fd_origin, buf, MAX_BUF))!= 0){
                 //write to the dest file
                write_size = write(fd_dest, buf, read_size);
        }
        close(fd_origin);
        close(fd_dest);
}
  • fstat()
    • 역할: 열려진 파일의 크기, 파일의 권한, 파일의 생성일시, 파일의 최종 변경일 등, 파일의 상태나 파일의 정보를 얻는 함수입니다.
    • 헤더: #include <sys/types.h> #include <sys/stat.h> #include <unistd.h>
    • 원형: int fstat(int fd, struct stat *buf);
    • 인자
      • int fd: open() 된 파일 디스크립터이다.
      • struct stat *buf: 파일의 상태 및 정보를 저장할 수 있는 구조체
        • 내용
          struct stat {
              dev_t     st_dev;     /* ID of device containing file */
              ino_t     st_ino;     /* inode number */
              mode_t    st_mode;    /* 파일의 종류 및 접근권한 */
              nlink_t   st_nlink;   /* hardlink 된 횟수 */
              uid_t     st_uid;     /* 파일의 owner */
              gid_t     st_gid;     /* group ID of owner */
              dev_t     st_rdev;    /* device ID (if special file) */
              off_t     st_size;    /* 파일의 크기(bytes) */
              blksize_t st_blksize; /* blocksize for file system I/O */
              blkcnt_t  st_blocks;  /* number of 512B 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 status change */
          };
          
           이 중에서 주요 내용을 보면,
           st_mode : 파일의 종류와 file에 대한 access 권한 정보
             파일의 종류 체크하는 POSIX macro입니다.
            S_ISREG(buf.st_mode) : 일반 파일 여부
            S_ISDIR(buf.st_mode) : 디렉토리 여부
            S_ISCHR(buf.st_mode) : character device 여부
            S_ISBLK(buf.st_mode) : block device 여부
            S_ISFIFO(buf.st_mode) : FIFO 여부
            S_ISLNK(buf.st_mode) : symbolic link 여부
            S_ISSOCK(buf.st_mode) : socket 여부 (주로 AF_UNIX로 socket 생성된 경우)
          
           st_mode는 파일의 유형값으로 직접 bit & 연산으로 여부를 확인가능합니다.
            S_IFMT     0170000   파일 유형의 전체의 bit or 값
            
            /* 파일 유형 */
            S_IFSOCK   0140000   socket
            S_IFLNK    0120000   symbolic link
            S_IFREG    0100000   regular file
            S_IFBLK    0060000   block device
            S_IFDIR    0040000   directory
            S_IFCHR    0020000   character device
            S_IFIFO    0010000   FIFO
              
            /* 특수 권한 설정 bit */
            S_ISUID    0004000   set-user-ID bit
            S_ISGID    0002000   set-group-ID bit
            S_ISVTX    0001000   sticky bit
              
            접근 권한 값(chmod의 값과 같음)
            S_IRWXU    00700     mask for file owner permissions
            S_IRUSR    00400     owner has read permission
            S_IWUSR    00200     owner has write permission
            S_IXUSR    00100     owner has execute permission
            S_IRWXG    00070     mask for group permissions
            S_IRGRP    00040     group has read permission
            S_IWGRP    00020     group has write permission
            S_IXGRP    00010     group has execute permission
            S_IRWXO    00007     mask for permissions for others (not in group)
            S_IROTH    00004     others have read permission
            S_IWOTH    00002     others have write permission
            S_IXOTH    00001     others have execute permission    
              
           st_atime, st_mtime, st_ctime member 변수는 time관련 함수(time.h)를 이용하여 conversion후에 
           사용하면 쉽게 사용할 수 있습니다. localtime(3), ctime(3)
    • 반환값:
      • 0인 경우: 정상적으로 조회
      • -1인 경우: 오류가 발생했으며 상세한 내용은 errno에 저장되어있다.
  • Makefile
    CFLAGS=-g
    LDFLAGS=-lpthread
    #LDLIBS=
    OBJS=mycp_adv.o
    TARGET=mycp_adv
    
    $(TARGET): $(OBJS)
            $(CC) -o $@ $(OBJS) $(LIBS)
    %.o: %.c %.h
            $(CC) $(CFLAGS) -c $(SRCS) $(HEARS)
    clean :
            rm -f *.o
            rm -f *.gch
            rm -f $(TARGET)

5. myls

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <dirent.h>
#include <sys/types.h>
int main(int argc, char *argv[]){

        DIR *dir=NULL;
        struct dirent* dentry=NULL;
        char *dir_name=".";                 //default

        if (argc == 1){ // args 없는 경우 현재 디렉토리 "." 내용을 보여줌.
                dir = opendir(dir_name);        }
        else if (argc == 2){
                dir_name = argv[1]; //warning.
                dir = opendir(dir_name); // dir_name의 DIR포인터 반환
        }else {
                printf("argc %d : We only accept 1 or 2 args for now\n", argc);
                exit(-1);
        }

        while((dentry = readdir(dir) )!=NULL){
                printf("%s \n", dentry->d_name);
        }
        closedir(dir);
}
  • opendir()
    • 헤더: dirent.h
    • 원형: DIR *opendir(**const char** *name)
    • 인수: const char *name: 열기 대상 디렉토리
    • 반환: DIR 열기에 성공하면 디렉토로 정보 구조체인 DIR 포인터를 반환하고 실패하면 NULL을 반환합니다.
  • readdir()
    • 헤더: dirent.h
    • 원형: `struct dirent readdir( DIR dir)`
    • 인수: DIR* dir: opendir() 열기한 디렉터리 정보
    • 반환: 성공하면 파일이나 디렉터리 정보를 반환(struct dirent * 타입으로) 하고 실패하면 NULL을 반환한다.
  • closedir()
    • 헤더: dirent.h
    • 원형: int closedir(DIR* dir)
    • 인수: DIR* dir opendir() 에서 열기한 디렉토리 정보
    • 반환: 0→ 성공, -1→ 실패
  • struct dirent
    dirent 구조체는 다음과 같이 선언된다.
     struct dirent
    {
        long d_ino;                                /* 아이노드 */
        off_t d_off;                                 /* dirent 의 offset */
        unsigned short d_reclen;            /* d_name 의 길이 */
        char d_name [NAME_MAX+1];   /* 파일 이름(없다면 NULL로 종료) */
    }

0개의 댓글