-
Unix Programming : 명령어 만들기 : 3/3Computer Science/etc 2020. 6. 15. 16:34728x90
3. myls [option] [file]
1) 구현 아이디어 및 설명
- 1번, 2번에서 사용한 함수를 포함하여, 3번 과제에서는 stat 구조체의 이해가 더욱 필요했다. stat 구조체를 보면 다음과 같다.
- 주로 사용한 정보는, st_mode(파일의 퍼미션), st_ino(inode의 번호), st_nlink(하드링크 수), st_uid(user의 id), st_gid(group의 id), st_size(파일의 바이트 수), st_mtime(마지막 수정 시간), st_blocks(할당한 블록의 수)이다.
- 옵션 l 과 n 의 경우, 파일의 퍼미션을 출력하는 부분에 있어서, 기존 명령어의 형태와 동일하게 출력하기 위해 새로운 함수를 만들었다.
- 이 함수는 st_mode값을 이용하여 현재 파일이 어떤 종류의 파일인지, 어떤 권한이 있는지를 파악한 후, 알맞은 문자열 형태로 변환하여 출력한다.
- 또한 기존의 명령어의 형태에서의 시간 부분의 형태와 동일하게 하기 위해 strtime함수를 이용하였다.
2) 프로그램 소스 및 설명문
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <dirent.h> #include <time.h> void permittion(struct stat st); int main(int argc, char* argv[]){ char *cwd; char tmpbuf[BUFSIZ]; // 형식에 맞는 time을 출력하기 위해 DIR *dir=NULL; struct stat st; struct dirent *entry=NULL; int rfd, wfd, n, count=0; // 주석문 작성 순서 : 옵션이 없는 경우 -> 옵션이 있는 경우 cwd=getcwd(NULL, BUFSIZ); // 현재 디렉토리 경로를 cwd에 저장한다 if((dir=opendir(cwd))==NULL) // opendir함수를 통해 cwd 경로에 해당하는 디렉토리를 dir 포인터로 한다 { perror("opendir"); exit(1); } // 옵션이 있는 경우 while((n=getopt(argc, argv, "ails1nm"))!=-1){ switch(n){ case 'm': while((entry=readdir(dir))!=NULL) // dir 포인터에 해당되는 파일을 entry로 하여 순차 접근한다 { count++; stat(entry->d_name, &st); // 현재 파일에 대한 정보를 st에 저장한다 if(S_ISREG(st.st_mode)) // 현재 파일이 일반 파일인 경우 { if(count==2) printf("%s", entry->d_name); // 첫 번째 파일인 경우 파일 이름만 출력한다 else printf(", %s", entry->d_name); // 첫 번째 파일이 아닌 경우 파일 이름 앞에 쉼표를 출력한다 } } printf("\n"); break; case '1': while((entry=readdir(dir))!=NULL) // dir 포인터에 해당되는 파일을 entry로 하여 순차 접근한다 { stat(entry->d_name, &st); // 현재 파일에 대한 정보를 st에 저장한다 if(S_ISREG(st.st_mode)) // 현재 파일이 일반 파일인 경우 printf("%s\n", entry->d_name); // 개행 문자를 포함하여 출력한다 } break; case 'a': while((entry=readdir(dir))!=NULL) // dir 포인터에 해당되는 파일을 entry로 하여 순차 접근한다 printf("%s ", entry->d_name); printf("\n"); break; case 'i': while((entry=readdir(dir))!=NULL) // dir 포인터에 해당되는 파일을 entry로 하여 순차 접근한다 { stat(entry->d_name, &st); // 현재 파일에 대한 정보를 st에 저장한다 if(S_ISREG(st.st_mode)) // 현재 파일이 일반 파일인 경우 printf("%d %s ", (int)entry->d_ino, entry->d_name); // inode와 이름을 함께 출력한다 } printf("\n"); break; case 's': while((entry=readdir(dir))!=NULL) // dir 포인터에 해당되는 파일을 entry로 하여 순차 접근한다 { stat(entry->d_name, &st); // 현재 파일에 대한 정보를 st에 저장한다 if(S_ISREG(st.st_mode)) // 현재 파일이 일반 파일인 경우 count+=(int)st.st_blocks; // 파일의 block 수를 누적합 한다 } printf("total %d\n", count/2); // 누적합을 2로 나누어 출력한다 dir=opendir(cwd); // 현재 디렉토리를 초기화한다 while((entry=readdir(dir))!=NULL){ stat(entry->d_name, &st); if(S_ISREG(st.st_mode)) printf("%d %s ", ((int)st.st_blocks)/2, entry->d_name); // block 수와 이름을 함께 출력한다 } printf("\n"); break; case 'l': while((entry=readdir(dir))!=NULL) // dir 포인터에 해당되는 파일을 entry로 하여 순차 접근한다 { stat(entry->d_name, &st); // 현재 파일에 대한 정보를 st에 저장한다 if(S_ISREG(st.st_mode)) // 현재 파일이 일반 파일인 경우 count+=(int)st.st_blocks; // 파일의 block 수를 누적합 한다 } printf("total %d\n", count/2); // 누적합을 2로 나누어 출력한다 dir=opendir(cwd); // 현재 디렉토리를 초기화한다 while((entry=readdir(dir))!=NULL){ stat(entry->d_name, &st); if(S_ISREG(st.st_mode)){ time_t t; struct tm *tp; t=time(NULL); tp=localtime(&t); // 수정 날짜의 형식에 맞는 출력을 위한 과정이다 permittion(st); // permittion함수를 통해 퍼미션을 출력한다 printf("%o %s %s %5d ", (unsigned int)st.st_nlink, ((int)st.st_uid==501)? "ec2-user" : "unknown-user", ((int)st.st_gid==501)? "ec2-user" : "unknown-user", (int)st.st_size); // 퍼미션, 링크 수, user의 uid, group의 gid, 크기를 출력한다 strftime(tmpbuf, sizeof(tmpbuf), "%b %d %R", tp); printf("%s ", tmpbuf); // 수정 시간을 strftime함수를 이용해, "nov 14 15:59"와 같은 형식으로 출력한다 printf("%s\n", entry->d_name); // 파일 이름을 출력한다 } } break; case 'n': // 옵션 l과 같은 과정이되 uid, gid를 int로 출력한다 while((entry=readdir(dir))!=NULL){ stat(entry->d_name, &st); if(S_ISREG(st.st_mode)) count+=(int)st.st_blocks; } printf("total %d\n", count/2); dir=opendir(cwd); while((entry=readdir(dir))!=NULL){ stat(entry->d_name, &st); if(S_ISREG(st.st_mode)){ time_t t; struct tm *tp; t=time(NULL); tp=localtime(&t); permittion(st); printf("%o %d %d %5d ", (unsigned int)st.st_nlink, (int)st.st_uid, (int)st.st_gid, (int)st.st_size); strftime(tmpbuf, sizeof(tmpbuf), "%b %d %R", tp); printf("%s ", tmpbuf); printf("%s\n", entry->d_name); } } break; } } // 옵션이 없을 경우 if(n==-1 && optind==1) // 옵션이 없고, 옵션의 인덱스의 변화 역시 없다면 다음을 실행한다 { while((entry=readdir(dir))!=NULL) // dir 포인터에 해당하는 파일은 entry로 하여 순차 접근 한다 { stat(entry->d_name, &st); // 현재 파일에 대한 정보를 st에 저장한다 if(S_ISREG(st.st_mode)) // 현재 파일이 일반 파일인 경우 printf("%s ", entry->d_name); // 파일의 이름을 출력한다 } printf("\n"); } closedir(dir); return 0; } // permittion함수는 현재 파일의 정보를 읽고, 현재 파일의 퍼미션을 문자열로 출력하는 함수이다 void permittion(struct stat st){ int kind; // 현재 파일이 어떤 종류인지 확인하기 위해 char* permit = (char*)malloc(sizeof(BUFSIZ)); // 퍼미션의 문자열을 저장하기 위해 kind=st.st_mode & S_IFMT; // 파일의 종류를 정의한 부분을 가져온다 switch(kind){ case S_IFDIR: strcat(permit, "d"); // 디렉토리 파일인 경우 문자열에 d를 추가한다 break; case S_IFREG: strcat(permit, "-"); // 일반 파일인 경우 문자열에 -를 추가한다 break; case S_IFIFO: strcat(permit, "p"); // FIFO 파일인 경우 문자열에 p를 추가한다 break; case S_IFBLK: strcat(permit, "b"); // 블록 장치 특수 파일인 경우 문자열에 b를 추가한다 break; case S_IFCHR: strcat(permit, "c"); // 문자 장치 특수 파일인 경우 문자열에 c를 추가한다 break; } // user, group, other 별로 읽기, 쓰기, 실행에 대한 권한이 있는지 따져본다 if((st.st_mode & S_IRUSR)) strcat(permit, "r"); else strcat(permit, "-"); if((st.st_mode & S_IWUSR)) strcat(permit, "w"); else strcat(permit, "-"); if((st.st_mode & S_IXUSR)) strcat(permit, "x"); else strcat(permit, "-"); if((st.st_mode & S_IRGRP)) strcat(permit, "r"); else strcat(permit, "-"); if((st.st_mode & S_IWGRP)) strcat(permit, "w"); else strcat(permit, "-"); if((st.st_mode & S_IXGRP)) strcat(permit, "x"); else strcat(permit, "-"); if((st.st_mode & S_IROTH)) strcat(permit, "r"); else strcat(permit, "-"); if((st.st_mode & S_IWOTH)) strcat(permit, "w"); else strcat(permit, "-"); if((st.st_mode & S_IXOTH)) strcat(permit, "x"); else strcat(permit, "-"); printf("%s ", permit); // 문자열을 출력한다 free(permit); // 할당 받은 메모리를 해제한다 }
3) 기본 기능
4) 옵션 기능
(1) -a : 경로 안의 모든 파일을 나열한다.
(2) -i : 파일 왼쪽에 inode를 보여준다.
(3) -l : 파일을 나열할 때, 파일 형태, 사용권한, 하드링크 번호, user 이름, group 이름, 파일 크기, 최종 변경 시간, 파일 이름을 보여준다.
(4) -1 : 한 줄에 한 파일씩 나열한다.
(5) -m : 쉼표로 구분하여 출력한다.
(6) -s : 파일 크기를 1KB 단위로 표시한다. (number of file system block)
(7) -n : l 옵션과 같고, UID, GID를 표시한다.
728x90'Computer Science > etc' 카테고리의 다른 글
CS : REST API (0) 2021.04.11 CS : COCO Dataset (0) 2021.04.09 Unix Programming : 명령어 만들기 : 2/3 (0) 2020.06.15 Unix Programming : 명령어 만들기 : 1/3 (0) 2020.06.15 ProgrammingLanguages : Question : 2 (0) 2020.06.15