Develop

[c] 파일(File)의 연결과 연결 해제 (link, unlink, chown)

by hooni posted Apr 23, 2013
?

단축키

Prev이전 문서

Next다음 문서

ESC닫기

크게 작게 위로 아래로 댓글로 가기 인쇄
파일의 연결과 연결해제
파일을 연결(link)에는 "심볼릭 링크" 와 "하드 링크" 의 2가지가 존재한다. 하드링크는 연결을 원하는 원본파일의 inode 를 가지고 파일을 직접 만들지만 (파일복사), linke 는 inode 를 가지고 파일을 만들지 않고, 단지 파일만을 참조한다.
심볼링 링크의 경우 서로 다른 파일시스템 사이를 연결할수 있지만(파일을 단지 참조하는 것이므로), 하드 링크의 경우 다른 파일시스템 사이를 연결할수는 없다.
그 이유는 하드링크가 inode 를 가지고 파일을 연결한다고 했는데, 다른 파일시스템 의 경우 inode 가 중복될수가 있기 때문(즉 유일한 파일 이라는걸 확인할수 없음)이다.
그러므로 서로다른 파일시스템(파티션) 사이에 파일 복사를 원한다면, 별도의 함수를 만들어서 써야 한다.
이러한 파일시스템을 넘나드는 파일의 연결을 신경써야 한다면, 파일을 직접 read 해서 write 하는 함수를 만들어서 사용해야 할것이다.
파일의 링크를 해제하기 위해서는 unlink(2) 를 사용하면 된다.
유닉스 쉘상에서도 이러한 파일 링크를 위한 "ln" 이라는 시스템 명령어가 존재하는데, "-s" 옵션을 사용하면 심볼릭 링크 "-d" 를 사용하면 하드링크를 시키게 된다.

하드링크와 심볼링 링크
우선 심볼릭 링크 쪽을 보면 파일시스템이 다른데도 별문제 없이 링크가 됨을 알수 있다. 
그러나 서로다른 파일시스템(장치)간에 하드링크를 하려고 할경우 에러가 나는걸 볼수 있을것이다.
위에서 말했듯이 inode 를 가져가기 때문이다.
위의 예제에서 "-d" 옵션을 이용한 하드 링크에서 에러가 발생한 이유는 서로다른 장치에 있는 파일을 하드링크 시키려고 했기 때문이다. 
아래는 간단한 예제이다. 

예제: link.c
#include <unistd.h>
#include <string.h>
#include <stdio.h>
 
int main(int argc, char **argv)
{
    int opt;
 
    if ( argc != 4)
    {
        printf ("Usage: ./link [s|h] [원본파일] [복사파일]\n");
        return -1;
    }
 
    if(access(argv[2], F_OK) != 0)
    {
        printf("원본파일이 없습니다\n");
        return -1;
    }
 
    if(access(argv[3], F_OK) == 0)
    {
        printf("이미 파일이 존재합니다\n");
        return -1;
    }
 
    while((opt = getopt(argc, argv, "sh")) != -1)
    {
        switch(opt)
        {
            case 's':
                printf("심볼릭링크\n");
                symlink(argv[2], argv[3]);
                break;
 
            case 'h':
                printf("하드링크\n");
                link(argv[2], argv[3]);
                break;
        }
    }
}

예상과 달리 --; 썩 그럴듯하게 돌아갈 것이다.
명령행 옵션의 처리를 위해서 getopt 를 사용했는데 getopt 에 대한내용은 getopt를 이용한 프로그램 인자처리를 참조하기 바란다.
"-s" 옵션을 주면 symlink(2)를 이용해서 심볼링 링크를 만들고, 
"-h" 옵션을 주면 link(2)를 이용해서 하드링크를 만든다. 
"-d" 옵션을 주면 해당 파일의 연결을 해제한다. 

파일권한및 소유주/그룹 변경 파일의 실행권한은 "유저", "그룹", "그밖의 유저(other)" 에 대한 권한을 각기 지정해 줄수 있다.

[root@localhost test]# ls -al
-rwxr-xr-x    1 root     root        13953  1월 24  2002 access
-rw-r--r--    1 root     yundream      180  1월 24  2002 access.c
-rw-r--r--    1 root     root          708  1월 24  2002 access.c.html
-rwxr-xr-x    1 root     root        25250  7월 31 21:57 accumulate
-rw-r--r--    1 root     root          346  7월 31 21:57 accumulate.cc
-rwxr-xr-x    1 root     root        13976  8월 17 16:40 add
-rw-r--r--    1 root     root          101  8월 17 16:40 add.c
-rwxr-xr-x    1 root     root        25333  7월 31 22:37 adjacent_difference
-rw-r--r--    1 root     root          389  7월 31 22:37 adjacent_difference.cc
-rwxr-xr-x    1 root     root        14104  8월 18 14:29 alarm
-rw-r--r--    1 root     root          230  8월 18 14:29 alarm.c
-rwxr-xr-x    1 root     root        13791  1월 14  2002 argc
-rw-r--r--    1 root     root          214  1월 14  2002 argc.c
-rw-r--r--    1 root     root          777  1월 14  2002 argc.c.html
-rwxr-xr-x    1 root     root        15191 12월 19  2001 array
-rw-r--r--    1 root     root          742 12월 19  2001 array.c
-rwxr-xr-x    1 root     root        13678  9월 20 00:43 asc
-rw-r--r--    1 root     root           38  9월 20 00:42 asc.c

위는 "ls -al" 의 결과 이다. ls -al 을 사용할경우 각 파일권한, 파일의 소유자, 소유그룹등에 대한 상세한 정보를 볼수가 있다.
ls -al 의 결과 가장 앞의 10자리가 파일의 권한을 나타낸다. 이 10자리중 가장 앞자리는 파일의 타입(일반파일, 디렉토리, FIFO, 소켓)을 명시하고, 나머지 9자리가 파일의 권한을 나타내는데, 3자리씩 끊어서 각각 "소유자", "그룹", "Other" 에 대한 권한을 명시한다. 
"w"는 쓰기권한, "r"은 읽기권한, "x"는 쓰기권한, "-" 는 권한없음을 나타낸다. 
그러므로 위의 access 파일은 소유자인 "root"유저에게 대하여 "rwx"(읽기, 쓰기, 실행) 권한이 부여되어 있고, "root"그룹에 포함된 유저와 그밖의 유저에 대해"r-x"(읽기, 실행) 권한이 부여된다.
access.c 파일을 보면 "root" 사용자에게 "rw-"(일기, 쓰기), yundream 그룹에 포함된 유저와, 그밖의 유저에게 대하여서는 단지 "r--"(읽기) 권한만 부여되어 있음을 알수 있다.

  소유자   그룹     Other
 +-+-+-+  +-+-+-+  +-+-+-+
 |R|W|X|  |R|W|X|  |R|W|X|
 +-+-+-+  +-+-+-+  +-+-+-+
  4 2 1    4 2 1    4 2 1 

우리는 쉘상에서 파일권한변경을 위해 아래와 같은 명령을 사용한다.
[root@localhost test]# chmod 755 test.sh

소유주와 그룹의 변경을 위해서는 아래와 같은 명령을 사용한다.
[root@localhost test]# chown yundream.cvs test.sh

Linux 상에서는 chown 을 이용하여 파일에 대한 소유주와 그룹을 동시에 변경할수 있지만 다른 Unix 에서는 그룹변경을 위해서 "chgrp"를 사용해야만 할것이다.

C 에서는 파일권한 변경을 위해서 chmod(2), 소유주/그룹 변경을 위해서 chown(2) 함수를 제공한다. 

예제 : mychown
#include <sys/types.h>
#include <pwd.h>
#include <unistd.h>
 
int main(int argc, char **argv)
{
    struct passwd *my_pass;
 
    my_pass = getpwnam(argv[1]);
    if (my_pass == NULL)
    {
        printf("%s 유저가 없음\n", argv[1]);
        exit(0);
    }
    printf("%s : %d\n", argv[1], my_pass->pw_uid, my_pass->pw_gid);
    if (chown(argv[2], my_pass->pw_uid, my_pass->pw_gid) !=0)
    {
        perror("error : ");
    }
}

프로그램이 하는 일은 간단하다.
첫번째 아규먼트는 그룹권한을 변경할 유저의 ID 이고, 두번째 아규먼트는 권한을 변경할 파일 이름이다.
프로그램을 실행하면 해당파일의 소유주와 소유그룹이 변경되고, 파일권한이 664 로 변경될것이다.