Types of files
- regular file : 텍스트 또는 이전 데이터 파일
- directory : 파일의 목록을 저장한 파일
- symbolic link file : 이미 존재하는 파일이나 디렉토리에 접근할 수 있는 새로운 이름
- special file : 장치와 데이터를 주고 받는 통로(장치 번호를 inode에 저장)
- character device file : character 단위로 데이터 전송
- block device file : block 단위로 데이터 전송
File organization
- file name(hard link) : 사용자가 파일에 접근할 때 사용
- inode
- 파일에 대한 정보를 저장
- 번호를 통해 관리/접근
- ls -i : inode번호 확인
- data block : 실제 데이터가 저장된 디스크의 공간
- file open : fd array -> file table -> inode -> disk의 data block
stat
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
int stat(const char* pathname, struct stat* buf);
int fstat(int fd, struct stat* buf);
- inode에 저장된 파일 정보를 읽어 옴
- pathname : 파일 경로
- buf : 파일의 정보를 저장한 주소
- return
- 0 : success
- -1 : error
Example
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
int main(void) {
struct stat buf;
stat("printFileInfo.c", &buf);
printf("Inode = %d\n", (int)buf.st_ino);
printf("Mode = %o\n", (unsigned int)buf.st_mode);
printf("Nlink = %o\n", (int)buf.st_uid);
printf("UID - %d\n", (int)buf.st_gid);
printf("SIZE = %d\n", (int)buf.st_size);
printf("Atime = %d\n", (int)buf.st_atime);
printf("Mtime = %d\n", (int)buf.st_mtime);
printf("Ctime = %d\n", (int)buf.st_ctime);
printf("Blksize = %d\n", (int)buf.st_blksize);
printf("Blocks = %d\n", (int)buf.st_blocks);
return 0;
}
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
int main(void) {
struct stat buf;
int kind;
stat("checkFileType.c", &buf);
printf("Mode = %o (Hexa = %x)\n",
(unsigned int)buf.st_mode, (unsigned int)buf.st_mode);
kind = buf.st_mode & S_IFMT;
printf("Kind = %x\n", kind);
// 정의된 매크로 사용
if (S_ISREG(buf.st_mode)) printf("checkFileType.c : Regular File\n");
return 0;
}
access
#include <unistd.h>
int access(const char* pathname, int mode);
- 현재 process가 가진 접근 권한 확인
- pathname : 파일의 경로
- mode : 확인할 권한
- return
- 0 : 권한 있음
- -1 : error
Example
#include <sys/errno.h>
#include <unistd.h>
#include <stdio.h>
extern int errno;
int main(void) {
int per;
if (access("linux.bak", F_OK) == -1 && errno == ENOENT)
printf("linux.bak: File not exist.\n");
per = access("linux.txt", R_OK);
if (per == 0)
printf("linux.txt: Read permission is permitted.\n");
else if (per == -1 && errno == EACCES)
printf("linux.txt: Read permission is not permitted.\n");
return 0;
}
chmod
#include <sys/stat.h>
int chmod(const char* pathname, mode_t mode);
int fchmod(int fd, mode_t mode);
- pathname : 파일의 경로
- mode : 적용하려는 권한
- return
- 0 : success
- -1 : error
Example
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
int main(void) {
struct stat buf;
chmod("linux.txt", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH); // 754
stat("linux.txt", &buf);
printf("Permission change 1 = %o\n", (unsigned int)buf.st_mode);
buf.st_mode |= S_IWGRP; // 774
buf.st_mode &= ~(S_IROTH); // 770
chmod("linux.txt", buf.st_mode);
stat("linux.txt", &buf);
printf("Permission change 1 = %o\n", (unsigned int)buf.st_mode);
return 0;
}
Directory
- file name과 file name이 가리키는 inode 번호를 담고 있는 파일
※ file open : directory에서 가리키는 inode 번호 -> i-list -> inode -> disk의 data block
- sub-directory : directory 안의 directory
- special direcotries : 모든 directory가 퐇마하는 directory들 ex) .(current directory) ..(parent's directory)
- pathname : 절대 경로(루트 디렉토리 기준), 상대 경로(현재 디렉토리 기준)
mkdir, rmdir, rename
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int mkdir(const char* pathname, mode_t mode);
int rmdir(const char* pathname);
int rename(const char* oldpath, const char* newpath);
- return
- 0 : success
- -1 : fail
Example
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#define PRINT_ERR_EXIT(_msg) {perror(_msg); exit(1);}
int main(void) {
if (mkdir("system", 0755) == -1)
PRINT_ERR_EXIT("system");
if (mkdir("programming", 0755) == -1)
PRINT_ERR_EXIT("programming");
if (rename("system", "systemProgramming") == -1)
PRINT_ERR_EXIT("systemProgramming");
if (rmdir("programming") == -1)
PRINT_ERR_EXIT("programming");
return 0;
}
getcwd
#include <unistd.h>
char* getcwd(char* buf, size_t size);
- 현재 디렉토리 경로
- buf가 NULL인 경우, 내부에서 동적 할당 후 주소 리턴
- return : path가 저장된 buf의 주소, NULL : error
chdir
#include <unistd.h>
int chdir(const char* path);
- 디렉토리 변경
- return
- 0 : success
- -1 : fail
Example
#include <unistd.h>
#include <stdio.h>
int main(void) {
char* cwd;
char wd[BUFSIZ];
cwd = getcwd(NULL, BUFSIZ);
printf("1. Current Directory : %s\n", cwd);
chdir("newDir");
getcwd(wd, BUFSIZ);
printf("2. Current Directory : %s\n", wd);
return 0;
}
open a directory file
#include <sys/types.h>
#include <dirent.h>
DIR* opendir(const char* name);
- name : 열려는 디렉토리 이름
- return : 열린 디렉토리의 DIR 포인터, NULL:error
close a directory file
#include <sys/types.h>
#include <dirent.h>
int closedir(DIR* dirp);
- dirp : 닫으려는 DIR 포인터
- return
- 0 : success
- -1 : fail
read a directory file
#include <dirent.h>
struct dirent* readdir(DIR* dirp);
- Directory 내용을 하나씩 읽어 옴
- dirp : 읽으려는 directory file 의 포인터
- return : 현재 읽엉온 항목의 dirent 구조체를 가리키는 포인터, NULL : 더 이상 읽어올 항목이 없음
Example
#include <dirent.h>
#include <stdlib.h>
#include <stdio.h>
int main(void) {
DIR* dp;
struct dirent *dent;
if ((dp = opendir("systemProgramming")) == NULL) {
perror("opendir: systemProgramming");
exit(1);
}
while ((dent = readdir(dp))) {
printf("Name : %s ", dent->d_name);
printf("Inode : %d\n", (int)dent->d_ino);
}
closedir(dp);
return 0;
}
offset of a directory file
#include <dirent.h>
long telldir(DIR* dirp);
void seekdir(DIR* dirp, long loc);
void rewinddir(DIR* dirp);
Example
#include <sys/stat.h>
#include <dirent.h>
#include <stdlib.h>
#include <stdio.h>
int main(void) {
DIR* dp;
struct dirent* dent;
if ((dp = opendir("systemProgramming")) == NULL)
{
perror("opendir");
exit(1);
}
printf("** Directory content **\n");
printf("Start Offset : %ld\n", telldir(dp));
while ((dent = readdir(dp))) {
printf("Read : %s ", dent->d_name);
printf("Cur Offset : %ld\n", telldir(dp));
}
printf("** Directory Pointer Rewind **\n");
rewinddir(dp);
printf("Cur Offset : %ld\n", telldir(dp));
printf("** Move Directory Pointer **\n");
seekdir(dp, 2);
printf("Cur Offset : %ld\n", telldir(dp));
dent = readdir(dp);
printf("Read : %s ", dent->d_name);
printf("Next Offset : %ld\n", telldir(dp));
closedir(dp);
return 0;
}
Link(Hard link)
- 디렉토리에서 파일 이름과 inode를 연결한 것
- 디렉토리의 inode -> i-list -> disk
- 동일 file system 내에 여러 개의 hard link 생성 가능
- 링크 수 = hard link 수
- 링크 수 = 0 -> 파일 삭제
- 다른 file system에 있는 inode에 대한 hard link는 불가능
Symbolic link(Soft link)
- 실제 파일의 경로명을 저장하는 또 다른 파일(새로운 inode 사용)
- 디렉토리의 inode -> i-list -> disk에 있는 실제 경로 -> 디렉토리 -> i-list-> disk
- 다른 file system의 파일/폴더 연결 가능
making a link
#include <unistd.h>
int link(const char* oldpath, const char* newpath);
int symlink(const char* target, const char* linkpath);
- return
- 0 : success
- -1 : fail
removing a link
#include <unistd.h>
#include <stdio.h>
int unlink(const char* pathname); // dir에 사용 불가
int remove(const char* pathname);
- pathname : 삭제하려는 hard link 경로
- return
- 0 : success
- -1 : error
Example
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void) {
struct stat buf;
stat("linux.txt", &buf);
printf("Before Link Count = %d\n", (int)buf.st_nlink);
link("linux.txt", "linux.ln");
stat("linux.txt", &buf);
printf("After Hard Link Count = %d\n", (int)buf.st_nlink);
symlink("linux.txt", "linux.sym");
stat("linux.txt", &buf);
printf("After Soft Link Count = %d\n", (int)buf.st_nlink);
int cnt;
cnt = unlink("linux.sym");
if (cnt == -1)
{
perror("Unlink linux.sym");
exit(1);
}
printf("Unlink linux.sym success!!\n");
return 0;
}
get symbolic link file info
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int lstat(const char* pathname, struct stat* buf);
- symbolic link file 자체의 파일 정보를 얻어 옴
- return
- 0 : success
- -1 : error
#include <unistd.h>
ssize_t readlink(const char* pathname, char* buf, size_t bufsiz);
- symbolic link에 저장된 데이터 읽기 -> 상대 경로가 됨
- return : 읽은 byte의 수, -1 : error
#include <limits.h>
#include <stdlib.h>
char* realpath(const char* path, char* resolved_path);
- symbolic link가 가리키는 파일의 절대 경로를 얻음
- resolved_path : 결과 값을 저장할 buffer, NULL인 경우 내부적으로 동적 할당 후 포인터 반환
- return : 결과가 저장된 buffer의 포인터, NULL : error
'💻 Computer Science > System' 카테고리의 다른 글
[System] 프로세스 (0) | 2024.01.25 |
---|---|
[System] 시스템 정보 (0) | 2024.01.24 |
[System] High-Level File I/O (1) | 2024.01.24 |
[System] Low-Level File I/O (1) | 2024.01.23 |
[System] Thread (0) | 2024.01.04 |