4-2 디렉토리

do·2022년 3월 30일
0

API

목록 보기
18/42

리눅스 디렉토리
/ /bin /boot /dev /etc /home /lib /media /mnt
/opt /proc /root /run /sbin /sys /usr /var /tmp /lost+found

현재 작업 디렉토리
./

디렉토리 관련 함수
opendir(), readdir(), closedir()
link(), symlink(), unlink()
getcwd()
chdir(), mkdir(), rmdir()

리눅스 디렉토리 구조

/ 최상위에 있는 디렉토리
/bin 기본적인 명령어가 저장된 디렉토리
/boot 부팅에 필요한 정보를 가진 파일들이 있는 디렉토리
/dev 시스템 디바이스 파일을 저장하고 있는 디렉토리
HDD, CD-ROM, 마우스, 키보드 등과 물리적 장치들이 파일화 되어서 저장
/etc 설정 파일이 저장된 디렉토리
네트워크 관련 설정파일, 사용자 정보 및 암호정보, 파일 시스템 정보, 보안파일, 시스템 초기화 파일
/home 사용자 홈 디렉토리가 생성되는 곳
사용자를 추가하면 사용자의 id와 동일한 디렉토리가 자동으로 생성됩니다.
/lib 커널이 필요로 하는 각종 라이브러리 파일, 커널 모듈파일 등이 존재하는 디렉토리
/media DVD, CD_ROM, USB 등의 외부 장치들의 마운트 포인트로 사용하는 디렉토리
/mnt 파일 시스템을 임시로 연결하는 디렉토리
/media와 비슷한 기능인데,
media는 os에서 자동으로 마운팅 해주고, mnt는 사용자가 직접 마운트 해야합니다.
예를 들어 컴퓨터에 usb를 꽂아 자동으로 마운팅 된다면 주로 media 폴더 내에,
외부에 있는 디스크 등을 직접 명령어를 통해 마운트한다면 mnt 디렉토리에 위치하게됨
/opt 추가 소프트웨어 설치 디렉토리
/proc 커널과 프로세스를 위한 가상 파일 시스템들이 저장되어 있는 경로
/root 관리자 계정의 홈디렉토리
/run 계속 진행되고 있는 프로세스를 저장하는 디렉토리
/sbin 시스템 명령어가 저장된 디렉토리
/sys 디바이스를 관리하기 위한 가상 파일 시스템 디렉토리
/usr 일반 사용자가 사용하는 프로그램이 설치되는 디렉토리
/var 시스템 운영 중에 저장되는 자료가 저장된 디렉토리 (시스템 관련 로그파일, 사용자 메일파일, 사용자 로그인 보안기록 등)
/tmp 공용 디렉토리 및 임시 저장소
/lost+found 휴지통 같은 개념. 비정상적인 시스템 종료 등의 오류로 인한 메모리나 버퍼의 내용을 담고있음

Path 환경변수에 /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:
라고 지정되어 있어 운영체제는 디렉토리에 있는 실행파일들을 어느 위치에서든 실행할 수 있음

현재 작업 디렉토리

사용자가 현재 작업 중인 디렉토리로 명령 프롬프트와 상호 작용할 때마다 디렉토리 내에서 작업합니다. pwd 명령어로 확인 가능합니다.

디렉토리 관련 함수

opendir()

기능. 디렉토리를 열고, 이에 대한 스트림 포인터를 리턴합니다.
이 스트림은 디렉토리의 첫번째 요소의 위치를 가리킵니다.
헤더. #include <dirent.h>
원형. DIR* opendir(const char* dirname)
매개변수. const char* dirname 열고자 하는 디렉토리 이름
리턴값. DIR* 정상적이면 DIR* 포인터를 리턴
NULL 실패하면 NULL 리턴하고 errno에 에러코드가 들어갑니다.
DIR 데이터 유형은 디렉토리 스트림을 나타내기 위해 구현되지만, 사용자는 DIR 유형의 오브젝트를 할당해서는 안됩니다.
예제.

DIR* dir;
if ((dir = opendir("/etc")) == NULL)
	puts("error");
else
	puts("success to open");

readdir()

기능. opendir()로 얻어진 디렉토리 포인터를 통해 디렉토리 정보를 하나씩 차례대로 읽습니다. (파일의 끝에 도달할 때까지 입력path의 정보를 읽어옵니다.)
특정 디렉토리 내 1건의 디렉토리/파일 등을 구하는 함수. 함수 호출 시마다 1건씩 리턴됩니다.
읽힌 디렉토리/파일명은 리턴되는 struct dirent 구조체 내 d_name 변수에 저장됩니다.
헤더. #include <dirent.h>
원형. struct dirent* readdir(DIR* dirstream)
매개변수. DIR* dirstream 오픈된 디렉토리 스트림
리턴값. 디렉토리 스트림의 끝에 도달하거나(디렉토리 내 파일 정보를 모두 읽었을 때) 에러가 발생하면 NULL 리턴
예제.

DIR* dir;
struct dirent* entry;
if ((dir = opendir("/etc")) == NULL)
	puts("error");
else
	puts("success to open");
while ((entry = readdir(dir)) != NULL)
	puts("디렉토리 읽기 성공");
dirent.h
struct dirent
{
	long d_ino; //inode 번호
    off_t d_off; //offset
    unsigned short d_reclen; //파일 이름 길이
    char d_name[NAME_MAX+1]; //파일 이름
}
//inode 번호가 0이면 삭제된 파일

closedir()

기능. opendir() 호출 시 리턴된 DIR에 연관된 디렉토리를 닫습니다.
헤더. #include <dirent.h>
원형. int closedir(DIR* dirstream)
매개변수. DIR* dirstream 오픈된 디렉토리 스트림
리턴값. 정상이면 0, 실패면 -1을 리턴합니다.

기능. 링크 생성
헤더. #include <unistd.h>
원형. int link(const char* oldpath, const char* newpath)
매개변수1. const char* oldpath 존재하는 파일 이름
매개변수2. const char* newpath 만들고자 하는 링크 이름
리턴값. 성공 시 0, 실패 시 -1을 리턴합니다.

기능. 심볼릭 링크 생성
헤더. #include <unistd.h>
원형. int symlink(const char* oldpath, const char* newpath)
매개변수1. const char* oldpath 존재하는 파일 이름
매개변수2. const char* newpath 만들고자 하는 링크 이름
리턴값. 성공 시 0, 실패 시 -1을 리턴합니다.

기능. 링크 삭제
헤더. #include <unistd.h>
원형. int unlink(const char* path)
매개변수. const char* path 삭제하려는 링크 이름
리턴값. 성공 시 0, 실패 시 -1을 리턴합니다.

getcwd()

기능. 현재 작업 디렉토리의 full path명을 null-terminated 문자열로 얻습니다.
헤더. #include <unistd.h>
원형. char* getcwd(char* buf, size_t size)
매개변수1. char* buf 현재 디렉토리의 절대 경로를 저장할 버퍼 주소
매개변수2. size_t size 버퍼의 크기
리턴값. char* 현재 작업 디렉토리명을 얻음
NULL 실패 및 상세 오류 내용은 errno에 저장

chdir()

기능. 현재 작업 디렉토리 변경
헤더. #include <unistd.h>
원형. int chdir(const char* dirname)
매개변수. const char* dirname 변경할 디렉토리의 경로
리턴값. 성공 시 0, 실패 시 -1을 리턴합니다.

mkdir()

기능. 디렉토리 생성
헤더. #include <sys/stat.h>
원형. int mkdir(const char* dirname, mode_t mode)
매개변수1. const char* dirname 생성할 디렉토리명
매개변수2. mode_t mode 접근 권한 지정
리턴값. 성공 시 0, 실패 시 -1을 리턴합니다.
만들려는 폴더가 이미 존재하면 errno는 EEXIST,
폴더가 부정확하면 errno는 ENOENT

rmdir()

기능. 디렉토리 삭제
헤더. #include <unistd.h>
원형. int rmdir(const char* dirname)
매개변수1. const char* dirname 삭제할 디렉토리명
리턴값. 성공 시 0, 실패 시 -1을 리턴합니다.

과제 - 1

dirinfo - 디렉토리 정보 출력

#include <stdio.h>
#include <string.h> //strlen() strcpy()
#include <stdio_ext.h> //__fpurge()
#include <stdlib.h> //malloc() free()
#include <sys/types.h> //stat()
#include <sys/stat.h> //stat()
#include <unistd.h> //getcwd() chdir()
#include <dirent.h> //opendir()

enum { NUM_ERROR = -2, NUM_SUCCESS = 0 };
enum { PATH_CHANGED = 4, PATH_NOT_CHANGED = -4 };
enum { DIR_NOT_OPEN = -5, DIR_NOT_CLOSED = -6, DIR_READ = 9 };
enum { BUF_SIZE = 256 };

void Menu();
void Clear_stdin(char* c);
int NumRangeCheck(int n);
int ChangePath(char* path);
int ReadPath(char* path);

void Menu()
{
	int num = 0;
	char* path = (char*)malloc(BUF_SIZE);
	char current[256];

	do {
		do {
			printf("============================\n");
			printf("현재 작업 디렉토리: %s\n", getcwd(current, 256));
			printf("1) 현재 작업 디렉토리 변경\n");
			printf("2) 디렉토리 정보 출력\n");
			printf("3) 종료\n");
			printf("============================\n");
			printf("select num: ");
			scanf("%d", &num);
			__fpurge(stdin);
		} while(NumRangeCheck(num));

		switch(num) {
			case 1:
				{
					ChangePath(path);
				}
				break;
			case 2:
				{
					ReadPath(path);
				}
				break;
			case 3:
				{
					printf("프로그램을 종료합니다.\n");
					free(path);
				}
				break;
		} //switch
	} while(num != 3); //do while
}

void Clear_stdin(char* c)
{
	if (c == NULL) {
		return;
	}

	if (c[strlen(c) - 1] == '\n') {
		c[strlen(c) - 1] = '\0';
	}
	__fpurge(stdin);
}

int NumRangeCheck(int n)
{
 	if (n != 1 && n != 2 && n != 3) {
		return NUM_ERROR;
	}
	else {
		return NUM_SUCCESS;
	}
}

int ChangePath(char* path)
{
	printf("input path: ");
	fgets(path, BUF_SIZE, stdin);
	Clear_stdin(path);

	if (chdir(path) == -1) {
		printf("디렉토리 변경 실패\n");
		return PATH_NOT_CHANGED;
	}
	else {
		printf("디렉토리 변경 성공\n");
		return PATH_CHANGED;
	}
}

int ReadPath(char* path)
{
	DIR* d = NULL;
	struct dirent* s = NULL;

	if ((d = opendir(path)) == NULL) {
		printf("디렉토리 오픈 실패\n");
		return DIR_NOT_OPEN;
	}
	else {
		printf("디렉토리 오픈 성공\n");
	}

	char file[1000][256];
	int c = 0;

	while ((s = readdir(d)) != NULL) {
		strcpy(file[c], s->d_name);

		struct stat buf;
		stat(file[c], &buf);

		if (S_ISREG(buf.st_mode) != 0) {
			strcat(file[c], "*");
		}
		else if (S_ISDIR(buf.st_mode) != 0) {
			strcat(file[c], "/");
		}
		c++;
	}

	for (int i = 0; i < c; i++) {
		printf("%-40s", file[i]);

		if (i % 5 == 0) {
			printf("\n");
		}
	}

	printf("\n");

	if (closedir(d) == -1) {
		return DIR_NOT_CLOSED;
	}
    
	return DIR_READ;
}

int main()
{
	Menu();
	return 0;
}

0개의 댓글