๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
6. CS ๊ธฐ์ดˆ ๐Ÿ“š/Linux & Unix ๐Ÿง

[Linux/Unix][4-3] Inode ์ •๋ณด ์ถœ๋ ฅ

by lxvxxu 2025. 10. 21.
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>

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

    dp = opendir(".");

    while ((dent = readdir(dp))) {
        printf("Name : %s ", dent->d_name);
        printf("Inode : %d\n", (int)dent->d_ino);
    }

    closedir(dp);
}

 

 

 

 

 

์ข‹์•„! ์‚ฌ์ง„ ์† ์ฝ”๋“œ๋Š” ํ˜„์žฌ ๋””๋ ‰ํ„ฐ๋ฆฌ์˜ ํ•ญ๋ชฉ(ํŒŒ์ผ/ํด๋”)๋“ค์„ ์ฝ์–ด์„œ ๊ฐ ํ•ญ๋ชฉ์˜ ์ด๋ฆ„๊ณผ inode ๋ฒˆํ˜ธ๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ๊ฐ„๋‹จํ•œ C ํ”„๋กœ๊ทธ๋žจ์ด์•ผ. opendir(".")๋กœ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ์—ด๊ณ , readdir()๋กœ ํ•ญ๋ชฉ์„ ํ•˜๋‚˜์”ฉ ์ฝ์–ด ์˜ค๋ฉฐ, dirent ๊ตฌ์กฐ์ฒด์˜ d_name(์ด๋ฆ„)๊ณผ d_ino(inode ๋ฒˆํ˜ธ)๋ฅผ ์ถœ๋ ฅํ•ด.

์•„๋ž˜์— ์‚ฌ์ง„ ์† ์ฝ”๋“œ ์žฌ๊ตฌ์„ฑ๋ณธ๋™์ž‘ ์„ค๋ช…์—๋Ÿฌ ์ฒ˜๋ฆฌ/์‚ฌ์šฉ์„ฑ ๋ณด๊ฐ• ๋ฒ„์ „ ์ˆœ์„œ๋กœ ์ •๋ฆฌํ• ๊ฒŒ.


1) ์‚ฌ์ง„ ์† ์ฝ”๋“œ ์žฌ๊ตฌ์„ฑ๋ณธ

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>

// List directory entries and their inode numbers

int main(void) {
    // directory stream pointer
    DIR *dp;
    // directory entry pointer
    struct dirent *dent;

    // open current directory
    dp = opendir(".");

    // read entries until NULL
    while ((dent = readdir(dp))) {
        // print file/dir name, inode number
        printf("Name : %s", dent->d_name);
        printf("Inode : %d\n", (int) dent->d_ino);
    }

    closedir(dp);
    return 0;
}

โš ๏ธ ์œ„ ์ฝ”๋“œ๋Š” “๊ทธ๋ฆผ์— ๋ณด์ด๋Š” ๊ทธ๋Œ€๋กœ”์— ๊ฐ€๊น๊ฒŒ ์˜ฎ๊ธด ๊ฒƒ์ด๊ณ ,
์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ(์˜ˆ: opendir ์‹คํŒจ, readdir ๋„์ค‘ ์˜ค๋ฅ˜, closedir ์‹คํŒจ) ๊ฐ€ ์—†๊ณ ,
inode ํ˜•์‹ ์ถœ๋ ฅ๋„ ์‹œ์Šคํ…œ์— ๋”ฐ๋ผ ํ˜•๋ณ€ํ™˜์ด ๋ถ€์ •ํ™•ํ•  ์ˆ˜ ์žˆ์–ด(์•„๋ž˜ ๋ณด๊ฐ• ๋ฒ„์ „์—์„œ ๊ณ ์นจ).


2) ์ฝ”๋“œ๊ฐ€ ํ•˜๋Š” ์ผ(์ƒ์„ธ)

  • opendir(".")
    ํ˜„์žฌ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ๋””๋ ‰ํ„ฐ๋ฆฌ ์ŠคํŠธ๋ฆผ์œผ๋กœ ์—ฐ๋‹ค. ์‹คํŒจ ์‹œ NULL์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  • readdir(dp)
    ๋””๋ ‰ํ„ฐ๋ฆฌ ์ŠคํŠธ๋ฆผ์—์„œ ๋‹ค์Œ ๋””๋ ‰ํ„ฐ๋ฆฌ ์—”ํŠธ๋ฆฌ๋ฅผ ํ•˜๋‚˜ ์ฝ๋Š”๋‹ค.
    ์„ฑ๊ณต ์‹œ struct dirent*๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , ๋์ด๋‚˜ ์˜ค๋ฅ˜ ์‹œ NULL์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
    (๋๊ณผ ์˜ค๋ฅ˜๋ฅผ ๊ตฌ๋ถ„ํ•˜๋ ค๋ฉด errno๋ฅผ ํ™•์ธํ•ด์•ผ ํ•œ๋‹ค.)
  • dent->d_name
    ํ•ญ๋ชฉ ์ด๋ฆ„(์˜ˆ: ".", "..", "a.txt", "subdir" …).
  • dent->d_ino
    ๊ทธ ํ•ญ๋ชฉ์˜ inode ๋ฒˆํ˜ธ. ํŒŒ์ผ ์‹œ์Šคํ…œ์—์„œ ํŒŒ์ผ/๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ์‹๋ณ„ํ•˜๋Š” ํ•ต์‹ฌ ํ‚ค.
  • closedir(dp)
    ๋””๋ ‰ํ„ฐ๋ฆฌ ์ŠคํŠธ๋ฆผ์„ ๋‹ซ๋Š”๋‹ค. ์‹คํŒจ ์‹œ -1์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

3) ๋ณด๊ฐ• ๋ฒ„์ „(์—๋Ÿฌ ์ฒ˜๋ฆฌ + ์ถœ๋ ฅ ํ˜•์‹ ์•ˆ์ „ + ๊ฒฝ๋กœ ์ธ์ž ์ง€์›)

๊ฐœ์„ ์ 

  • opendir ์‹คํŒจ ์‹œ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€์™€ ์ข…๋ฃŒ.
  • readdir ๋ฃจํ”„ ์ข…๋ฃŒ ํ›„ errno๋กœ ์˜ค๋ฅ˜/์ •์ƒ ์ข…๋ฃŒ ๊ตฌ๋ถ„.
  • closedir ๋ฐ˜ํ™˜๊ฐ’ ํ™•์ธ.
  • ๊ฒฝ๋กœ ์ธ์ž๋ฅผ ๋ฐ›์•„ ์›ํ•˜๋Š” ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ๋‚˜์—ด ๊ฐ€๋Šฅ.
  • ino_t ๋Š” ํ”Œ๋žซํผ๋งˆ๋‹ค ํฌ๊ธฐ๊ฐ€ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์•ˆ์ „ํ•œ ํ˜•์‹ ์ง€์ •์ž ์‚ฌ์šฉ(uintmax_t๋กœ ์Šน๊ฒฉ + %ju).
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <errno.h>
#include <inttypes.h>  // for uintmax_t and %ju
#include <string.h>

int main(int argc, char *argv[]) {
    const char *path = (argc >= 2) ? argv[1] : ".";

    DIR *dp = opendir(path);
    if (dp == NULL) {
        fprintf(stderr, "opendir failed for '%s': %s\n", path, strerror(errno));
        return EXIT_FAILURE;
    }

    errno = 0; // to distinguish end-of-dir vs error
    struct dirent *dent;
    while ((dent = readdir(dp)) != NULL) {
        // inode (ino_t) -> uintmax_t ๋กœ ์Šน๊ฒฉํ•ด ์•ˆ์ „ํ•˜๊ฒŒ ์ถœ๋ ฅ
        uintmax_t ino = (uintmax_t) dent->d_ino;
        printf("Name : %s\n", dent->d_name);
        printf("Inode: %ju\n", ino);
    }

    if (errno != 0) { // readdir๊ฐ€ NULL์„ ๋ฐ˜ํ™˜ํ–ˆ๋Š”๋ฐ errno๊ฐ€ 0์ด ์•„๋‹ˆ๋ฉด ์˜ค๋ฅ˜
        fprintf(stderr, "readdir error on '%s': %s\n", path, strerror(errno));
        closedir(dp); // ์‹œ๋„๋Š” ํ•ด๋ณธ๋‹ค
        return EXIT_FAILURE;
    }

    if (closedir(dp) == -1) {
        fprintf(stderr, "closedir failed for '%s': %s\n", path, strerror(errno));
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

 

์™œ ์ด๋ ‡๊ฒŒ ๊ณ ์ณค๋‚˜?

  • opendir/readdir/closedir ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ: ์‹ค๋ฌด/๊ณผ์ œ์—์„œ ํ•„์ˆ˜.
  • ํ˜•์‹ ์ง€์ •์ž: ino_t๋Š” ์‹œ์Šคํ…œ๋งˆ๋‹ค unsigned long/unsigned long long ๋“ฑ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์–ด %d๋Š” ์œ„ํ—˜.
    ๊ฐ€์žฅ ๋ณดํŽธ์ ์œผ๋กœ uintmax_t๋กœ ์บ์ŠคํŒ… + %ju ๊ฐ€ ์•ˆ์ „ํ•˜๋‹ค.
  • ๊ฒฝ๋กœ ์ธ์ž ์ง€์›: ./prog /etc ์ฒ˜๋Ÿผ ์›ํ•˜๋Š” ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ๋ฐ”๋กœ ์กฐํšŒ ๊ฐ€๋Šฅ.

4) ์ปดํŒŒ์ผ & ์‹คํ–‰ ๋ฐฉ๋ฒ•

# ๊ถŒ์žฅ(๊ฒฝ๊ณ +์ตœ์ ํ™”)
gcc -Wall -Wextra -O2 list_inodes.c -o list_inodes

# ์‹คํ–‰: ํ˜„์žฌ ๋””๋ ‰ํ„ฐ๋ฆฌ
./list_inodes

# ์‹คํ–‰: ๋‹ค๋ฅธ ๋””๋ ‰ํ„ฐ๋ฆฌ
./list_inodes /etc

 

์ฐธ๊ณ  ์˜ต์…˜

  • -Wall -Wextra : ์ผ๋ฐ˜/์ถ”๊ฐ€ ๊ฒฝ๊ณ  ํ™œ์„ฑํ™” (์ž ์žฌ ๋ฒ„๊ทธ ์กฐ๊ธฐ ๋ฐœ๊ฒฌ)
  • -O2 : ๋ณดํŽธ์ ์ธ ์ตœ์ ํ™”
  • -g : ๋””๋ฒ„๊น… ์ •๋ณด๋ฅผ ํฌํ•จํ•˜๋ ค๋ฉด ์ถ”๊ฐ€

5) ์ถœ๋ ฅ ์˜ˆ์‹œ(ํ˜•์‹)

 

Name : .
Inode: 131073
Name : ..
Inode: 131072
Name : hw-04.c
Inode: 263201
Name : subdir
Inode: 263205
...

 


 

์•„๋ž˜๋Š” ๋„ˆ๊ฐ€ ์š”์ฒญํ•œ “./.. ๊ฑด๋„ˆ๋›ฐ๊ธฐ + ํŒŒ์ผ ์ข…๋ฅ˜(๋””๋ ‰ํ„ฐ๋ฆฌ/์ผ๋ฐ˜ ํŒŒ์ผ) ํ‘œ์‹œ + ๊ถŒํ•œ·ํฌ๊ธฐ๊นŒ์ง€ ์ถœ๋ ฅ” ๋ฒ„์ „์ด์•ผ.
์‹ค๋ฌดํ˜• ๊ณผ์ œ ์ˆ˜์ค€์œผ๋กœ ๊ฐœ์„ ํ–ˆ๊ณ , ๊ฐ ๋ถ€๋ถ„์— ์ฃผ์„๊ณผ ์„ค๋ช…๋„ ๋ง๋ถ™์˜€์–ด.


โœ… ์™„์„ฑ ์ฝ”๋“œ: list_inodes_detailed.c

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

// Function to print permission bits in rwx format
void print_permissions(mode_t mode) {
    printf("%c", (mode & S_IRUSR) ? 'r' : '-');
    printf("%c", (mode & S_IWUSR) ? 'w' : '-');
    printf("%c", (mode & S_IXUSR) ? 'x' : '-');
    printf("%c", (mode & S_IRGRP) ? 'r' : '-');
    printf("%c", (mode & S_IWGRP) ? 'w' : '-');
    printf("%c", (mode & S_IXGRP) ? 'x' : '-');
    printf("%c", (mode & S_IROTH) ? 'r' : '-');
    printf("%c", (mode & S_IWOTH) ? 'w' : '-');
    printf("%c", (mode & S_IXOTH) ? 'x' : '-');
}

int main(int argc, char *argv[]) {
    const char *path = (argc >= 2) ? argv[1] : ".";

    DIR *dp = opendir(path);
    if (!dp) {
        fprintf(stderr, "โŒ opendir('%s') ์‹คํŒจ: %s\n", path, strerror(errno));
        return EXIT_FAILURE;
    }

    printf("\n๐Ÿ“‚ Directory: %s\n", path);
    printf("-------------------------------------------------------------\n");
    printf("%-25s %-10s %-8s %-12s %-10s\n", "Name", "Inode", "Type", "Permissions", "Size");
    printf("-------------------------------------------------------------\n");

    errno = 0;
    struct dirent *dent;
    struct stat st;
    char fullpath[1024];

    while ((dent = readdir(dp)) != NULL) {
        // Skip current (.) and parent (..)
        if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0)
            continue;

        snprintf(fullpath, sizeof(fullpath), "%s/%s", path, dent->d_name);

        if (lstat(fullpath, &st) == -1) {
            fprintf(stderr, "โš ๏ธ  lstat('%s') ์˜ค๋ฅ˜: %s\n", fullpath, strerror(errno));
            continue;
        }

        // Determine file type
        char type[16];
        if (S_ISDIR(st.st_mode))
            strcpy(type, "DIR");
        else if (S_ISREG(st.st_mode))
            strcpy(type, "FILE");
        else if (S_ISLNK(st.st_mode))
            strcpy(type, "LINK");
        else
            strcpy(type, "OTHER");

        printf("%-25s %-10ju %-8s ", dent->d_name, (uintmax_t) dent->d_ino, type);
        print_permissions(st.st_mode);
        printf(" %-10ld\n", (long) st.st_size);
    }

    if (errno != 0) {
        fprintf(stderr, "โŒ readdir() ์˜ค๋ฅ˜: %s\n", strerror(errno));
        closedir(dp);
        return EXIT_FAILURE;
    }

    if (closedir(dp) == -1) {
        fprintf(stderr, "โŒ closedir('%s') ์‹คํŒจ: %s\n", path, strerror(errno));
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

โš™๏ธ ์ปดํŒŒ์ผ & ์‹คํ–‰

gcc -Wall -Wextra -O2 list_inodes_detailed.c -o list_inodes_detailed
./list_inodes_detailed

ํ˜น์€ ํŠน์ • ๋””๋ ‰ํ„ฐ๋ฆฌ ์ง€์ •:

./list_inodes_detailed /etc

 

๐Ÿ“Š ์‹คํ–‰ ์˜ˆ์‹œ ์ถœ๋ ฅ

 
๐Ÿ“‚ Directory: .
-------------------------------------------------------------
Name                      Inode      Type     Permissions   Size      
-------------------------------------------------------------
list_inodes_detailed.c    263201     FILE     rw-r--r--     2496      
hw-04                     263205     DIR      rwxr-xr-x     4096      
readme.md                 263210     FILE     rw-r--r--     1024

๐Ÿ” ์ฝ”๋“œ ์„ค๋ช… ์š”์•ฝ

๊ตฌ๋ถ„์„ค๋ช…
opendir() ์ง€์ •ํ•œ ๊ฒฝ๋กœ์˜ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ์—ฐ๋‹ค
readdir() ๋””๋ ‰ํ„ฐ๋ฆฌ์˜ ๊ฐ ์—”ํŠธ๋ฆฌ๋ฅผ ์ฐจ๋ก€๋กœ ์ฝ๋Š”๋‹ค
lstat() ํŒŒ์ผ์˜ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ(ํฌ๊ธฐ, ๊ถŒํ•œ, ์œ ํ˜• ๋“ฑ)๋ฅผ ์–ป๋Š”๋‹ค
S_ISDIR / S_ISREG ํŒŒ์ผ ํƒ€์ž… ๋งคํฌ๋กœ (๋””๋ ‰ํ„ฐ๋ฆฌ / ์ผ๋ฐ˜ ํŒŒ์ผ ๊ตฌ๋ถ„)
st_mode ๊ถŒํ•œ ๋น„ํŠธ ๋ฐ ํŒŒ์ผ ์œ ํ˜• ์ €์žฅ
st_size ํŒŒ์ผ ํฌ๊ธฐ(byte)
d_ino inode ๋ฒˆํ˜ธ
print_permissions() rwx ํ˜•์‹์œผ๋กœ ๊ถŒํ•œ ๋น„ํŠธ ์ถœ๋ ฅ

๐Ÿ’ก ์ฐธ๊ณ : ํ™•์žฅ ์•„์ด๋””์–ด

  • ์ƒ‰์ƒ ์ถœ๋ ฅ (๋””๋ ‰ํ„ฐ๋ฆฌ=ํŒŒ๋ž‘, ์‹คํ–‰ํŒŒ์ผ=์ดˆ๋ก)
  • ํŒŒ์ผ ์ˆ˜์ • ์‹œ๊ฐ„ ํ‘œ์‹œ (st_mtime ์ด์šฉ)
  • ์ˆจ๊น€ํŒŒ์ผ(.์œผ๋กœ ์‹œ์ž‘) ํ‘œ์‹œ/์ œ์™ธ ์˜ต์…˜
  • ์žฌ๊ท€ ํƒ์ƒ‰ ๊ธฐ๋Šฅ (nftw() ์‚ฌ์šฉ)