리눅스 프로그래밍 - 5주차 3.3~4.4

고강희·2022년 9월 28일
1

3.3 Obtaining File Information: stat and fstat

stat은 파일의 상태정보를 알려주는 system call

System call: stat(2)

#include <sys/stat.h>

int stat(const char *pathname, struct stat *buf);
int fstat(int filedes, struct stat *buf);
int lstat(const char *pathname, struct stat *buf);

세가지 모두 파일의 상태정보를 제공하는것은 똑같음. (return 0 on success, -1 on error)

  • stat : pathname을 통해 정보를 얻음
  • fstat : 파일 디스크립터 값을 통해 정보를 얻음
  • lstat : symbolic link파일의 정보를 얻음
    • 만약 File A가 File B에대한 symlink 파일일경우, fstat(A),stat(A)를 하면 파일 B에대한 정보를 얻음, 반면
      lstat(A)는 A에대한 정보를 얻을 수 있음

struct stat

struct stat{
	mode_t	st_mode; 	// 파일의 타입, 모드 (권한 = permission)
    ino_t	st_ino; 	// i-node 번호
    dev_t	st_dev; 	// device 번호
    dev_t 	st_rdev;	// special 파일에대한 device 번호
    nlink_t st_nlink;	// link 카운트
    uid_t	st_uid;		// user id of owner
    gid_t	st_gid;		// group id of owner
    off_t	st_size;	// byte 크기 (for regular files)
    time_t	st_atime;	// 마지막 접근 시간
    time_t	st_mtile;	// 마지막 수정 시간
    time_t	st_ctime;	// 마지막 상태 수정 시간
    blksize_t st_blksize;	// block size (for file system i/o
    blkcnt_t st_blocks;	// 할당된 disk block 수
};

Directories, File Systems and Special Files

File System and Directory

  • File system
    • directory 역시도 파일이다. 파일 시스템은 disk에 있는 디렉토리, 파일들을 사용자가 사용할 수 있게 계층적으로 만든 시스템
    • 파일 시스템은 root라는 directory부터 시작되며 root는 "/"로 표시함
  • Working directory
    • 워킹 디렉토리는 모든 프로세스에 존재함 (해당 프로세스의 워킹 디렉토리를 current working directory라 함)
    • 상대 경로로 표시되는 directory
  • Home directory
    • 로그인할때, 워킹 디렉토리는 가장 먼저 홈 디렉토리를 set함 ( 첫 실행 프로세스: bash, bash의 워킹 디렉토리 -> home)
  • Pathname
    • 절대경로 : root부터 시작하는것 ex) /home/file1/file2
    • 상대경로 : 현재 워킹 디렉토리 file2

The Implementation of Directory

Directory

  • 디렉토리는 파일에 대한 엔트리를 가짐
  • 디렉토리와 일반 파일의 차이
    • 디렉토리는 file에 대한 시스템 콜이 대부분 작동함 (file이니까)
    • 하지만 write는 불가능 -> write한다는 것은 디렉토리 안의 파일내용도 바꾼다는 것을 의미 -> 디렉토리 구조가 망가짐
    • open, creat 시스템 콜로 directory를 생성 할 수 없음
    • 있는 파일을 O_RDWR, O_WRONLY flag를 set하고 open하면 error (write가 안되니까)
    • directory 자체를 write 할 수도없음
    • 오직 커널만이 directory를 write할 수 있음
  • 디렉토리는 directory 엔트리를 가짐. 엔트리에 각각의 파일과 서브디렉토리들은 다음과 같은 내용을 담고 있음
    • i-node 번호
    • character field
  • link를 한다는것 = 파일에 또다른 이름을 부여한다는 것 = directory entry에 새롭게 추가한다는 것
  • 만약 link("abc","xyz"); 을 하게 되면 entry는 다음과 같아짐
  • unlink도 같음

Dot, and double-dot

  • "." : current working directory
  • ".." : parent directory

Example: Directory Structure

Directory Permissions

  • 디렉토리의 권한은 일반파일 권한과 똑같이 구성됨

  • 그러나 각각의 권한은 조금 다르게 해석이됨

    • read
      • 디렉토리 안의 어떤것들이 있는지 list 할 수 있게하는 권한을 부여함
    • write
      • directory 안의 파일을 만들거나 삭제할 권한을 부여함.
        이때 앞의 디렉토리는 write를 할 수 없다는 말에 의문을 가질 수 있는데, 앞에서의 write는 write 시스템 콜을 이용해 파일을 바꿀 수 없다는 것을 의미하고, write permission은 write 시스템 콜이 아닌, 다른 시스템 콜을 이용해 파일을 만들거나 삭제할 수 있다는 것을 의미함
        ex) /home/ex 에있다고 할 때 ex라는 디렉토리에 write 권한을 부여한다는 것은 ex에서 open("file2", ...) 이것은 가능하지만, open("ex", ...) 이것은 불가능 하다는 것을 의미
    • execute
      • 그 디렉토리로 직접 들어갈 수 있을 권한을 부여함. 즉, working directory를 해당 디렉토리로 바꿀 수 있음을 의미
        ex) /usr/include/stdio.h를 open하기 위해서는, '/', '/usr', '/usr/include'에 대한 execute 권한이 있어야 한다.
        read 권한과 execute 권한은 다르다 read는 그안의 내용을 list만 얻어오는것이고, execute는 직접 들어갈 수 있어야 함.
  • save-text-image (sticky bit): S_ISVTX

  • 만약 sticky bit이 디렉토리에 set됐을 경우, 디렉토리에 write permission있을 때, file 생성만 되고 삭제는 안되게 할 수 있다.

  • 삭제는 file의 소유자, directory의 소유자, superuser만이 가능하다.

Programming with Directories

Structure: dirent

#include <dirent.h>

struct dirent {
	ino_t 	d_ino;							// i-node 번호
    chsr 	d_name[NAME_MAX+1];   			// 파일 이름
}
  • 만약 d_ino가 0이면, 삭제됐다는 것을 의미. 새로 만들면 d_ino가 0인 곳에 값을 넣어줌

System Call: mkdir(2)

#include <sys/stat.h>

int mkdir(const char *pathname, mode_t mode);
  • mkdir은 directory를 만드는 system call (return 0 on success, -1 on error)
  • mode_t mode = permission을 의미 umask의 영향을 받음
  • mkdir은 '.'과 '..'을 자동으로 부여
  • 일반적으로 execute 권한은 주고 시작한다.

System Call: rmdir(2)

#include <unistd.h>

int rmdir(const char *pathname);
  • rmdir은 empty 디렉토리를 지운다. (return 0 on success, -1 on error)
  • empty 디렉토리라는 것은, 디렉토리 엔트리에 '.', '..' 두개만 있는 것을 의미함.

Function: opendir(3)

#include <dirent.h>

DIR *opendir(const char *dirname);
  • directory를 위한 open function (directory는 open system call 사용 불가능)
  • dirname을 가진 directory를 open (return pointer of dir on success, NULL on error)

Function: closedir(3)

#include <dirent.h>

int closedir(DIR *dirptr);
  • 디렉토리를 종료 반환받은 dirptr을 파라미터로 받음 (return 0 on success, -1 on error)

Function readdir(3)

#include <dirent.h>

struct dirent *readdir(DIR *dirptr);
  • directory를 read하는 함수. read는 directory entry를 보는것을 의미. 따라서 readdir(dir)하면 첫번째 entry의 dirent 구조체를 반환, 한번더 readdir(dir)하면, 두번째 entry dirent 구조체를 반환....
  • while문으로 readdir()호출하면, 디렉토리의 모든 dirent를 return. 이때 다시 첫번째 entry로 다시가는법-> rwinddir

Function rewinddir(3)

#include <dirent.h>

void rewinddir(DIR *dirptr);
  • dirptr을 directory의 첫번째 엔트리로 가게 하는 함수 ( return 0 on success, -1 on error)

The Current Working Directory

  • linux에서 모든 프로세스는 자기 자신의 커렌트 워킹 디렉토리를 가짐
  • user와 관련된 커렌트 워킹 디렉토리는 사용자가 명령어를 입력하는 shell이다.

System Call: chdir(2)

#include <unistd.h>

int chdir(const char *path);
  • cd명령어는 실제로 chdir system call을 호출
  • chdir은 커랜트 워킹 디렉토리를 바꿈 (return 0 on success, -1 on error)
  • Error case
    • path를 잘못 쓸경우
    • path에 있는 모든 디렉토리에 대한 execute permission이 있어야 한다.

Function: getcwd(3)

#include <unistd.h>

char *getcwd(char *name, size_t size);
  • 커랜트 워킹 디렉토리의 이름을 리턴 (return NULL on error)
  • size_t size는 name의 size보다 커야함

Function: ftw(3)

#include <unistd.h>
int ftw(const char *path, int(*func)(), int nopenfd);
  • 시작점으로부터 모든 디렉토리에대해 function을 수행
  • Argument
    • path : directory의 path
    • depth(nopenfd) : 동시에 몇개의 file을 execute할 수 있는지
    • func : 수행될 함수
profile
그냥 AI 관련 유익해보이는거 이것저것 적어놓음

0개의 댓글