#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char * path);
#include <sys/types.h>
#include <dirent.h>
struct dirent *readdir(DIR *d);
\0
을 포함한 문자열이기 때문에 printf()에서 그대로 사용할 수 있다.#include <sys/types.h>
#include <dirent.h>
Int closedir(DIR *d);
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
static void do_ls(char *path);
int main(int argc, char *argv[]){
int i;
if (argc < 2) { // 실행 인자가 없다면 프로그램 종료
fprintf(stderr, "%s: no arguments\n", argv[0]);
exit(1);
}
for (i = 1; i < argc; i++) { // 실행 인자가 있다면 do_ls() 실행
do_ls(argv[i]);
}
exit(0);
}
static void do_ls(char *path){
DIR *dir_info;
struct dirent *dir_entry;
dir_info = opendir(path);
if (!dir_info) {
perror(path);
exit(1);
}
dir_entry = readdir(dir_info);
while (dir_entry) {
printf("%s\n", dir_entry->d_name);
dir_entry = readdir(dir_info);
}
closedir(dir_info);
}
main() 함수
echo x y z
do_ls() 함수
실행인자 .
은 현재 디렉터리를 의미한다.
현재 디렉터리의 모든 파일이 파일명을 출력한 결과이다.
#include <sys/stat.h>
#include <sys/types.h>
int mkdir(const char *path, mode_t mode);
mode & ~umask
비트연산으로 계산된다.mkdir()에서 많이 발생하는 실패 원인은 다음과 같다.
메세지 | 내용 |
---|---|
ENOENT | 상위 디렉터리가 없음 |
ENOTDIR | path로 지정한 상위 디렉터리가 아님 |
EEXIST | path로 지정한 경로에 이미 파일이나 디렉터리가 존재함 |
EPERM | 상위 디렉터리에 대한 변경 권한이 없음 |
#include <sys/types.h>
#include <sys/stat.h>
mode_t umask(mode_t mask);
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
int main(int argc, char *argv[]){
int i;
if(argc<2){
fprintf(stderr, "%s: no arguments\n", argv[0]);
exit(1);
}
for(i=1;i<argc;i++){
if(mkdir(argv[i], 0777)<0){
perror(argv[i]);
exit(1);
}
}
exit(0);
}
#include <unistd.h>
int rmdir(const char *path);
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]){
int i;
if(argc<2){
fprintf(stderr, "%s: no arguments\n",argv[0]);
exit(1);
}
for(i=1;i<argc;i++){
if(rmdir(argv[i])<0){
perror(argv[i]);
exit(1);
}
}
exit(0);
}
$ echo 'This is file.' > a
$ ln a b
#include <unistd.h>
int link(const char *src, const char *dest);
- src와 dest는 동일한 파일 시스템에 있어야 한다.
- src와 dest에 디렉터리는 사용할 수 없다. 즉, 디렉터리에 하드 링크를 붙일 수 없다.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]){
if(argc!=3){
fprintf(stderr,"%s: wrong arguments\n",argv[0]);
exit(1);
}
if(link(argv[1],argv[2])<0){
perror(argv[1]);
exit(1);
}
exit(0);
}
ls -l
가 출력하는 항목 중 두 번째 열이 이름의 개수를 의미한다. 이를 링크 카운터라고 한다.ln.c
와 anothername
모두 같은 실체를 가리키고 있으므로 2로 증가했다.
- 심볼릭 링크에는 대응하는 실체가 존재하지 않아도 된다.
- 실제로 액세스 할 때가 아니면 이름과 실체의 매핑을 하지 않기 때문에 실체가 없어도 만들 수 있다.
- 파일 시스템의 경계를 뛰어넘어 별명을 붙일 수 있다.
- 디렉터리에도 별명을 붙일 수 있다.
#include <unistd.h>
int symlink(const char *src, const char *dest);
#include <unistd.h>
int readlink(const char *path, char *buf, size_t bufsize);
\0
을 기록하지 않는다.#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char*argv[]){
if(argc!=3){
fprintf(stderr,"%s: wrong number of arguments\n",argv[0]);
exit(1);
}
if(symlink(argv[1],argv[2])<0){
perror(argv[1]);
exit(1);
}
exit(0);
}
ls -l
의 출력 결과 anothername2
가 symlink.c
를 가리키고 있다.anothername2
가 symlink.c
의 심볼릭 링크 파일임을 알 수 있다.#include <unistd.h>
int unlink(const char *path);
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]){
int i;
if(argc<2){
fprintf(stderr, "%s: no arguments\n",argv[0]);
exit(1);
}
for(i=1;i<argc;i++){
if(rmdir(argv[i])<0){
perror(argv[i]);
exit(1);
}
}
exit(0);
}
ls
명령어 실행 결과 junk
파일이 없어진 것을 확인할 수 있다.$ mv a b
$ ln a b
$ rm a
#nclude <stdio.h>
int rename(const char *src, const char *dest);
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]){
if(argc!=3){
fprintf(stderr,"%s:wrong arguments\n",argv[0]);
exit(1);
}
if(rename(argv[1],argv[2])<0){
perror(argv[1]);
exit(1);
}
exit(0);
}
현재 디렉터리에 있는 mv.c
파일명을 mv2.c
로 바꾸었다.
현재 디렉터리에 있는 mv2.c
파일을 mvdir 디렉터리로 이동시켰다.
mvdir 디렉터리에 있는 mv2.c
파일을 상위 디렉터리로 이동시키고 파일명을 mv.c
로 바꾸었다.
- 파일의 종류
- 크기
- 권한
- 소유자
- 그룹
- 작성 시각
- 변경 시각
- 액세스 시각
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *buf);
int lstat(const char *path, struct sat *buf);
stat() path로 지정한 엔트리 정보를 취득해서 buf에 써넣는다.
lstat()은 stat()과 거의 같지만 path가 심볼릭 링크일 경우 해당 링크를 따라가지 않고 심볼릭 링크 자신의 정보를 반환하는 차이점이 있다.
struct stat 타입의 멤버들은 다음과 같다.
타입 | 멤버이름 | 설명 |
---|---|---|
dev_t | st_dev | 디바이스 번호 |
ino_t | st_ino | i 노드 번호 |
mode_t | st_mode | 파일 타입과 권한을 포함한 플래그 |
nlink_t | st_nlink | 링크 카운터 |
uid_t | st_uid | 소유 사용자 ID |
gid_t | st_gid | 소유 그룹 ID |
dev_t | st_rdev | 디바이스 파일의 종류를 나타내는 번호 |
off_t | st_size | 파일 크기(바이트 단위) |
blksize_t | st_blksize | 파일의 블록 크기 |
blkcnt_t | st_blocks | 블록 수 |
time_t | st_atime.tv_sec | 최종 액세스 시각의 초 단위 |
long | st_atime.tv_nsec | 최종 액세스 시각의 나노 초 단위 |
time_t | st_mtime.tv_sec | 최종 변경 시각의 초 단위 |
long | st_mtime.tv_nsec | 최종 변경 시각의 나노 초 단위 |
time_t | st_ctime.tv_sec | 메타 정보의 최종 변경 시각의 초 단위 |
long | st_ctime.tv_nsec | 메타 정보의 최종 변경 시각의 나노 초 단위 |
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
static char *filetype(mode_t mode);
int
main(int argc, char *argv[])
{
struct stat st;
if (argc != 2) {
fprintf(stderr, "wrong argument\n");
exit(1);
}
if (lstat(argv[1], &st) < 0) {
perror(argv[1]);
exit(1);
}
printf("type\t%o (%s)\n", (st.st_mode & S_IFMT), filetype(st.st_mode));
printf("mode\t%o\n", st.st_mode & ~S_IFMT);
printf("dev\t%llu\n", (unsigned long long)st.st_dev);
printf("ino\t%lu\n", (unsigned long)st.st_ino);
printf("rdev\t%llu\n", (unsigned long long)st.st_rdev);
printf("nlink\t%lu\n", (unsigned long)st.st_nlink);
printf("uid\t%d\n", st.st_uid);
printf("gid\t%d\n", st.st_gid);
printf("size\t%ld\n", st.st_size);
printf("blksize\t%lu\n", (unsigned long)st.st_blksize);
printf("blocks\t%lu\n", (unsigned long)st.st_blocks);
printf("atime\t%s", ctime(&st.st_atime));
printf("mtime\t%s", ctime(&st.st_mtime));
printf("ctime\t%s", ctime(&st.st_ctime));
exit(0);
}
static char*
filetype(mode_t mode)
{
if (S_ISREG(mode)) return "file";
if (S_ISDIR(mode)) return "directory";
if (S_ISCHR(mode)) return "chardev";
if (S_ISBLK(mode)) return "blockdev";
if (S_ISFIFO(mode)) return "fifo";
if (S_ISLNK(mode)) return "symlink";
if (S_ISSOCK(mode)) return "socket";
return "unknown";
}
메타 정보를 변경하는 시스템 콜은 다음과 같다.
변경 대상 | 시용하는 시스템 콜 |
---|---|
권한 | chmod(2) |
오너와 그룹 | chown(2) |
최종 액세스 시각과 최종 갱신 시각 | utime(2) |
#include <sys/stat.h>
int chmod(const char *path, mode_t mode);
chmod()는 path로 지정한 파일의 모드를 mode로 변경한다.
mode는 다음과 같은 상수를 OR
로 묶어서 지정하거나 0755 같은 숫자를 사용한다.
상수 | 값 | 의미 |
---|---|---|
S_IRUSR, S_IREAD | 00400 | 소유한 사용자가 읽기 가능 |
S_IWUSR, S_IWRITE | 00200 | 소유한 사용자가 쓰기 가능 |
S_IXUSR, S_IEXEC | 00100 | 소유한 사용자가 실행 가능 |
S_IRGRP | 00040 | 소유한 사용자가 속한 그룹이 읽기 가능 |
S_IWGRP | 00020 | 소유한 사용자가 속한 그룹이 쓰기 가능 |
S_IXGRP | 00010 | 소유한 사용자가 속한 그룹이 실행 가능 |
S_IROTH | 00004 | 그 외의 사용자가 읽기 가능 |
S_IWOTH | 00002 | 그 외의 사용자가 쓰기 가능 |
S_IXOTH | 00001 | 그 외 사용자가 실행 가능 |
C언어에서 숫자에 0을 앞에 두면 8진수가 된다.
예를 들어 권한 644의 경우, 0644
또는 S_IRUSR | S_lWUSR | S_IRGRP | S_IROTH |
로 지정한다.
#include <unistd.h>
int chown(const char *path, uid_t owner, gid_t group);
int lchown(const char *path, uid_t owner, gid_t group);
#include <sys/types.h>
#include <utime.h>
int utime(const char *path, struct utimbuf *buf);
struct utimebuf{
time_t actime; // 최종 액세스 시각
time_t modtime; // 최종 갱신 시각
};
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
int
main(int argc, char *argv[])
{
int mode;
int i;
if (argc < 2) {
fprintf(stderr, "no mode given\n");
exit(1);
}
mode = strtol(argv[1], NULL, 8);
for (i = 2; i < argc; i++) {
if (chmod(argv[i], mode) < 0) {
perror(argv[i]);
}
}
exit(0);
}
#include <sys/types.h>
#includde <sys/stat.h>
#include <fcntln.h>
int open(const *path, int flags);
int open(const char *path, int flags, mode_t mode);
open()은 path로 지정한 경로의 파일에 대한 스트림을 만들고 그 스트림을 가리키는 파일 디스크럽터를 반환한다.
flags에는 파일을 어떤 모드로 열 것인지 flag들의 비트 연산자 OR
을 사용하여 지정한다.
flag | 의미 |
---|---|
O_RDONLY | 읽기 전용 |
O_WRONLY | 쓰기 전용 |
O_RDWR | 읽고 쓰기 |
O_CREATE | 파일이 존재하지 않으면 새롭게 만든다 |
O_EXCL | O_CREAT와 함께 사용되어 이미 파일이 존재하면 에러가 된다 |
O_TRUNC | O_CREAT와 함께 사용되어 이미 파일이 존재하면 파일의 크기를 0으로 만든다 |
O_APPEND | write() 함수가 항상 파일의 끝에 쓰도록 설정한다 |
mode는 flags에 O_CREAT를 설정했을 때만 유효한 인자다.
umask라는 값과 비트 연산되어 그 파일의 권한을 지정한다.