본문 바로가기
Computer Science/UNIX & Linux

[UNIX/Linux] ep2+) 파일 함수 실습

by 클레어몬트 2024. 9. 26.

ex1. 명령행 인자로 받은 파일의 크기를 알려주는 프로그램을 작성하시오

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int main(int argc, char* argv[]) {
    if (argc == 1) {
        printf("usage: ex1 filename\n");
        exit(1);
    }

    struct stat statbuf;

    stat(argv[1], &statbuf);
    printf("SIZE = %d\n", (int)statbuf.st_size);
    
    return 0;
}

abcde 가 담긴 test.txt 파일의 크기는 6

 

 

 

ex2. 명령행 인자로 받은 파일의 종류를 출력하는 프로그램을 작성하시오

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int main(int argc, char* argv[]) {
    if (argc == 1) {
        printf("usage: ex2 filename\n");
        exit(1);
    }

    struct stat statbuf;
    int kind;

    stat(argv[1], &statbuf);
    printf("mode = %o\n", (unsigned int)statbuf.st_mode);

    kind = statbuf.st_mode & S_IFMT;
    switch (kind) {
        case S_IFLNK:
            printf("%s: symbolic link\n", argv[1]);
            break;
        case S_IFDIR:
            printf("%s: directory\n", argv[1]);
            break;
        case S_IFREG:
            printf("%s: regular file\n", argv[1]);
            break;
    }

    return 0;
}

 

 

 

ex3. 명령행 인자로 받은 파일의 정보를 추출해 다음 예와 같이 출력하는 프로그램을 작성하시오

- 파일명:

- inode번호:

- 파일종류:

- 접근권한:

- UID:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int main(int argc, char* argv[]) {
    if (argc == 1) {
        printf("usage: ex3 filename\n");
        exit(1);
    }

    struct stat statbuf;
    int kind;

    stat(argv[1], &statbuf);
    printf("file name: %s\n", argv[1]);
    printf("inode: = %d\n", (int)statbuf.st_ino);

    kind = statbuf.st_mode & S_IFMT;
    switch (kind) {
        case S_IFLNK:
            printf("link file\n");
            break;
        case S_IFDIR:
            printf("directory\n");
            break;
        case S_IFREG:
            printf("regular file\n");
            break;
    }

    printf("permission %o\n", (unsigned int)statbuf.st_mode);
    printf("UID: %d\n", (unsigned int)statbuf.st_uid);

    return 0;
}

 

 

 

ex4. 명령행 인자로 받은 파일의 UID와 접근권한을 다음 예와 같이 출력하는 프로그램을 작성하시오

a.c 1000 rw-r—r—

 

// S_IRUSR=0, S_IWUSR=1, S_IXUSR=2, S_IRGRP=0, S_IWGRP=1, …

CheckMode(statbuf.st_mode, S_IRUSR, 0);

CheckMode(statbuf.st_mode, S_IWUSR, 1);

CheckMode(statbuf.st_mode, S_IXUSR, 2);

CheckMode(statbuf.st_mode, S_IRGRP, 0);

……

void CheckMode(unsigned int mode, int m, int k) {

    if ((mode & m) != 0) {

        switch(k) {

            case 0: /* r */

                printf("r");

                break;

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

void CheckMode(unsigned int mode, int m, int k) {
    if ((mode & m) != 0) {
        switch(k) {
            case 0:  /* r */
                printf("r");
                break;
            case 1:  /* 1 */
                printf("w");
                break;
            case 2:  /* 2 */
                printf("x");
                break;
        }
    }
    else
         printf("-");
}

int main(int argc, char* argv[]) {
    if (argc == 1) {
        printf("usage: ex4 filename\n");
        exit(1);
    }

    struct stat statbuf;
    int kind;

    stat(argv[1], &statbuf);
    printf("%s %d ", argv[1], (unsigned int)statbuf.st_uid);

    // 유저 체크
    CheckMode(statbuf.st_mode, S_IRUSR, 0);
    CheckMode(statbuf.st_mode, S_IWUSR, 1);
    CheckMode(statbuf.st_mode, S_IXUSR, 2);
    // 그룹 체크
    CheckMode(statbuf.st_mode, S_IRGRP, 0);
    CheckMode(statbuf.st_mode, S_IWGRP, 1);
    CheckMode(statbuf.st_mode, S_IXGRP, 2);
    // 기타 사용자 체크
    CheckMode(statbuf.st_mode, S_IROTH, 0);
    CheckMode(statbuf.st_mode, S_IWOTH, 1);
    CheckMode(statbuf.st_mode, S_IXOTH, 2);
    printf("\n");

    return 0;
}

 

 

 

ex5. 현재 디렉터리에 있는 모든 파일 및 하위 디렉터리의 이름과 inode를 출력하는 프로그램을 작성하시오

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>

int main() {
    DIR* dp;
    struct dirent* dent;
    struct stat statbuf;

    if ((dp = opendir(".")) == NULL) {
        perror("opendir");
        exit(1);
    }

    while (dent = readdir(dp)) {
        stat(dent->d_name, &statbuf);
        printf("name: %s ", dent->d_name);
        printf("inode = %d\n", (int)statbuf.st_ino);
    }
    closedir(dp);

    return 0;
}

 

 

 

ex6. 현재 디렉터리에서 . 과 .. 항목을 제외하고 하위 디렉터리만 출력하는 프로그램을 작성하시오

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>

int main() {
    DIR* dp;
    struct dirent* dent;
    int count;
    struct stat statbuf;

    if ((dp = opendir(".")) == NULL) {
        perror("opendir");
        exit(1);
    }

    while (dent = readdir(dp)) {
        if (dent->d_name[0] == '.') 
            continue;

        stat(dent->d_name, &statbuf);
        if (S_ISDIR(statbuf.st_mode)) {
            printf("name: %s, inode: %d\n", dent->d_name, statbuf.st_ino);
        }
    }
    closedir(dp);

    return 0;
}

 

 

 

hw1. 명령행 인자로 받은 파일의 기존 접근권한을 출력하고 접근권한을 변경하는 프로그램을 작성하시오

./hw1 g+w test.txt

 

int x;

switch (argv[1][0]) {

    case 'u':

        switch (argv[1][2]) {

            case 'r': x = S_IRUSR; break;

            case 'w': x = S_IWUSR; break;

            case 'x': x = S_IXUSR; break;

……

if (argv[1][1] == '+') buf.st_mode |= x;

else if (argv[1][1] == '-') buf.st_mode &= ~(x);

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>

void print_permissions(struct stat buf);

int main(int argc, char* argv[]) {
    if (argc < 3) {
        printf("usage: hw1 permission_command file_name\n");
        exit(1);
    }

    struct stat buf;
    
    stat(argv[2], &buf);

    print_permissions(buf);

    int x = 0;
    switch (argv[1][2]) {
        case 'r': 
            x = (argv[1][0] == 'u') ? S_IRUSR : (argv[1][0] == 'g') ? S_IRGRP : S_IROTH; 
            break;
        case 'w': 
            x = (argv[1][0] == 'u') ? S_IWUSR : (argv[1][0] == 'g') ? S_IWGRP : S_IWOTH; 
            break;
        case 'x': 
            x = (argv[1][0] == 'u') ? S_IXUSR : (argv[1][0] == 'g') ? S_IXGRP : S_IXOTH; 
            break;
        default: 
            printf("invalid permission\n"); 
            exit(1);
    }

    if (argv[1][1] == '+') {
        buf.st_mode |= x;
    } else if (argv[1][1] == '-') {
        buf.st_mode &= ~x;
    } 

    chmod(argv[2], buf.st_mode); // 파일에 새로운 권한 적용
    printf("== after updated ==\n");
    print_permissions(buf);

    return 0;
}

void print_permissions(struct stat buf) {
    printf("permission: ");
    printf((buf.st_mode & S_IRUSR) ? "r" : "-");
    printf((buf.st_mode & S_IWUSR) ? "w" : "-");
    printf((buf.st_mode & S_IXUSR) ? "x" : "-");
    printf((buf.st_mode & S_IRGRP) ? "r" : "-");
    printf((buf.st_mode & S_IWGRP) ? "w" : "-");
    printf((buf.st_mode & S_IXGRP) ? "x" : "-");
    printf((buf.st_mode & S_IROTH) ? "r" : "-");
    printf((buf.st_mode & S_IWOTH) ? "w" : "-");
    printf((buf.st_mode & S_IXOTH) ? "x" : "-");
    printf("\n");
}

사용자(u)에 실행(x) 권한 부여

 

 

 

hw2. 명령행 인자로 받은 파일의 기존 접근권한을 출력하고 접근권한을 변경하는 프로그램을 작성하시오

./hw2 777 test.txt

 

int x, a;

for (a = 0; a < 3; a++) {

    x = 0;

    switch (argv[1][a]) {

        case '7': x |= S_IRWXU; break;

        case '6': x |= (S_IRUSR | S_IWUSR); break;

        case '5': x |= (S_IRUSR | S_IXUSR); break;

        case '4': x |= S_IRUSR; break;

        case '3': x |= (S_IWUSR | S_IXUSR); break;

…………

}

if (a == 0) buf.st_mode |= x;

if (a == 1) buf.st_mode |= (x>>3);

if (a == 2) buf.st_mode |= (x>>6);

// 반드시 chmod를 실행해야 파일접근권한이 수정됨

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>

void print_permissions(struct stat buf);

int main(int argc, char* argv[]) {
    if (argc < 3) {
        printf("usage: hw2 permission_mode file_name\n");
        exit(1);
    }

    struct stat buf;

    stat(argv[2], &buf);

    print_permissions(buf);

    int x, a;
    for (a = 0; a < 3; a++) {
        switch (argv[1][a]) {
            case '7': 
                x |= S_IRWXU; 
                break;
            case '6': 
                x |= (S_IRUSR | S_IWUSR); 
                break;
            case '5': 
                x |= (S_IRUSR | S_IXUSR); 
                break;
            case '4': 
                x |= S_IRUSR; 
                break;
            case '3': 
                x |= (S_IWUSR | S_IXUSR); 
                break;
            case '2': 
                x |= S_IWUSR; 
                break;
            case '1': 
                x |= S_IXUSR; 
                break;
            case '0': 
                x = 0; 
                break;
            default: 
                printf("invalid mode\n"); 
                exit(1);
        }

        if (a == 0) { // 사용자 권한 설정
            buf.st_mode = (buf.st_mode & ~S_IRWXU) | x; 
        } 
        if (a == 1) { // 그룹 권한 설정
            buf.st_mode = (buf.st_mode & ~S_IRWXG) | (x >> 3); 
        } 
        if (a == 2) { // 기타 사용자 권한 설정
            buf.st_mode = (buf.st_mode & ~S_IRWXO) | (x >> 6); 
        }
    }

    chmod(argv[2], buf.st_mode); // 파일에 새로운 권한 적용
    printf("== after updated ==\n");
    print_permissions(buf);

    return 0;
}

void print_permissions(struct stat buf) {
    printf("permission: ");
    printf((buf.st_mode & S_IRUSR) ? "r" : "-");
    printf((buf.st_mode & S_IWUSR) ? "w" : "-");
    printf((buf.st_mode & S_IXUSR) ? "x" : "-");
    printf((buf.st_mode & S_IRGRP) ? "r" : "-");
    printf((buf.st_mode & S_IWGRP) ? "w" : "-");
    printf((buf.st_mode & S_IXGRP) ? "x" : "-");
    printf((buf.st_mode & S_IROTH) ? "r" : "-");
    printf((buf.st_mode & S_IWOTH) ? "w" : "-");
    printf((buf.st_mode & S_IXOTH) ? "x" : "-");
    printf("\n");
}

u, g, o에게 r, w, x 모두 부여

 

 

 

ex1. 명령행 인자로 받은 파일의 심볼릭 링크를 생성하고, 심볼릭 링크 파일의 내용과 원본 파일의 경로를 출력하는 프로그램을 작성하시오

./ex1 testdata

 

n = 0;

while (argv[1][n] != '.') {

    buf[n] = argv[1][n];

    n++;

}

buf[n] = '\0';

 

printf("buf: %s\n", buf);

sprintf(symname, "%s.sym", buf);

printf("symname: %s\n", symname);

 

symlink(argv[1], symname);

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

int main(int argc, char* argv[]) {
    if (argc == 1) {
        printf("usage: mysym filename\n");
        exit(1);
    }

    char buf[256];
    char symname[1024];
    int n;

    n = 0;
    while(argv[1][n] != '.') {
        buf[n] = argv[1][n];
        n++;
    }
    buf[n] = '\0';

    printf("buf: %s\n", buf);
    sprintf(symname, "%s.sym", buf); // sprintf() 함수는 문자열을 포맷팅하는 함수(symname에 문자열을 저장)
    printf("symname: %s\n", symname);

    symlink(argv[1], symname);

    n = readlink(symname, buf, sizeof(buf));
    if (n == -1) {
        perror("readlink");
        exit(1);
    }
    buf[n] = '\0';
    printf("%s: READLINK = %s\n", symname,  buf);

    realpath(symname, buf);
    printf("%s: REALPATH = %s\n", symname,  buf);

    return 0;
}

 

 

 

ex2. 현재 디렉터리에서 inode가 같은 파일을 검색해 inode를 출력하는 프로그램을 작성하시오

(하드 링크로 여러 개의 파일을 생성한 후 실행함)

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>

int main(void) {
    DIR* dp;
    struct dirent* dent;
    struct stat statbuf;
    int count, i, j, isSameInode;
    int ind[256], curInode;

    if ((dp = opendir(".")) == NULL) {
        perror("opendir");
        exit(1);
    }

    count = 0;
    while (dent = readdir(dp)) { // 디렉터리 내의 파일들을 하나씩 읽어옴
        lstat(dent->d_name, &statbuf);
        ind[count] = (int)statbuf.st_ino;
        count++;
    }
    closedir(dp);

    isSameInode = 0;
    for (i = 0; i < count; i++) {
        curInode = ind[i];
        for (j = 0; j < count; j++) {
            if (j != i && (curInode == ind[j]) && (ind[j] != -1)) {
                printf("same inode: %d\n", curInode);
                ind[j] = -1; // 이미 처리한 inode 번호는 -1로 표시하여 중복처리 방지
                isSameInode = 1; // 동일한 inode를 찾았음을 표시
            }
        }
    }
    if (!isSameInode) {
        printf("no same inode file\n");
    }

    return 0;
}

※ stat()이 아닌 lstat()을 써야 한다

하드링크 파일 2개: testdata2, testdata3
하드 링크 파일이 없는 경우

 

 

 

ex3. 현재 디렉터리에 어떤 파일의 하드 링크가 여러 개 있을 때 그 중에 한 파일만 남기고, 링크를 모두 끊는 프로그램을 작성하시오

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>

int main(void) {
    DIR* dp;
    struct dirent* dent;
    struct stat statbuf;

    if ((dp = opendir(".")) == NULL) {
        perror("opendir");
        exit(1);
    }

    while (dent = readdir(dp)) {
        stat(dent->d_name, &statbuf);
        if (((statbuf.st_mode & S_IFMT) == S_IFREG) && (statbuf.st_nlink > 1)) {
            unlink(dent->d_name);
        }
    }
    closedir(dp);

    return 0;
}

unlink() 함수: 연결을 끊은 경로명이 그 파일을 참조하는 마지막 링크라면 파일을 삭제

 

 

 

 

 

 

 

참고 및 출처: 시스템 프로그래밍 리눅스&유닉스(이종원)