9 파일 시스템 인터페이스

이 장은 파일들을 다루기 위한 GNU C 라이브러리 함수들을 설명하고 있다. 7장 [I/O on Streams] 에서 설명된 입/출력 함수들과는 달리, 이 함수들은 파일안의 내용보다는 파일 그 차제를 다루는 것에 대한 함수들이다.

이 절에서 설명된 것들은 디렉토리들을 조사하고, 갱신하기 위한 함수들과 파일들을 삭제하거나 재 명명하기 위한 함수들과, 엑세스 허용과, 갱신시간과 같은 파일 속성들을 조사하고, 설정하기 위한 함수들이다.


9. 1 작업 디렉토리

각 프로세스는 한 디렉토리와 연관되어 있고, 그것을 현재 작업 디렉토리라 부르거나, 간단하게 작업 디렉토리라 부른다. 디렉토리 이름은 파일이름과 같은 방법으로 사용된다. ( 6. 2. 2절 [File Name Resolution] 참조 )

당신이 로그인하고 새로운 세션(session)을 시작할 때, 당신의 작업 디렉토리는 시스템 유저 데이터베이스 안에 당신의 로그인 계정과 연관된 홈 디렉토리(home directory)로 초기 설정된다. 당신은 getpwuid 나 getpwnam 을 사용해서 사용자의 홈 디렉토리를 찾을 수 있다; 25. 12절[User Database] 참조.

 
--- 역자주 : 세션(session) : 사용자가 컴퓨터와의 연결이 시작된 순간부터 단절되는 순간까지를 하나의 논리적인 단위로 구분해놓은 것

사용자는 cd와 같은 쉘 명령어를 사용해서 작업 디렉토리를 변경할 수 있다. 이 절에서 설명하고 있는 함수들은 이들 명령에 의해 사용되고, 또한 작업 디렉토리를 조사하고, 변경하려는 다른 프로그램들에 의해 사용된다. 이들 함수들의 프로토타입은 헤더파일 'unistd. h'에 선언되어 있다.

함수 : char * getcwd (char *buffer, size_t size)

getcwd 함수는 현재의 작업 디렉토리를 나타내는 파일 이름을, 당신이 제공한 문자 배열 버퍼에 그것을 저장하여 리턴한다. size인수는 버퍼의 할당 크기이다.
이 함수에서 GNU 라이브러리는 당신이 buffer 인수에 널 포인터를 지정하는 것을 허용한다. 그러면 getcwd는 malloc( 3. 3절 [Unconstrained Allocation] )을 사용해서 자동적으로 버퍼를 할당한다. 만일 그 size가 0보다 크다면 버퍼는 그 크기로 할당되고 그렇지 않다면 버퍼는 결과를 저장하기에 필요한 만큼의 크기로 할당된다. 리턴 값은 성공하면 버퍼이고, 실패하면 널 포인터이다.
다음의 errno는 이 함수에서 정의하고 있는 에러 상황이다.

    EINVAL : size인수가 0인데 buffer가 널 포인터가 아니다.

    ERANGE

    size인수가 작업 디렉토리 이름의 길이보다 작다. 당신은 배열을 더 크게 할당하고 다시 시도하라.

    EACCES : 읽기 요청이나, 파일이름의 구성요소 찾기가 거부되었다.

이곳에 getcwd의 표준동작만을 사용한 GNU의 getcwd (NULL, 0)의 동작을 보여주는 예가 있다.

char *gnu_getcwd ()
{
int size = 100;
char *buffer = (char *) xmalloc (size);
while (1) {
char *value = getcwd (buffer, size);
if (value != 0)
return buffer;
size *= 2;
free (buffer);
buffer = (char *) xmalloc (size);
}
}
/* 다 아시겠지만. . . 잠시 설명을 합죠~ xmalloc을 이용해서 100바이트 만큼의 버퍼를 할당한 다음. . .
while 루프를 돌리네요. while루프의 조건을 1로 해놓고 루프안의 조건에 따라서 루프를 벗어나게 되는데. . . getcwd함수를 이용해서 이름을 얻었는데, 그 크기가 0이 아니면 버퍼를 리턴하고 루프를 벗어나고 그렇지 않으면 size에 2를 곱해서 (즉. . 버퍼의 크기를 늘리기 위해 ) 원래의 버퍼는 해제하고 다시 큰 크기의 버퍼를 할당받아서 다시 루프의 처음으로 돌아가고. . 끝. . */
xmalloc에 대한 정보는 3. 3. 3절 [Malloc Examples]를 참조하라. xmalloc은 라이브러리 함수가 아니라 대부분의 GNU 소프트웨어에서 사용되는 사용자정의 이름이다.

함수 : char * getwd (char *buffer)

이것은 getcwd와 유사하다. GNU 라이브러리는 BSD와의 호환성을 위해 getwd를 제공하고 있다. 버퍼는 적어도 PATH_MAX 바이트 길이의 배열을 가리키는 포인터가 된다.

함수 : int chdir (const char *filename)

이 함수는 filename으로 프로세스의 작업 디렉토리를 설정하기 위해 사용된다. 보통 성공하면 리턴 값은 0이다. 만일 -1이 리턴되면 에러가 발생했음을 나타낸다. 이 함수에서 정의하고 있는 에러상황 errno는 대부분 파일 이름의 문법적 에러이고( 6. 2. 3절 [File Name Errors] 참조) ENOTDIR은 파일 이름이 디렉토리가 아님을 나타낸다.


9. 2 디렉토리 억세스하기

이 절에서 설명하고 있는 것들은 한 디렉토리 파일의 내용을 읽는데 쓰여 진다. 이것은 당신의 프로그램이 아마도 메뉴의 일부분으로써, 디렉토리 안의 모든 파일들의 리스트를 원할 때 유용하다. opendir 함수는 디렉토리 엔트리들(entries)을 그 요소로 갖고 있는 디렉토리 스트림을 개방한다. readdir는 struct dirent objects로서 표현된 그 엔트리들을 디렉토리 스트림에서 얻기 위하여 사용한다. 각 엔트리를 위한 파일의 이름은 이 구조체의 d_name 안에 저장되어있다. 7장 [I/O on Streams] 에 설명된, 원래의 파일들을 위한 스트림 도구들과 이곳에 있는 것들과는 유사하다.

 

9. 2. 1 디렉토리 엔트리의 형식

이 절은 당신이 디렉토리 스트림으로부터 획득한, 단일 디렉토리 엔트리에서 무엇을 발견할 수 있는지를 설명하고 있다. 모든 심볼들은 헤더파일'dirent. h'에 선언되어 있다.

 데이터타입 : struct dirent

이것은 디렉토리 엔트리들에 대한 리턴 정보로서 사용되는 구조체 타입이다. 그것은 다음과 같은 필드들은 포함하고 있다.

char *d_name

이것은 널 문자로 끝나는 파일이름 요소이다. 이것은 모든 POSIX 시스템 상에서 당신이 셀 수 있는 유일한 필드이다.

ino_t d_fileno

이것은 파일 시리 얼 넘버이다. BSD와의 호환성을 위해서, 당신은 d-ino로서 이 멤버를 대치할 수 있다.

size_t d_namlen

이것은 널 종료 문자가 포함되지 않은, 파일 이름의 길이이다. 이 구조체는 앞으로 부가적인 멤버들을 포함할 것이다. 파일이 다중의 이름들을 가질 때, 각각의 이름들은 자신의 디렉토리 엔트리를 갖는다. 단일 파일에 속한 디렉토리 엔트리들을 가리키는 유일한 방법은 d_fileno 필드에 동일한 값을 줌으로써 할 수 있다. 크기, 갱신 시간 과 같은 파일 속성과, 파일 그 자체의 일부분과 같은 것은 어느 특별한 디렉토리 엔트리가 아니다. 9. 8절 [File Attributes] 참조.

 

9. 2. 2 디렉토리 스트림 개방하기

이 절은 디렉토리 스트림을 어떻게 개방하는지 설명하고 있다. 모든 심볼들은 헤더파일 'dirent. h'에 선언되어 있다.

데이터타입 : DIR

DIR 데이터타입은 디렉토리 스트림을 나타낸다. 당신은 struct dirent 나 DIR 데이터타입들로 objects들을 할당받을 수 없다. 대신에 당신은 다음에 있는 함수들을 사용함으로 인해서 리턴된 포인터를 사용해서 이들 objects를 참조할 수 있다.

함수 : DIR * opendir (const char *dirname)

opendir 함수는 파일 이름이 dirname인 디렉토리를 읽기 위해서 디렉토리 스트림을 개방하고 리턴한다. 그 스트림은 DIR * 타입을 갖는다. 만일 성공하지 못하면 opendir는 널 포인터를 리턴한다. 보통 쉽게 일어나는 파일 이름 문법 에러들에 더하여( 6. 2. 3 [File Nmae Errors] 참조),
다음의 errno는 이 함수에서 정의하고 있는 에러 상황이다.

    EACCES : dirname의 이름을 가진 디렉토리를 읽기 위한 요청이 거부되었다.

    EMFILE : 그 프로세스가 너무 많은 파일들을 개방했다.

    ENFILE

    디렉토리를 포함하고 있는 전체 시스템이나, 아마도 파일 시스템이 그 순간에 더 이상 파일을 개방하는 것은 지원하지 않는다. ( 이 문제는 GNU시스템에서는 발생할 수 없다.

DIR 타입은 파일 기술자와, 그리고 open 함수에서 사용되는 opendir 함수에서 사용되어진다. 8장 [Low-Level I/O] 참조. 디렉토리 스트림들과 포함된 파일 기술자들은 exec에서 폐쇄된다. 23.5절 [Executing a File] 참조 )

 

9. 2. 3 디렉토리 스트림 읽고 닫기

이 절은 디렉토리 스트림으로부터 디렉토리 엔트리들을 어떻게 읽고, 그렇게 한 후 그 스트림을 어떻게 닫을 것인지를 설명하고 있다. 모든 심볼들은 헤더파일 'dirent. h'에 선언되어 있다.

함수 : struct dirent * readdir (DIR *dirstream)

dl 함수는 디렉토리로부터 다음 엔트리를 읽는다. 보통 리턴 값은 파일에 대한 정보를 갖고 있는 구조체의 포인터이다. 이 구조체는 정적으로 할당되고 그후에 일어나는 호출에 의해서 갱신되어질 수 있다.
 
이식성 노트 : 어떤 시스템에서는, readdir는 `. '과 `. . '가 어느 디렉토리에서 유용한 파일이름 일지라도, 그것들을 위한 엔트리들을 리턴하지 않을 것이다. 6. 2. 2 [File Name Resolution] 참조
만일 그 디렉토리 안에 더 이상 엔트리가 없거나, 에러가 검출되면, readdir은 널 포인터를 리턴한다.
다음의 errno는 이 함수에서 정의한 에러 상황이다.
EBADF : dirstream인수가 유용하지 않다.

함수 : int closedir (DIR *dirstream)

이 함수는 디렉토리 스트림 dirstream을 폐쇄한다. 성공하면 0을 리턴하고 실패하면 -1을 리턴한다.
다음의 errno는 이 함수에서 정의하고 있는 에러상황이다.
    EBADF : dirstream인수가 유용하지 않다.

 

9. 2. 4 디렉토리의 파일을 리스트 하는 간단한 프로그램

이곳에 현재 작업 디렉토리의 파일들의 이름을 출력하는 간단한 프로그램이 있다.

#include <stddef. h>
#include <stdio. h>
#include <sys/types. h>
#include <dirent. h>
int main (void)
{
DIR *dp;
struct dirent *ep; /* 현재의 디렉토리를 개방해서 dp에 넣어라!!! */
dp = opendir (". /");
/* 만일 개방이 됐다면 dp의 엔트리를 읽어서 ep에 넣고 그 구조체에서 d_name멤버를 출력하라. */
if (dp != NULL) {
while (ep = readdir (dp))
puts (ep->d_name);
(void) closedir (dp);
}
/* 개방이 안됐다면 에러 메시지 출력. . . */
else
puts ("Couldn't open the directory. ");
return 0;
}

디렉토리 안에 나타나는 파일들의 순서는 불규칙적이다. 이것보다 더 유용한 프로그램은 그들을 출력하기 전에 엔트리들을 정렬(아마도 알파벳 순서로. . )하는 것이다; 15. 3절 [Array Sort Function] 참조.

 

9. 2. 5 디렉토리 스트림의 랜덤 억세스

이 절은 이미 개방된 디렉토리 스트림으로부터 읽었던 한 부분을 어떻게 다시 읽을 수 있는지를 설명하고 있다. 모든 심볼들은 헤더파일 'dirent. h'에 선언되어 있다.

함수 : void rewinddir (DIR *dirstream)

rewinddir함수는 디렉토리 스트림 dirstream을 재 설정하는데 사용되어지기 때문에 만일 당신이 readdir을 호출하면 그것은 다시 디렉토리의 첫 번째 엔트리에 대한 정보를 리턴한다. 이 함수는 또한 opendir로 개방된 후 디렉토리 안의 파일들이 더해지거나, 제거된 적이 있는지에 대한 것도 지적한다. ( 이들 파일들을 위한 엔트리들은 당신이 마지막으로 호출했던 opendir이나 rewinddir 이후에 더해지거나 제거된 것이라면 readdir을 통해 리턴될 수도, 리턴되지 않을 수도 있다.

함수 : off_t telldir (DIR *dirstream)

telldir 함수는 디렉토리 스트림 dirstream의 파일 위치를 리턴한다. 당신은 그 위치에 디렉토리 스트림을 저장하기 위한 함수 seekdir에 이 값을 사용할 수 있다.

함수 : seekdir (DIR *dirstream, off_t pos)

seekdir함수는 pos로 디렉토리 스트림 dirstream의 파일 위치를 설정한다. 그 값 pos는 이 특별한 스트림 상에서 미리 telldir를 호출한 것의 결과이어야 한다; 디렉토리를 폐쇄하고, 다시 열기는 telldir에 의해 리턴된 값들을 무효로 만들 수 있다.


9. 3 하드 링크

POSIX 시스템에서는, 한 개의 파일이 동시에 많은 다른 이름을 소유할 수 있다. 그 이름들 모두는 동등하게 실제로 존재하고, 그들중 어느 것도 다른 것들을 취할 수 있다.

파일에 이름을 더하기 위해서, link 함수를 사용하라. ( 새로운 이름은 파일에 하드링크라고 불려진다. ) 파일에 만들어진 새로운 링크는 파일의 내용들은 복사하지 않는다; 그것은 그냥 간단히 기존에 있는 파일에 새로운 이름을 하나 더할 뿐이다.

하나의 파일은 여러개의 디렉토리들에 이름을 가질 수 있어서, 파일 시스템의 구조는 정적 계층 도나 트리 모양이 아니다.

단일한 파일 시스템 안에 존재하는 특별한 파일에서, 그 파일 이름들은 모두 단일한 파일 시스템의 디렉토리 안에 존재해야만 한다. link는 다른 파일 시스템으로부터 그 파일에 하드링크를 만들려고 시도하면 에러를 출력한다.

 
역자주 : 그러니까. . 어떤 파일에서 링크된 것들도 모두 원래의 파일과 같은 파일 시스템 안에 존재해야지, 다른 곳에 있으면 안된다는 말씀. 즉, 파일 시스템들간에 파일을 링크하는 것은 불가능하다.

link함수의 프로토타입은 헤더파일 'uinstd. h'에 선언되어 있다.

함수 : int link (const char *oldname, const char *newname)

link함수는 oldname의 이름을 가진 현존하고 있는 파일에 newname이라는 이름을 갖는 새로운 링크를 만든다. 이 함수는 성공하면 0을 리턴하고 실패하면 -1을 리턴한다. 보통의 파일 이름 문법 에러에 더하여서( 6. 2. 3절[File Name Errors] 참조),
다음 errno는 이 함수에서 정의하고 있는 에러상황이다.

EACCES : 새로운 링크가 쓰여져야 할 디렉토리가 기록 불가능이다.

EEXIST

이미 newname의 이름을 가진 파일이 있다. 만일 새로운 링크로 기존의 링크를 대치하게 원한다면, 당신은 먼저 기존의 링크를 제거해야 한다.

EMLINK

그것엔 이미 oldname에 의해 이름된 너무 많은 링크가 있다. ( 링크의 최대개수는 LINK_MAX이다. 27. 6절 [Limits for Files] 참조) 잘 만들어진 파일시스템들은 결코 이 에러를 발생시키지 않는다. 왜냐하면 그들은 당신의 디스크가 가질 수 있는 만큼의 많은 링크를 허용하기 때문이다. 그렇지만 당신은 다른 기계상의 파일 시스템을 네트웍으로 억세스 할 수도 있으므로, 당신의 시스템이 이런 에러를 발생시키지 않는다고 하더라도, 당신은 여전히 링크의 개수에 신경을 써야한다.

ENOENT

oldname이란 이름을 가진 파일이 존재하지 않는다. 당신은 그 파일이 없으면, 파일에 링크를 만들 수 없다.

ENOSPC

새로운 링크를 포함해야할 디렉토리나 파일 시스템이 "가득 찼고" 더 이상 확장되지 않는다.

EPERM

어떤 곳에서는 특권이 부여된 사용자에게만 디렉토리에 링크를 만드는 것을 허용하고, 다른 사용자들에게는 완전히 이 명령을 금지한다. 이 에러는 그 문제를 알리기 위해 사용된다.

EROFS

디렉토리가 읽기 모드 파일 시스템이기 때문에 새로운 링크를 갖고 있는 디렉토리로 갱신되어 질 수 없다.

EXDEV

새로운 이름으로 지정된 디렉토리가 링크하려는 파일과는 다른 파일 시스템 상에 존재한다.


9. 4 심볼릭 링크

GNU 시스템에서는 소프트 링크 혹은 심볼릭 링크를 지원한다. 이것은 일종의 "파일"로서 본질적으로는 다른 파일이름을 가리키는 포인터이다. 하드링크와는 달리, 심볼릭 링크는 디렉토리나 서로 다른 파일 시스템에 아무런 제한없이 만들 수 있다. 당신은 또한 아직 어느 파일의 이름으로 존재하지 않는 이름에 심볼릭 링크를 만들 수도 있다. ( 이런 링크의 개방은 그 이름의 파일이 만들어질 때까지 실패할 것이다. ). 마찬가지로, 만일 심볼릭 링크가 현존하는 파일에서 만들어지고 나중에 그 파일이 지워졌다면, 심볼릭 링크는 더이상 그 파일이 존재하지 않음에도 불구하고 동일한 파일이름을 가리키며 남아있다.

심볼릭 링크라고 불려지는 이유는 당신이 링크를 개방하려 시도할 때 그들이 행하는 특별한 작업방법 때문이다. open함수는 당신이 링크의 지정된 이름을 인수로 준다면, 그 링크에 포함된 파일이름을 읽어서, 대신에 그 파일 이름을 개방한다. stat함수는 마찬가지로, 링크의 그 자체 대신에 심볼릭 링크에 연결된 그 파일상에서 동작한다. link함수는 하드 링크를 만든다.

하지만, 파일을 지우거나, 재 명명하거나 하는 명령들을 링크 그 자신에서 행해진다. readlink와 lstat 함수는 또한 심볼릭 링크에서 동작하는데, 왜냐하면 그들의 목적이 링크에 대한 정보를 얻는 것이기 때문이다. 이들 함수를 위한 프로토타입은 'uinstd. h'이다.

함수 : int symlink (const char *oldname, const char *newname)

symlink함수는 oldname에 newname으로 이름된 심볼릭 링크를 만든다. symlink로부터 리턴 값은 보통 0이다. 만일 에러가 발생하면 -1을 리턴한다. 보통 파일 이름 문법 에러에 더하여서( 6. 2. 3절 [File Name Errors] 참조)
다음 errno는 이 함수에서 정의된 에러 상황이다.

EEXIST : 이미 newname이름을 가진 파일이 존재한다.

EROFS : newname 파일이 읽기-모드 파일 시스템 상에 존재할 것이다.

ENOSPC : 디렉토리나 파일 시스템이 새로운 링크를 만들도록 확장되어질 수 없다.

EIO : 디스크에 데이터를 쓰거나, 읽는 동안 하드웨어 에러가 발생했다.

함수 : int readlink (const char *filename, char *buffer, size_t size)

readlink함수는 심볼릭 링크 filename의 값을 얻는다. 링크가 가리키는 파일 이름이 버퍼에 카피된다. 이 파일 이름 문자열은 널 종료문자로 끝나지 않는다; readlink는 보통 카피된 문자들의 개수를 리턴한다. size인수는 카피할 문자들의 최대 수를 지정하고, 보통 버퍼의 할당 크기가 된다. 만일 리턴 값이 size와 같다면, 당신은 그 버퍼에 완전한 이름이 리턴된 것인지, 아닌지를 알 수가 없다. 그러므로 다시 버퍼를 크게 하고, readlink를 다시 호출하라.
이곳에 그 예가 있다.
char *readlink_malloc (char *filename)
{
int size = 100;
while (1)
{
char *buffer = (char *) xmalloc (size);
int nchars = readlink (filename, buffer, size);
if (nchars < size)
return buffer;
free (buffer);
size *= 2;
}
}
-1의 값이 리턴되었다면 에러가 발생한 것이다. 보통 파일이름 문법에러에 대하여( 6. 2. 3절 [File Name Errors] 참조)
다음의 errno는 이 함수에서 정의한 에러상황이다.

EINVAL : 주어진 filename이 심볼릭 링크가 아니다.

EIO : 디스크 상에서 읽거나, 쓰고 있는 동안 하드웨어 에러가 발생했다.


9. 5 파일 지우기

당신은 unlink 나 remove 의 함수로 파일을 지울 수 있다. ( 이들 이름들은 동의어이다. )

삭제(Deletion)는 실제로 파일이름을 지운다. 만일 그 이름이 파일의 유일한 이름이라면, 그 파일은 삭제된다. 하지만 만일 그 파일이 다른 이름으로 존재하고 있다면( 9. 3절 [Hard Links] 참조), 그것은 다른 이름 아래서 억세스 가능한 상태로 남는다.

함수 : int unlink (const char *filename)

unlink함수는 파일이름 filename을 지운다. 만일 이 파일이름이 그 파일의 유일한 이름이라면, 그 파일 자체가 삭제된다. (실제로는, 만일 어느 프로세스가 이처럼 unlink될 때 그 파일을 개방된 파일로 갖고 있다면, 모든 프로세스들이 그 파일을 닫을 때까지 삭제는 연기된다. )unlink함수는 헤더파일 'unistd. h'에 선언되어 있다. 이 함수는 성공하면 0을 리턴하고 에러이면 -1을 리턴한다. 보통의 파일이름 문법에러에 더하여서( 6.2.3절 [File Name errors] 참조)
다음의 errno는 이 함수를 위하여 정의된 에러 상황이다.

EACCESS : 파일을 제거하기 위한 쓰기 요청이 디렉토리에서 거부되었다.

EBUSY

이 에러는 그 파일이 제거되어질 수 없는, 시스템에서 사용하고 있는 파일임을 나타낸다. 당신이 어디서건 이 에러를 보았다면 그것은 당신이 지정한 파일이름이 루트 디렉토리이거나 파일 시스템에서 마운트하고 있다는 것이다.

ENOENT : 제거하려는 파일이름이 존재하지 않는다.

EPERM

어떤 시스템에서는, unlink는 디렉토리 제거에 사용할 수 없거나, 오직 특권이 부여된 사용자만이 이 방법을 사용할 수 있거나 한다. 이와 같은 문제들을 피하기 위해서, 디렉토리를 지우려면 rmdir를 사용하라.

EROFS

지우려는 파일 이름의 디렉토리가 읽기 모드 파일 시스템 상에 존재하고 있기 때문에 갱신되어 질 수 없다.

함수 : int remove (const char *filename)

remove 함수는 unlink의 다른 이름으로 ANSI C 이다. unlink는 POSIX. 1 이름이다. remove는 'stdio. h'에 선언되어 있다.

함수 : int rmdir (const char *filename)

rmdir는 디렉토리를 지운다. 디렉토리를 제거하기 전에는 디렉토리는 반드시 비어있어야 한다. 즉, 그 디렉토리는 `. ' 와 `. . ' 의 엔트리만 갖고 있어야 한다. rmdir 은 unlink처럼 동작한다.
다음의 두 개의 부가적 errno는 rmdir을 위해서 정의된 에러상황이다.

EEXIST, ENOTEMPTY

지우려는 디렉토리가 비어있지 않다. 이들 두 개의 에러는 동일하다. 어떤 시스템에서는 어떤 하나를 사용하고, 다른 시스템에서는 다른 하나를 사용한다. 이 함수를 위한 프로토타입은 헤더파일 'uinstd. h'에 선언되어 있다.


9. 6 파일 재 명명하다

rename함수는 파일의 이름을 변경하는데 사용한다.

함수 : int rename (const char *oldname, const char *newname)

rename함수는 파일 이름 oldname을 newname으로 재 명명한다. oldname 이름 하에서의 파일 검색 형식은 나중에 newname으로 재명명 되더라도, 역시 변함이 없다. (만일 그 파일이 oldname외에 다른 이름들은 가졌다면, 그것들의 이름에도 변함이 없다. ) newname 이름의 파일을 갖고 있는 디렉토리는 그 파일( oldname 이름의 파일 )과 같은 파일 시스템 안에 있어야만 한다. 재명명의 특별한 경우는 동일한 파일에 oldname과 newname 두 개의 이름이 존재할 때이다. 이 경우에 대응하기 위한 일관된 방법은 oldname을 제거하는 것이다. 그렇지만, POSIX는 이 경우에 rename은 아무 일도 하지 않고, 일치하는 파일이 없었을 때, 성공하게 된다. 우리는 당신의 운영체제가 무엇을 할 것인지 알지 못한다.
GNU시스템은 당신이 POSIX 시스템과 호환성을 가지도록, 명백하게 요청하지 않더라도, 옳은 일(oldname의 제거)을 할 것이다. 만일 oldname이 디렉토리가 아니라면, 이미 존재하고 있던 newname의 이름을 가진 파일은 재명명의 동작이 수행될 때 지워진다. 그렇지만, 만일 newname이 디렉토리라면, rename은 이 경우 실패로 끝난다. 만일 oldname이 디렉토리일 때, newname의 이름을 가진 어떤 것도 존재해서는 안되고, 또는 그것이 비어있는 디렉토리 이름이거나 해야한다.
후자의 경우에, newname의 이름을 가진 디렉토리를 우선 지우고 재명명을 하는 것이다. newname은 재명명을 시도할 디렉토리로 oldname의 서브디렉토리를 지정하지 않아야만 한다. rename은 기존에 oldname이란 이름을 갖고 있는 파일을 newname이라는 새로운 이름으로 자동적으로 변경할 때 쓰여 진다. old를 new로 변경할 동안 "그 사이에" newname의 이름을 가진 것이 존재하지 않는다면 더 이상 신경쓸것이 아무 것도 없다. 만일 rename이 실패하면, -1을 리턴한다.

파일 이름 문법 에러에 ( 6.2.3절 [File Name Errors] 참조) 더하여, 다음 errno는 이 함수에서 정의된 에러 상황이다.

    EACCES

    newname이나 oldname을 갖고 있는 디렉토리들 중의 하나가 쓰기 요청을 거부했다. 또는 newname과 oldname은 디렉토리인데 쓰기 요청이 그들 중에 하나에서 거부되어졌다.

    EBUSY

    oldname이나 newname이름을 가진 디렉토리가 시스템이 작업하는 동안 재명명을 거부하는 방법으로 현재 그 디렉토리를 시스템에서 사용하고 있다. 디렉토리가 파일 시스템으로 마운트(mount)된 것이고, 디렉토리가 프로세스들의 현재 작업 디렉토리이다.

    EEXIST : newname 디렉토리가 비어있지 않다.

    ENOTEMPTY : newname 디렉토리가 비어있지 않다.

    EINVAL : oldname 디렉토리가 newname을 포함하는 디렉토리이다.

     
    역자주 : newname이 oldname의 서브디렉토리.

    EISDIR : newname은 디렉토리 이름인데, oldname은 디렉토리 이름이 아니다.

    EMLINK

    newname의 부모 디렉토리가 너무 많은 링크들을 가지고 있다. 잘 만들어진 파일 시스템들은 결코 이 에러를 발생시키지 않는다, 왜냐하면 그들은 당신의 디스크가 허용하는 한 많은 링크를 허용하기 때문이다. 하지만 당신은 다른 기계상의 파일 시스템을 네트웍으로 억세스할 수 있으므로, 이 에러에 대한 가능성에 대해서 항상 대비해야만 한다.

    ENOENT : oldname 이란 이름을 가진 파일이 존재하지 않는다.

    ENOSPC

    newname을 포함할 디렉토리가 더 이상의 엔트리를 받아들일 수 없고, 그곳에는 파일 시스템 안에 확장할 공감이 남아있지 않다.

    EROFS : 오직 읽기 모드인 파일 시스템상의 디렉토리에 쓰기를 시도하고 있다.

    EXDEV

    oldname과 newname이라는 두 개의 파일 이름이 서로 다른 파일 시스템에 존재하고 있다.


9. 7 디렉토리 만들기

디렉토리는 mkdir 함수로 만들어진다. ( 같은 일을 하는 mkdir 이라는 쉘 명령어도 있다. )

함수 : int mkdir (const char *filename, mode_t mode)

mkdir 함수는 filename의 이름을 가진 새로운, 빈 디렉토리를 만든다. mode 인수는 새로운 디렉토리에 대한 접근 권한을 정한다. 9.8.5절 [Permission Bits]를 참조로 해서 접근 권한에 대한 자세한 정보를 얻어라.

수행이 성공적으로 끝나면 0의 값을 리턴하고, 그렇지 않을 경우에는 -1을 리턴한다. 보통의 파일 이름 문법 에러들에 더하여( 6.2.3 [File Name Errors] 참조 )

다음의 errno는 이 함수를 위해 정의된 에러 상황들이다.

    EACCES : 새로운 디렉토리를 더하게될 부모 디렉토리에서 파일 쓰기 허용이 거부되었다.

    EEXIST : filename의 이름을 가진 파일이 이미 존재한다.

    EMLINK

    부모 디렉토리가 너무 많은 링크들은 가지고 있다. 잘 만들어진 파일 시스템에서는 이러한 에러를 결코 발생시키지 않는다, 왜냐하면, 그들은 당신의 디스크가 저장할 수 있는 만큼의 링크를 허용하기 때문이다. 하지만 당신은 다른 기계 상에 존재하는 파일 시스템을 네트웍을 통해서 억세스할 수 있으므로 이러한 에러가 발생될 가능성에 대해서 항상 대비해야 한다.

    ENOSPC : 파일 시스템이 새로운 디렉토리를 만들만한 충분한 공간을 가지고 있지 않다.

    EROFS

    디렉토리의 부모 디렉토리가 오직 읽기 모드 파일 시스템 상에 존재하고 있고, 그래서 갱신할 수 없다.

이 함수를 사용하려면, 당신의 프로그램에 헤더파일 'sys/stat. h'를 포함해야 한다.


9. 8 파일 속성들

한 파일에 쉘 명령어 'ls -l'을 사용하면, 당신은 파일의 크기, 파일의 소유자, 마지막 갱신된 때, 등등에 대한 정보를 얻을 수 있다. 이러한 정보들의 종류를 파일 속성이라고 부른다; 이것은 파일 그 자체와 연관되어 있고, 그 이름들의 하나가 특별한 것은 아니다.

이 절에서는 당신이 어떻게 파일들의 속성들에 대한 정보를 얻고, 그들을 갱신할 수 있는지를 설명하고 있다.

 

9. 8. 1 파일 속성들의 값이 무엇을 의미하는가

당신이 파일 속성을 읽을 때, 그들은 struct stat라고 불리는 구조체로 보내져온다. 이 절은 그 속성들의 이름과, 그들의 데이터 타입들과, 그들이 무엇을 의미하고 있는지에 대해 설명하고 이다. 파일의 속성을 읽기 위한 함수는, 9. 8. 2절 [Reading Attributes]를 참조하라.

이 절에서 정의된 모든 심볼들은 헤더파일 'sys/stat. h'에 있다.

데이터타입 : struct stat

stat 구조체형은 파일의 속성들에 대한 정보를 리턴하기 위해 사용되어진다. 그들은 적어도 다음과 같은 멤버들을 포함하고 있다.

mode_t st_mode

파일의 모드를 정한다. 이것은 파일 타입 정보와( 9. 8. 3 [Testing File Type] 참조) 파일 접근 권한 비트를(file permission) 포함하고 있다. ( 9. 8. 5절 [Permission Bits] 참조)

ino_t st_ino

파일 일련 번호( file serial number), 로써 같은 디바이스 상에서 모든 다른 파일들과 이 파일을 구분한다.

dev_t st_dev

파일을 포함하고 있는 디바이스를 기술한다. st_ino와 st_dev, 이 둘을 가지고, 파일을 유일하게 식별한다.

nlink_t st_nlink

파일에 관련된 하드 링크의 개수이다. 이 파일을 엔트리로 가지고 있는 얼마나 많은 디렉토리들이 있는지 추적해서 그 값을 유지한다. 만일 개수가 0 으로 감소하면, 그 파일 자체가 없어진 것이다. 심볼릭 링크들은 총 개수에 포함되지 않는다.

uid_t st_uid

파일 소유자의 유저 ID 이다. 9.8.4 절 [File Owner] 참조.

gid_t st_gid

파일의 그룹 ID이다. 9.8.4절 [File Owner] 참조.

off_t st_size

이것은 바이트의 수로 일반적 파일의 크기를 지정한다. 만일 파일들이 디바이스거나, 그와 같은 파일로 존재한다면, 이 필드는 보통 아무런 의미가 없다.

time_t st_atime

이것은 파일의 최종 억세스 시간이다. 9. 8. 9절 [File Times] 참조.

unsigned long int st_atime_usec

이것은 파일의 최종 억세스 시간의 부수적인 부분이다. 9. 8. 9절 [File Times] 참조.

time_t st_mtime

이것은 파일의 내용이 마지막으로 갱신된 시간을 말한다. 9. 8. 9절[File Times] 참조.

unsigned long int st_mtime_usec

이것은 파일이 마지막으로 갱신된 시간의 부수적인 부분이다. 9. 8. 9절 [File Times] 참조.

time_t st_ctime

이것은 파일의 속성 자체가 마지막으로 갱신된 시간을 말한다. 9. 8. 9절 [File Times] 참조.

unsigned long int st_ctime_usec

이것은 파일 속성이 마지막으로 갱신된 시간의 부수적인 부분이다. 9. 8. 9절 [File Times] 참조.

unsigned int st_nblocks

이것은 512-바이트 블록의 단위로 계산된, 파일의 점유하고 있는 디스크 공간의 양을 말한다. 디스크 블록들의 개수는 파일이 크기와 완전히 비례하지 않는다. 두 가지 이유로. . . ; 파일 시스템이 내부적 레코드를 가지고 있기 위해서 어떤 블록들을 사용할 것이고; 그리고 파일들은 0(zeros)과 같은 "구멍들"을 가지고 있을 것이기 때문이다. 한 파일에서 st_size와 이 값을 비교하면 (대략) 한 파일의 내용이 드문드문한지 아닌지 알 수 있다. 이처럼:
(st. st_blocks * 512 < st. st_size)
이 결과는 모든 여기저기 흩어져 있는 것들이 검출이 되지 않을 수 도 있기 때문에, 완전한 결과는 아니다. 실용적인 어플리케이션에서, 이것은 문제가 아니다.

unsigned int st_blksize

쓰여진 파일을 읽기 위한 최적의 블록 크기를 말한다. 당신은 쓰여진 파일을 읽기 위한 버퍼 공간을 할당하기 위해서 이 크기를 사용할 것이다. 어떤 파일 속성들은 그들을 위해 특별히 존재하는 특별한 데이터 타입의 이름들을 가지고 있다. ( 그들은 당신이 익히 알고 있는 것들을 정수형으로 이름을 붙여놓은 것이다. ) 이들 typedef 시킨 이름들은 'sys/types. h'와 'sys/stat. h'에 정의되어 있다. 여기에 그들에 대한 설명이 있다.

데이터타입 : mode__t

이것은 현재의 파일 모드들을 나타내기 위해 사용되는 정수형 데이터 타입니다. GNU 시스템에서, 이것은 unsigned int 와 동일하다.

데이터타입 : ino__t

이것은 파일의 일련 번호들을 나타내기 위해 사용하는 산술적 데이터 타입이다. (jargon 유닉스에서는, 이들을 때때로 inode 번호라고 불려 진다. ) GNU 시스템에서는, 이 타입은 unsigned long int와 동일하다.

데이터타입 : dev__t

이것은 파일 디바이스 번호를 나타내기 위해 사용하는 산술적 데이터 타입니다. GNU 시스템에서는, 이것은 int 와 동일하다.

데이터타입 : nlink__t

이것은 파일 링크의 개수를 나타내기 위해 사용되는 산술적 데이터 타입입니다. GNU 시스템에서, 이것은 unsigned short int 와 동일하다.

 

9. 8. 2 파일 속성들 읽기

파일의 속성들을 조사하기 위해서는, stat, fstat 와 lstat 함수를 사용하라. 그들은 struct stat object에 속성정보를 리턴한다. 세 개 함수 모두는 헤더파일 'sys/stat. h'에 선언되어 있다.

함수 : int stat (const char *filename, struct stat *buf)

stat 함수는 buf가 가리키는 구조체안에 filename의 이름을 가진 파일의 속성에 대한 정보를 리턴한다. 만일 filename이 심볼릭 링크의 이름이라면, 당신이 얻게될 속성 정보는 링크가 가리키고 있는 파일에 대한 정보이다. 만일 링크가 가리키고 있는 파일이 존재하지 않는 파일이라면, stat는 실패하게 되고, 존재하지 않는 파일이라고 보고한다. 만일 오퍼레이션이 성공하면 0을 리턴하고, 실패하면 -1을 리턴한다. 파일 문법 에러들에 더하여(6. 2. 3절 [File Name Errors] 참조),

다음의 errno는 이 함수를 위해 정의된 에러 상황이다.

ENOENT : filename의 이름을 가진 파일이 존재하지 않음.

함수 : int fstat (int filedes, struct stat *buf )

fstat 함수는 파일 이름을 인수로 받아들이는 것 대신에 개방된 파일 기술자를 인수로 받아들이는 점을 제외하고는 stat와 같다. 8장 [Low_Level I/O] 참조.
stat처럼, fstat도 성공하면 0을 리턴하고, 실패하면 -1을 리턴한다.
다음은 errno는 함수 fstat를 위해 정의된 에러상황이다.

EBADF : filedes 인수가 유용한 파일 기술자가 아니다.

함수 : int lstat (const char *filename, struct stat *buf )

lstat 함수는 심볼릭 링크를 따르지 않는다는 점을 제외하고는 stat와 같다. 만일 filename이 심볼릭 링크의 이름이라면, lstat는 링크 그 자체에 대한 정보를 리턴한다; 그렇지 않다면 lstat는 stat처럼 동작한다. 9.4절 [Symbolic Links] 참조.

 

9. 8. 3 파일의 형식 알아보기

파일 속성의 st_mode 필드안에 저장된 파일 모드는 두 가지 정보를 담고 있다: 하나는 파일 타입 코드이고, 다른 하나는 접근 허가 비트들이다. 이 절은 그 파일이 디렉토리인지, 아니면 소켓인지, 등등을 알 수 있는 파일 타입 코드에 대한 것을 설명할 것이다. 파일 접근 권한에 대한 정보는, 9. 8. 5절 [Permission Bits] 참조.

파일 모드에서 파일 타입 부분을 검색할 수 있는 미리 정의된 두 가지 방법이 있다. 그중 한가지는, 파일 모드 값을 시험하는 매크로를 사용해서 파일이 그 타입인지, 아닌지를 참과 거짓으로 리턴하는 방법이 있다. 둘째로, 파일 모드에서 다른 값들을 제외하고( mask out을 시켜서 ) 오직 파일 타입 코드만을 얻어내는 방법이다. 당신은 이 값을 여러 가지 다양한 상수들과 비교할 수 있다. 이 절에서 설명된 모든 심볼들은 헤더파일 'sys/stat. h'에 정의되어 있다.

다음은 파일 타입을 테스트하기 위한 매크로로써, 주어진 m은 stat 함수에 의해 리턴된 st_mode 필드이다.

int S__ISDIR (mode_t m) Macro

이 매크로는 만일 그 파일이 디렉토리라면 0이 아닌 값을 리턴한다.

int S__ISCHR (mode_t m) Macro

이 매크로는 만일 그 파일이 문자 특수화일( 터미널과 같은 디바이스 )이면 0이 아닌 값을 리턴한다.

int S__ISBLK (mode_t m) Macro

이 매크로는 만일 그 파일이 블록 특수 파일 ( 디스크와 같은 디바이스 )이면 0이 아닌 값을 리턴한다.

int S__ISREG (mode_t m) Macro

이 매크로는 만일 그 파일이 보통의 파일이라면 0이 아닌 값을 리턴한다.

int S__ISFIFO (mode_t m) Macro

이 매크로는 만일 그 파일이 FIFO 특수 파일이나, pipe라면 0이 아닌 값을 리턴한다. 10장 [Pipes and FIFOs] 참조.

int S__ISLNK (mode_t m) Macro

이 매크로는 만일 파일이 심볼릭 링크라면 0이 아닌 값을 리턴한다. 9. 4절 [Symbolic Links] 참조.

int S__ISSOCK (mode_t m) Macro

이 매크로는 만일 그 파일이 소켓이라면 0이 아닌 값을 리턴한다. 11장 [Sockets] 참조. 파일 타입을 테스트하는 비-POSIX의 방법은 BSD와의 호환성을 위해서 지원된다. 그 모드는 파일 타입 코드를 추출하기 위해 S_IFMT와 비트 단위 AND연산을 시키고, 적당한 타입 코드 상수와 비교한다.
예를 들어, S_ISCHR (mode) 는 다음과 동등하다:
((mode & S_IFMT) == S-IFCHR)

int S__IFMT Macro

이것은 mode 값에서 파일 타입 코드의 부분을 추출하기 위해서 사용되는 비트마스크이다. 이들은 다른 파일 타입 코드들을 위해서 심볼화된 이름을 가지고 있다.

S_IFDIR

이 매크로는 디렉토리 파일을 위한 파일 타입 코드의 값을 나타낸다.

S_IFCHR

이 매크로는 문자-지향(character-oriented) 디바이스 파일을 위한 파일 타입 코드의 값을 나타낸다.

S_IFBLK

이 매크로는 블록-지향(block-oriented) 디바이스 파일을 위한 파일 타입 코드의 값을 나타낸다.

S_IFREG

이 매크로는 보통의 파일을 위한 파일 타입 코드의 값을 나타낸다.

S_IFLNK

이 매크로는 심볼릭 링크를 위한 파일 타입 코드의 값을 나타낸다.

S_IFSOCK

이 매크로는 소켓을 위한 파일 타입 코드의 값을 나타낸다.

S_IFIFO

이 매크로는 FIFO 나 pipe를 위한 파일 타입 코드의 값을 나타낸다.

 

9. 8. 4 파일 소유자

모든 파일은 시스템 상에 등록된 사용자 이름들중 하나인 소유자를 갖고 있다. 각 파일은 또한 정의된 그룹들중 하나인 그룹을 갖고 있다. 파일 소유자는 누가 그 파일을 편집했는지( 특별히 당신이 GNU Emacs로 편집을 할 때 ) 알기 위해서도 필요하지만, 그것의 주된 목적은 접근 권한을 제어하기 위함이다.

파일 소유자와 그룹은, 그 파일이, 파일 소유자인 사용자를 위한 접근 권한 설정, 그리고 파일의 그룹에 속한 사용자들에 적용시키기 위한 다른 설정, 그리고 모든 다른 사람들에게 적용하기 위한 세 번째 비트 설정을 가지고 있기 때문에, 접근을 결정하는 규칙에 따른다. 9. 8. 6절 [Access Permission] 를 참조하면, 이 데이터를 기초로 해서 어떻게 접근을 결정하는지에 대한 상세한 정보를 얻을 수 있다.

파일이 만들어질 때, 그 파일의 소유자는 그 파일을 만든 프로세스의 사용자 ID를 통해 설정된다( 25. 2절 [Process personal] 참조). 파일의 그룹 ID는 그 프로세스의 그룹 ID로 설정되거나, 아니면 그 파일이 포함된 디렉토리의 그룹 ID로 설정되거나 하는데, 그것은 그 파일이 저장된 시스템에 따라 다르다. 당신이 원격 파일 시스템을 억세스할 때, 당신의 프로그램이 구동되고 있는 시스템에 따르는 것이 아니라 그 파일 자신이 속한 시스템의 규칙에 따라 행동한다. 그래서 당신의 프로그램은, 당신이 어떤 시스템에서 그 프로그램을 구동시키는지에 상관없이, 당신이 부딪칠지도 모르는 모든 동작에 종류에 대해 미리 대비해야만 한다.

당신은 chown 함수를 사용해서 현존하는 파일의 사용자 와/또는 그룹 사용자를 변경할 수 있다. 이것은 chown과 chgrp 쉘 명령어에 기본적으로 포함되어 있다. 이 함수를 위한 프로토타입은 'unistd. h'에 선언되어 있다.

함수 : int chown (const char *filename, uid_t owner, gid_t group)

chown함수는 owner로 filename의 이름을 가진 파일의 소유자를 변경하고, group으로 그룹 소유자를 변경한다. 어떤 시스템 상에서 파일 소유자의 변경은 파일 접근 권한 비트들에서 set-user-ID 와 set-group-ID 비트를 클리어 한다(이것은 이 비트들이 새로운 소유자에게 적당하지 않을지도 모르기 때문이다. ). 다른 파일 접근 권한 비트들은 변경되지 않는다.

성공하면 리턴 값은 0이고, 실패하면 -1이다. 보통의 파일 문법 에러에 더하여( 6. 2. 3절 [File Name Errors] 참조),

다음의 errno는 이 함수를 위해 정의된 에러 상황이다.

EPERM

이 프로세스는 요청된 변경을 수행하기에는 접근권한이 부족하다. 오직 특권이 부여된 사용자나, 파일의 소유자만이 그 파일의 그룹을 변경할 수 있다. 대부분의 파일 시스템들은, 오직 특권이 부여된 사용자만이 그 파일의 소유자를 변경할 수 있다; 어떤 파일 시스템들은 만일 당신이 현재 그 파일의 소유자라면, 그 소유자를 변경할 수 있도록 허용한다. 당신이 원격 파일 시스템을 억세스할 때, 당신의 프로그램이 구동되고 있는 시스템에 의해서가 아니라, 그 파일을 실제로 갖고 있는 시스템에 의해서 동작이 결정되어 진다. 27. 7절 [Options for Files] 를 참조로-POSIX_CHOWN_RESTRICTED 매크로에 대한 정보를 얻어라.

EROFS : 파일이 오직 읽기 모드 파일 시스템에 존재한다.

함수 : int fchown (int filedes, int owner, int group)

이것은 개방된 파일 기술자 filedes의 파일 소유자를 변경한다는 점을 제외하고는 chown 함수와 같다. 성공하면 0을 리턴하고 실패하면 -1을 리턴한다. 다음의 errno는 이 함수를 위해 정의된 에러코드들이다.

EBADF : filedes 인수가 유용한 파일 기술자가 아니다.

EINVAL : filedes 인수가 보통의 파일이 아닌, pipe 나 소켓에 해당한다.

EPERM

이 프로세스는 요청된 변경을 수행하기 위한 파일 접근 허가가 부족하다. 좀더 상세한 것은 위의 chmod를 참조하라.

EROFS : 파일이 오직 읽기 모드 파일 시스템 상에 존재하고 있다.

9. 8. 5 파일 접근 허가 비트들

파일 속성의 st_mode 필드에 저장되어 있는 파일 모드는 두 가지의 정보를 포함하고 있다: 파일 타입 코드와 파일 접근 허가 비트들. 이 절에서는 오직, 파일을 누가 읽거나 쓸 수 있는가를 제어하는, 파일 접근 허가 비트에 대해서 다룰 것이다. 이 절에서 설명하고 있는 심볼들은 헤더파일 'sys/stat. h'에 정의되어 있다. 이들 심볼들은 파일 접근 하가를 제어하는 파일 모드 비트들을 위해 정의되어졌다.

S_IRUSR, S_IREAD

파일의 소유자를 위한 읽기 허가 비트. 많은 시스템들에서, 이 비트는 0400이다. S_IREAD는 BSD 와의 호환성을 위해 제공되고 있는 잘 안쓰이는 동의어이다.

S_IWUSR, S_IWRITE

파일의 소유자를 위한 쓰기 허가 비트. 보통 0200. S_IWRITE는 BSD와의 호환성을 위해 제공되고 있는 잘 안쓰이는 동의어이다.

S_IXUSR, S_IEXEC

파일의 소유자를 위한 실행( 보통의 파일 ) 이나 검색( 디렉토리를 위한 ) 허가 비트이다. 보통 0100. S_IEXEC는 BSD와의 호환성을 위해 제공되고 있는 잘 안쓰이는 동의어이다.

S_IRWXU : 이것은 '(S_IRUSR | S_IWUSR | S_IXUSR)'과 같다.

S_IRG : 파일의 그룹 소유자를 위한 읽기 허가 비트. 보통 040

S_IWG : 파일의 그룹 소유자를 위한 쓰기 허가 비트. 보통 020.

S_IXGP : 파일의 그룹 소유자를 위한 실행이나 검색 허가 비트. 보통 010.

S_IRWXG : 이것은 '(S_IRGRP | S_IWGRP | S_IXGRP)'와 같다.

S_IROTH : 다른 사용자를 위한 읽기 허가 비트. 보통 04.

S_IWOTH : 다른 사용자를 위한 쓰기 허가 비트. 보통 02.

S_IXOTH : 다른 사용자를 위한 실행이나 검색 허가 비트. 보통 01.

S_IRWXO : 이것은 '(S_IROTH | S_IWOTH | S_IXOTH)'와 같다.

S_ISUID

이것은 실행비트에서 set-user-ID로, 보통 04000. 25. 4절 [How Change Persona] 참조. 역자주: set-user-ID ; 수행중의 사용자 식별번호를 지정.

S_ISGID

이것은 실행비트에서 set-group-ID로, 보통 02000이다. 25. 4절 [How Change Persona] 참조. 역자주: set-user-ID : 수행중의 그룹식별번호를 지정

S_ISVTX : 이것은 스티키 비트로 보통 01000이다.

 
역자주: sticky bit ; 수행중의 텍스트 이미지를 저장.

수행중인 파일에서, 시스템의 스와핑 방법들을 변경한다. 보통은 프로그램이 종료될 때, 기억장치 안의 그 들은 즉시 해제되어 재사용 가능해진다. 그러나 만일 수행 가능한 파일에서 스티키 비트가 설정되면, 그 시스템은 마치 그 프로그램이 여전히 실행되고 있는 것처럼 기억장소에 들을 계속 유지하고 있다.

이것은 완전한 수행에 많은 시간이 소요될 것 같은 프로그램에 유용하다. 디렉토리에서, 스티키 비트는 만일 당신이 어느 파일에 쓰기 허가를 가지고 있다면 디렉토리 안의 그 파일을 제거하도록 허용한다. 보통 사용자는 디렉토리 안의 모든 파일들을 지울 수 있거나, 혹은 그들중 어느 것도 지울 수 없거나한다 ( 그 사용자가 디렉토리에 쓰기 허가를 갖고 있는지, 없는지에 기초한다. ). 스티키 비트는 개개의 파일들의 제거 권한을 제어하는 것을 가능하게 만든다.

 
역자주: 여기서 는 기억장치에 저장된 하나의 단위라고 볼 수 있겠네요.

심볼들의 실행 비트 값들은 위의 테이블에 있다. 당신은 당신의 프로그램을 디버깅할 때 파일 모드 값들은 해석할 수 있다. 이들 비트 값들은 대부분의 시스템에 정확하게 동작하지만, 그것을 완전히 보장할 수는 없다.

 
주의: 파일 접근 권한을 숫자로 명시하는 것은 좋지 않은 습관이다.

이것은 이식성이 없고, 또한 누군가 당신의 프로그램을 읽을 때, 그 비트가 무엇을 의미하는지 알 수 없기 때문이다. 프로그램을 기호(symbolic)이름들을 사용하여, 깨끗하게 만들어라.

 

9. 8. 6 어떻게 파일에 당신의 접근을 결정하는가

운영체제는 보통 유효 사용자와 프로세스의 그룹 ID들과, 그것을 보충하여 그룹 ID들과 파일의 소유자, 그룹 그리고 허가 비트들을 기초로 하여 파일에 대한 접근 하가를 결정한다. 이 원칙들은 25. 2절 [Process Persona] 에 자세히 나와있다.

 
역자주: 유효사용자ID: 실제 생성된 파일에 대한 소유권을 갖는 사용자 실제사용자ID: 프로세스를 수행시킨 사용자의 식별번호

만일 프로세스의 유효 사용자 ID가 파일의 소유 사용자 ID와 대응됐을 때, 읽기, 쓰기와 실행/검색허가는 해당되는 "사용자" (또는 "소유자") 비트에 의해 제어된다. 그와 같이, 만일 유효 그룹 ID 나 프로세스의 그룹 ID가 파일의 그룹 소유자 ID와 대응됐을 때, 파일 접근 허가는 "그룹" 비트들에 의해 제어된다. 그렇지 않다면, 파일 접근 허가는 "다른 사용자" 비트들에 의해 제어된다. '루트'처럼 특권이 부여된 사용자는 파일 접근 허가에 관계없이 어느 파일이라도 억세스할 수 있다. 특별한 경우로, 특권이 부여된 사용자를 위한 실행가능 파일을 위해서, 적어도 하나의 실행 비트들을 설정해야만 한다.

 

9. 8. 7 파일 접근 허가 정하기

파일을 만드는 원래의 함수들( 예를 들어, open이나 mkdir)은 새로이 만들어질 파일의 접근 허가를 정하기 위해서 mode인수를 취한다. 그러나 정해진 모드는 그것이 사용되기 전에, 프로세스의 파일생성마스크나 umask에 의해 갱신되어진다.

파일 생성 마스크에 설정되어진 비트들은 새로이 개방된 파일에 대한 , 그 설정에 해당하는 권한이 없다는 것을 의미한다. 예를 들어, 만일 당신이 "다른 사용자" 접근 권한 비트들을 모두 마스크에 설정하면, 새로이 생성된 파일에, "다른 사용자" 범주에 들어가는 모든 프로세스들의 접근이 불 가된다, 심지어 개방된 파일에 주어진 mode 인수가 접근가능이었다고 하더라도. 즉, 파일 생성 마스크는 당신이 원하는 만큼 파일 접근 허가를 부여하기가 용이하다.

프로그램들은 특별한 파일에 적정한 모든 허가를 포함하고 있는 mode 인수를 지정해서 파일을 개방한다. 보통의 파일은, 모든 부류의 사용자들에게 읽기와 쓰기 허가가 있다. 이들 허가들을 개별적으로 사용자 자신의 파일 생성 마스크를 통해서 제한하는 것이다.

이름이 있는 현존하는 파일의 허가를 변경하기 위해서는, chmod를 호출하라. 이 함수는 파일 생성 마스크를 무시한다; 그것은 정확히 정해진 허가 비트들을 사용한다. 보통, 파일 생성 마스크는 사용자의 로그인 쉘에서 초기화 되있고 (umask 쉘 명령어를 사용해서 ) , 그리고 모든 부프로세스들이 물려받는다. 응용 프로그램들은 보통 파일 생성 마스크에 대해서 걱정할 필요가 없다. 그것은 미리 가정된 것을 할 것이다. 당신이 파일을 개방하고, 파일 접근 허가를 위해서 umask를 사용할 때, umask를 사용하는 것보다는, 파일을 개방한 후에 fchmod를 사용하여 그 일을 하는 것이 가장 쉬운 방법이다.

실제로, umask를 통한 변경은 오직 쉘에 의해서 행해진다. 그들은 umask함수를 사용한다.

이 절의 함수들은 헤더파일 "sys/stat. h'에 선언되어 있다.

함수 : mode_t umask (mode_t mask)

umask 함수는 mask로 현재 프로세스의 파일 생성 마스크를 설정하고, 파일 생성 마스크의 전의 값을 리턴한다.
이곳에서는 그 값들을 변경하지 않고, umask를 사용해서 마스크를 어떻게 읽는지를 보여주고 있다.
mode_t
read_umask (void) {
mask = umask (0);
umask (mask);
}
그렇지만, 만일 당신이 마스크 값을 단지 읽기를 원한다면 getumask를 사용하는 편이 낫다, 왜냐하면 재진입 때문이다. (적어도 만일 당신이 GNU 운영체제를 사용하고 있다면 )

함수 : mode_t getumask (void)

현재의 프로세스를 위한 파일생성 마스크의 현재의 값을 리턴한다. 이 함수는 GNU확장이다.

함수 : int chmod (const char *filename, mode_t mode)

chmod 함수는 mode로 filename의 이름을 가진 파일을 위한 접근 허가비트를 설정한다. 만일 그 filename의 파일이 심볼릭 링크라면, chmod는 링크 그 자체가 아니라, 링크가 가리키고 있는 파일의 접근 허가를 변경한다. 링크의 모드를 설정할 수 있는 방법은 아무 것도 없다.
성공하면 0을, 실패하면 -1을 리턴한다. 보통의 파일 이름 문법 에러에 더하여 ( 6. 2. 3절 [File Name Errors] 참조),
다음의 errno는 이 함수에서 정의된 에러 상황이다.

ENOENT : 그 이름을 가진 파일이 존재하지 않는다.

EPERM

이 프로세스가 이 파일의 접근 허가를 변경할 만큼의 권한을 가지고 있지 않다. 오직 파일의 소유자( 프로세스의 유효 사용자 ID로 판단된)나 특권이 부여된 사용자만 그들을 변경할 수 있다.

EROFS : 파일이 오직 읽기 모드의 파일 시스템에 존재한다.

함수 : int fchmod (int filedes, int mode)

이것은 기술자 filedes를 거쳐서 현재 개방된 파일의 접근 허가를 변경한다는 점을 제외하고는 chmod와 같다.
fchmod로부터의 리턴 값은 성공하면 0이고, 실패하면 -1이다.
다음의 errno는 이 함수를 위해 정의한 상황이다.

EBADF : filedes 인수가 유용한 파일 기술자가 아니다.

EINVAL

filedes 인수가 파이프나 소켓이거나, 아니면 그것이 실제로 접근 허가를 가지지 않는 어떤 것에 해당한다.

EPERM

이 프로세스가 파일의 접근 허가를 변경하기 위한 허가를 가지고 있지 않다. 오직 파일의 소유자( 프로세스의 유효 사용자 ID로 판단된)나, 특권이 부여된 사용자만이 그들을 변경할 수 있다.

EROFS

파일이 오직 읽기 모드 파일 시스템 안에 존재한다.

9. 8. 8 파일을 억세스하기 위하여 파일 접근 허가를 알아보기

특권이 부여된 사용자로써 프로그램을 실행하고 있을 때, 그 사용자에게 제한없이 파일들을 억세스하도록 허용한다. 예를 들어, '/etc/passwd/'파일을 수정하기와 같은것도. 유효 사용자 ID로 항상 루트에서 실행되도록 setuid 비트를 사용하는 그런 파일들이 아니라면, 프로그램들은 보통의 사용자에 의해 실행되도록 만들어졌다. 정해진 사용자에 의하여 파일을 억세스하는 프로그램에서, 파일들이 명백한 사용자에 의해 억세스되어진다. 루트로 실행되는 프로그램에서는 정해진 사용자가 무슨 파일이든지 억세스가 허가되지만, 보통은 보통의 사용자가 검색할 수 있는 그런 파일들만 허가된다.

프로그램은 그 파일을 읽거나 쓰기전에, 사용자가 파일을 억세스할 필요가 있는지를 명백하게 체크해야만 한다. 이것을 하기 위해서, 유효 사용자 ID 보다는 프로세스의 실 사용자 ID에 의한 접근 허가를 체크하는 access함수를 사용하라. ( setuid는 그 프로그램을 실제로 실행시킨 사용자를 반영한, 실 사용자 ID를 변경하지 않는다. ) 설명하기는 쉽지만, 사용하기는 어려운 엑세스를 체크할 수 있는 다른 방법이 있다. 이것은 파일 모드 비트들을 시험하고 시스템의 엑세스조작을 흉내내는 것이다.

이 방법은 많은 시스템들이 부가적인 억세스 제어를 가지고 있기 때문에 바람직한 방법은 아니다; 당신의 프로그램이 이식성 있게 그들을 흉내낼 수도 없고, 다른 시스템들이 가진 다른 종류의 엑세스 제어를 알아내려 시도할 수도 없다. access를 사용하는 것은 간단하고, 당신이 사용하는 시스템이 무엇이든지간에 그 시스템에 적당한 동작을 자동적으로 한다.

이 절에서 설명된 심볼들은 'uinstd. h'에 선언되어 있다.

함수 : int access (const char *filename, int how )

access 함수는 how인수로 정해진 방법으로 filename의 이름을 가진 파일을 억세스하다 수 있는지를 알아보는 함수이다. how 인수는 R_OK, W_OK, X_OK, 플래그를 비트 단위 OR연산된 것이거나 존재 테스트 F_OK 플래그이다. 이 함수는 접근 허가를 체크하기위해서 유효사용자 ID를 사용하기 보다는 호출하는 프로세스의 실 사용자와 그룹 ID들을 사용한다. 그 결과로, 만일 당신이 setuid나 setgid 프로그램( 25. 4절 [How Change Persona] 참조)으로부터 함수를 사용한다면, 그것은 그 프로그램을 실제로 구동하는 사용자에 대한 정보를 알려준다.
억세스가 허가되면 0을 리턴하고, 그렇지 않으면 -1을 리턴한다. (즉, 하나의 함수로 취급하여, access는 요청된 접근이 거부되면 참을 리턴한다. ) 보통의 파일 이름 문법 에러에 더하여 ( 6. 2. 3절 [File Name Errors] 참조) 다음의 errno는 이 함수를 위해 정의된 에러 상황이다.

EACCES : how인수로 정해진 접근이 거부되었다.

ENOENT : 파일이 존재하지 않는다.

EROFS : 쓰기 허가가 오직 읽기 모드 파일 시스템 상에 존재하는 파일에 요청되었다.

이들 매크로들은 access 함수에 how인수로서 사용하기 위한 것으로 헤더파일 'unistd. h'에 정의되어 있다.

매크로 : int R__OK

읽기 허가를 위한 테스트를 의미하는 인수.

매크로 : int W__OK

쓰기 허가를 위한 테스트를 의미하는 인수

매크로 : int X__OK

실행/검색 허가를 위한 테스트를 의미하는 인수.

매크로 : int F__OK

파일의 존재를 위한 테스트를 의미하는 함수.

 

9. 8. 9 파일에 관련된 시간들

각 파일은 검색 시간, 갱신 시간, 속성 갱신 시간에 해당하는 세 가지 타임 스탬프들을 가지고 있다. 이것은 stat의 st_atime, st_mtime, st_ctime 멤버에 해당한다; 9. 8절 [File Attributes] 참조. 이 시간들 모두는 time_t objects 안에 표현된다. 이 데이터 타입은 'time. h'에 정의되어 있다. 시간 값들의 표현과 다루는 방법에 대한 자세한 설명은 17. 2절 [Calendar Time] 에 있다.

현존하는 파일이 개방되어 있을 때, 그 속성변경시간과 갱신 시간필드들은 갱신된다. 파일읽기는 검색 시간 속성을 갱신시키고, 파일쓰기도 또한, 갱신시간 속성을 갱신시킨다. 파일이 만들어질 때, 파일을 위한 세 가지 타임 스탬프는 현재의 시간으로 설정된다. 디렉토리의 속성 변경 시간과 갱신 시간의 필드들은 새로운 엔트리가 들어오면 갱신된다.

link함수로 원래의 파일에 새로운 이름이 더해지면, 링크되어진 파일의 속성 변경 시간(attribute change time)이 갱신되고, link를 통해 만들어진 새로운 이름을 포함하는 디렉토리의 속성 변경 시간과 갱신 시간(modifi-cation) 필드들이 갱신된다. 이와 같은 필드들은 unlink, remove, rmdir로 파일 이름이 제거될 때 영향을 받는다. rename로 파일을 재명명할 때, 파일이 포함된 부모 디렉토리들의 속성 변경 시간과 갱신시간 필드들 이 영향을 받지만, 파일에 관련된 시간속성들은 변경되지 않는다.

파일의 속성들의 변경은( 예를 들어, chmod를 통해서) 그 속성 변경시간 필드를 갱신한다. 당신은 속성 변경 시간을 제외하고, utime 함수를 사용해서 명시적으로 파일의 타임스탬프를 변경할 수 있다.

이것은 헤더파일 'utime. h'에 정의되어 있다.

데이터 타입 : struct utimbuf

utimbuf 구조체는 어떤 파일에 새로운 검색 시간과 갱신시간을 정해주기 위해서 utime 함수에서 사용된다. 이것은 다음과 같은 멤버들을 포함한다.
time_t actime 이것은 파일의 검색시간이다.
time_t modtime 이것은 파일의 갱신시간이다.

함수 : int utime (const char *filename, const struct utimbuf *times)

이 함수는 filename이름을 가진 파일과 연관된 시간을 변경하기 위해 사용된다. 만일 times가 널 포인터라면, 파일의 검색시간과 갱신시간들은 현재의 시간으로 설정된다. 그렇지 않다면, 그들은 times가 가리키는 구조체 utimbuf의 actime와 modtime 멤버들로부터 얻은 값으로 시간을 설정한다.
파일의 속성변경시간은 두 가지 경우 모두 현재의 시간으로 설정된다. ( 타임 스탬프들이 변경은, 파일 속성의 변경을 수반한다. )
utime 함수는 성공하면 0을 리턴하고, 실패하면 -1을 리턴한다. 보통의 파일 이름 문법 에러에 더하여( 6. 2. 3절 [File Name Errors] 참조), 다음의 errno는 이 함수를 위해서 정의된 에러 상황들이다.

EACCES

times 인수로 널 포인터를 주었을 때 허가문제가 있다. 파일의 타임 스탬프를 갱신하기 위해서는 파일의 소유자이고 파일에 쓰기 허가를 가지고 있거나, 특권이 부여된 사용자이어야 한다.

ENOENT : 파일이 존재하지 않는다.

EPERM

만일 times인수가 널 포인터라면, 당신은 파일의 소유자이거나 특권이 부여된 사용자이어야만 한다. 이 에러는 그 문제를 보고하는데 사용된다.

EROFS : 파일이 오직 읽기 모드 파일 시스템에 존재한다.

세 가지 타임 스탬프들은 연관된 마이크로초(microsecond) 부분을 가지고 있다. 이들 필드들은 st_atime_usec, st_mtime_usec, st_ctime_usec라고 불린다; 각각은 마이크로초 단위로 표현된 0에서 999, 999사이의 값을 가지고 있다. 그들은 timeval 구조체의 tv_usec에 해당한다; 17. 2. 2절[High-Resolution Calendar] 참조. utimes 함수는 utime와 같지만, 파일에 관련된 시간들을 아주 세밀하게 정하는 것을 허용한다.

이 함수를 위한 프로토타입은 헤더파일 'sys/time. h'이다.

함수 : int utimes (const char *filename, struct timeval tvp[2])

이 함수는 filename의 이름을 가진 파일의 검색 시간과 갱신시간을 설정하는 함수이다. 새로운 파일 검색 시간은 tvp[0]에 의해 정해지고, 새로운 갱신시간은 tvp[1]에 의해 설정된다. 이 함수는 BSD에서 왔다. 리턴 값과 error 에러 상황은 utime함수와 같다.


9. 9 특수 파일 만들기

mknod 함수는 디바이스와 같은, 특수한 파일을 만들기 위한 함수다. GNU 라이브러리는 BSD와의 호환성을 위해서 이 함수를 갖고 있다. mknod의 프로토타입은 'sys/stat. h'에 선언되어 있다.

함수 : int mknod (const char *filename, int mode, int dev)

mknod 함수는 filename의 이름을 가진 특수한 파일을 만든다. mode인수는 S_IFCHR(문자 특수 파일을 위해)나, S_IFBLK(블럭 특수 파일을 위해)와 같은 다양한 특수 파일 비트들을 가지고 파일의 모드를 지정한다. 9. 8. 3절 [Testing Fiel Type] 참조. dev 인수는 디바이스를 정한다. 그것의 정확한 해석은 만들어진 특수 파일의 종류에 의존한다.
리턴 값은 성공하면 0이고, 실패하면 -1이다. 보통의 파일 이름 문법 에러에 더하여 ( 6. 2. 3절 [File Name Errors] 참조), 다음의 errno는 이 함수를 위해 정의된 에러 상황이다.

EPERM : 호출한 프로세스가 특권이 없다. 특수 파일을 만들 수 있는 것은 슈퍼유저뿐이다.

ENOSPC : 새로운 파일을 갖고 있는 디렉토리나 파일 시스템이 가득 찼고, 더 이상 확장할 수 없다.

EROFS

새로운 파일을 갖고 있는 디렉토리가 오직 읽기 모드 파일 시스템 상에 있기 때문에 갱신될 수 없다.

EEXIST

filename의 이름을 가진 파일이 이미 존재한다. 만일 당신이 이 파일을 대체하기 원한다면, 당신은 먼저 그 원래의 파일을 제거해야만 한다.


9. 10 임시 파일들

만일 당신의 프로그램에서 임시파일의 사용이 필요하다면, 당신은 그것을 개방하기 위해 tmpfile함수를 사용할 수 있다. 또는 임시파일의 이름을 만들기 위해 tmpnam 함수를 사용하고 fopen을 사용해서 보통의 방법으로 그 임시파일을 개방할수 있다.

tempnam함수는 tmpnam함수와 같지만, 당신이 그 임시파일이 들어갈 디렉토리가 무엇인지, 그리고 그들의 파일이름이 무엇인지에 대한 것을 정하도록 허용한다.

함수 : FILE * tmpfile (void)

이 함수는 "wb+" 모드로 fopen을 호출함으로써, 갱신한 모드로 임시 바이너리 파일을 만든다. 그 파일은 그 프로그램이 종료할 때나 닫힐 때, 자동적으로 제거된다. ( 어떤 다른 ANSI C 시스템에서 그 프로그램이 비정상적으로 종료되면 파일의 제거도 실패할 것이다. )

함수 : char * tmpnam (char *result)

이 함수는 현재 존재하고 있는 파일 이름이 아닌 유용한 파일이름을 만들어서 리턴한다. 만일 result인수가 널 포인터라면, 리턴 값은 다음 호출로 갱신된 내부 정적 스트림의 포인터이다. 그렇지 않다면, result인수는 적어도 L_tmpnam의 배열을 가리키는 포인터이고 result는 그 배열 안에 저장된다. tmpnam의 호출에 너무 많은 시간이 소요되면 실패의 가능성이 있다. 이것은 임시파일을 정해진 개수의 파일이 있어야 하는 곳에서 이미 다른 파일들로 그 개수가 채워진 곳에 만들려했기 때문이다. tmpnam이 실패하면 널 포인터를 리턴한다.

매크로 : int L__tmpnam

이 매크로 값은 tmpnam함수로 만들어진 파일이름을 저장하기에 충분한 문자열의 최소 할당 크기를 나타내기 위한 정수 상수 표현이다.

매크로 : int TMP__MAX

매크로 TMP_MAX는 당신이 tmpnam으로 만들 수 있는 임시 파일 이름의 최소 경계이다. 당신이 너무 많은 임시 파일 이름을 만들어 실패를 경험하기 전에, 이 매크로 값에 의존할 수 있다. GNU 라이브러리에서는, 당신은 당신의 디스크의 공간이 허락하는 만큼의 많은 개수의 임시파일을 만들 수 있다. 어떤 다른 시스템에서는 임시파일의 개수를 작게 제한하고 있다. 그 제한은 25보다는 결코 작지 않다.

함수 : char * tempnam (const char *dir, const char *prefix)

이 함수는 단일한 임시 파일이름을 생성한다. 만일 prefix가 널 포인터가 아니고 이 문자열이 5개 문자 이상이면 그 prefix가 파일이름으로 사용된다. 임시파일 이름을 위한 디렉토리는 밑의 것들을 시험함으로 인해 결정한다. 디렉토리는 반드시 존재하고 기록 가능해야 한다.
환경 변수 TMPDIR이 정의되었는지. . .
dir 인수가 널 포인터인지. . .
P_tmpdir 매크로의 값.
'/tmp' 디렉토리.
이 함수는 SVID와의 호환성을 위해 정의되었다.

SVID 매크로 : char * P__tmpdir

이 매크로는 임시파일을 위한 디폴트(default) 디렉토리의 이름이다. 오래된 유닉스 시스템들은 설명된 함수들을 가지고 있지 않다. 대신에 그들은 mktemp 와 mkstemp 을 사용한다. 이들 함수들은 당신이 준 파일 이름 템플리트 문자열을 갱신하는 작업을 한다. 문자열의 마지막 6섯개 문자들은 반드시 'XXXXXX'이 되어야만 한다. 이들 6개 'X' 문자들은 단일한 파일 이름 문자열을 만든 6개의 문자들로 대체된다. 문자열은 보통 '/tmp/prefixXXXXXX'처럼 사용하고 각각의 프로그램은 단일한 prefix를 사용한다.

노트 : mktemp 와 mkstemp가 템플리트 문자열을 갱신하기 때문에, 당신은 그들에게 문자열 상수를 주지 않아야 한다. 문자열 상수들은 보통 오직 읽기만 가능한 기억장소에 존재하고, 그래서 당신의 프로그램은 mktemp 나 mkstemp가 문자열을 갱신하려 시도할 때 파괴되고 만다.

함수 : char * mktemp (char *template)

mktemp함수는 위에 설명된 것처럼 임시 문자열을 고쳐서 단일한 파일이름을 생성한다. 만일 성공하면, 갱신된 템플리트를 리턴한다. 만일 mktemp가 단일한 파일 이름을 발견할 수 없다면, mktemp는 빈 문자열을 만들고 그것을 리턴한다. 만일 그 템플리트에 'XXXXXX'로 끝나지 않는다면, mktemp는 널 포인터를 리턴한다.

함수 : int mkstemp (char *template)

mkstemp함수는 mktemp가 하는 것처럼 단일한 파일 이름을 생성하지만, mkstemp는 또한 open의 과정을 통해서 당신을 위해 그 파일을 개방한다 ( 8. 1절 [Opening and Closing Files] 참조). 만일 성공하면 적당한 템플리트를 갱신하고 그 파일을 읽기와 쓰기를 위해 개방해서 리턴한다. 만일 mkstemp가 단일한 이름을 가진 파일을 만들 수 없다면 그것은 빈 문자열의 템플리트를 만들고 -1을 리턴한다. 만일 템플리트가 'XXXXXX'로 끝나지 않는다면, mkstemp는 -1을 리턴하고 템플리트를 갱신하지 않는다.
mktemp와 달리, mkstemp는 임시 파일을 만들려 시도하고 있는 다른 프로그램과 충돌의 가능성이 없이 단일한 파일을 만드는 것을 보증한다. 그 이유는 open함수에 O_EXEL 플래그 비트를 사용함으로 인해서, 당신이 항상 새로운 파일을 만들기를 원함을 알리고, 그 파일이 이미 존재한다면 에러를 나타내도록 작업하기 때문이다.