본문 바로가기
운영체제/xv6

xv6 Lab: Utilities (4) find

by JaeminRyu 2022. 9. 2.
728x90

이 문제는 MIT의 xv6 수업에 출처가 있습니다.

Write a simple version of the UNIX find program: find all the files in a directory tree with a specific name. Your solution should be in the file user/find.c

find <path> <target> 명령어를 구현하는 문제이다.

find 명령어를 실행하면 path의 디렉토리에 들어있는 모든 파일(디렉토리 포함)을 검사하여 target과 동일한 이름을 가진 파일의 경로를 모두 출력한다.

 

사전 지식)

구조체 dirent

struct dirent{
    long d_ino; //inode 번호
    off_t d_off; //offset
    unsigned short d_reclen; //d_name 길이
    char d_name[NAME_MAX+1]; //파일 이름
};

디렉토리를 나타내는 구조체이다.

 

구조체 stat

//stat.h

#define T_DIR	1	//Directory
#define T_FILE	2	//File
#define T_DEVICE 3	//Device

struct stat {
	int dev;	//File system''s disk device
    uint ino;	//Inode number
    short type;	//Type of file
    short nlink; //Number of links to file
    uint64 size; //Size of file in bytes
}

파일의 상태를 나타내는 구조체이다.

이를 이용하여 해당 파일이 디렉토리인지를 판별할 것이다.

 

xv6는 디렉토리또한 파일로 취급하여 readdir함수가 아닌 read함수로 읽는다.

 

Solution

#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.h"
#include "kernel/fcntl.h"

//경로를 제외한 파일명 리턴, ls.c에서 가져옴
char* fmtname(char *path){
	char *p;
    // 맨 마지막 슬래쉬로
    for(p = path+strlen(path); p >= path && *p != '/'; p--)
    	;
  	//슬래쉬 다음으로 이동
	p++;
    
    return p;
}

void find(char *path, char *target){
	char buf[64];
    char *p;
    int fd;
    struct dirent dir;
    struct stat st;
    
    //target 문자열과 파일명이 같으면 출력
    if(!strcmp(fmtname(path),target)){
    	printf("%s\n",path);
    }
    
    fd = open(path,0)	//파일 읽기 전용 오픈
    fstat(fd,&st);		//파일 상태 확인
    
    //파일이 디렉토리가 아닐 경우
    if(st.type != T_DIR){
    	close(fd);
        return;
    }
    
    //buf에 path+/
    strcpy(buf,path);
    p = buf+strlen(buf);
    *p++ = '/';
    
    while(read(fd,&dir,sizeof(dir))){
    	if(dir.inum == 0){
        	continue;
        }
        
        //p 뒤에 파일 이름 붙이기
        memmove(p, dir.name, DIRSIZ);
        p[DIRSIZ] = 0;
        
        //파일명 .이거나 ..일 때 예외처리
        if(!strcmp(dir.name,".") || !strcmp(dir.name,"..")){
        	continue;
       	}
        find(buf,target);
    }
    close(fd);
}

int main(int argc, char *argv[]){
	if(argc <= 2){
    	printf("Usage: find <path> <filename>\n");
        exit(1);
    }
	
    find(argv[1],argv[2]);
    exit(0);
}

 

'운영체제 > xv6' 카테고리의 다른 글

xv6 Lab: Utilities (5) xargs  (0) 2022.09.03
xv6 Lab: Utilities (3) primes  (0) 2022.09.01
xv6 Lab: Utilities (2) pingpong  (0) 2022.08.31
xv6 Lab: Utilities (1) sleep  (0) 2022.08.31