diff --git a/getcwd.c b/getcwd.c new file mode 100644 index 0000000..11c73be --- /dev/null +++ b/getcwd.c @@ -0,0 +1,145 @@ +#define __LIBRARY__ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define BUF_MAX 128 +#define DIRBUF 8192 +#define NAME_MAX 14 + +struct dirent { /* Ŀ¼��ṹ�� */ + long d_ino; /* i�ڵ� */ + off_t d_off; /* λ�� */ + unsigned short d_reclen; /* �ļ������� */ + char d_name[NAME_MAX + 1]; /* �ļ��� */ +}; + +typedef struct +{ + int dd_fd; /* �ļ������� */ + int dd_loc; /* ����ƫ�� */ + int dd_size; /* ��Ч���ݴ�С */ + char* dd_buf; /* -> directory block */ +} DIR; /* Ŀ¼�� */ + +struct direct { + ino_t d_ino; + char d_name[NAME_MAX]; +}; + +static struct dirent result; + +_syscall3(int, read, int, fildes, char*, buf, off_t, count) +_syscall2(int, fstat, int, fildes, struct stat*, stat_buf) +_syscall2(int, stat, const char*, filename, struct stat*, stat_buf) +_syscall1(int, chdir, const char*, filename) + +struct dirent* readdir(DIR* dir) /* ���ز���dirĿ¼�����¸�Ŀ¼����� */ +{ /* ��ȡ��Ŀ¼��Ϣ�����ptrָ���Ŀ¼�ṹ���У�ֻ��i�ڵ��Ŀ¼�� */ + struct direct* ptr; /* ��ȡ��ǰĿ¼��ͬʱ��ȡ���¸�Ŀ¼����Ϣ�������result�� */ + /* ����ĩβ���������NULL */ + if (!dir) { + errno = EBADF; + return NULL; + } + if (!dir->dd_buf) + if (!(dir->dd_buf = malloc(DIRBUF))) + return NULL; + else + dir->dd_size = dir->dd_loc = 0; + while (1) { + if (dir->dd_size <= dir->dd_loc) { + dir->dd_loc = 0; + dir->dd_size = read(dir->dd_fd, dir->dd_buf, DIRBUF); + } + if (dir->dd_size <= 0) + return NULL; + ptr = (struct direct*)(dir->dd_loc + dir->dd_buf); + dir->dd_loc += sizeof(*ptr); + if (!ptr->d_ino) + continue; + result.d_ino = ptr->d_ino; + strncpy(result.d_name, ptr->d_name, NAME_MAX); + result.d_name[NAME_MAX] = 0; + result.d_reclen = strlen(result.d_name); + return &result; + } +} + +int closedir(DIR* dir) /* �رղ���dir��ָ���Ŀ¼�� */ +{ + int fd; + + if (!dir) { + errno = EBADF; + return -1; + } + fd = dir->dd_fd; + free(dir->dd_buf); + free(dir); + return close(fd); +} + +DIR* opendir(const char* dirname) /* �򿪲���dirnameָ����Ŀ¼��������DIR��̬��Ŀ¼����ʧ�ܷ���NULL */ +{ + int fd; + struct stat stat_buf; + DIR* ptr; + + if ((fd = open(dirname, O_RDONLY)) < 0) /* ִ��ϵͳ����read����ȡ�ļ������� */ + return NULL; + if (fstat(fd, &stat_buf) < 0 || /* ִ��ϵͳ����fstat��ͨ���ļ���������ȡ�ļ�״̬��Ϣ�����뻺����stat_buf */ + !S_ISDIR(stat_buf.st_mode) || + !(ptr = malloc(sizeof(*ptr)))) { + close(fd); + return NULL; + } + memset(ptr, 0, sizeof(*ptr)); + ptr->dd_fd = fd; + return ptr; +} + +char* sys_getcwd(char* buf, size_t size) { + char through_name[BUF_MAX], cwd[BUF_MAX]; + DIR* pre_fstream; + struct dirent* through_stream; + struct stat current_direct_state, through_state, pre_direct_state; + dev_t current_direct_dev; + ino_t current_direct_inum; + + while (1) { + if (stat(".", ¤t_direct_state == 0)) { /* ��ȡ��ǰĿ¼���ļ�״̬��Ϣ */ + current_direct_dev = current_direct_state.st_dev; + current_direct_inum = current_direct_state.st_ino; + } + + pre_fstream = opendir(".."); /* ��ȡ��ǰĿ¼�ĸ�Ŀ¼���ļ��� */ + stat("..", &pre_direct_state); /* ��ȡ��ǰĿ¼�ĸ�Ŀ¼���ļ���Ϣ */ + if (pre_direct_state.st_dev == current_direct_dev && pre_direct_state.st_ino == current_direct_inum) + break; /* �����Ŀ¼�͵�ǰĿ¼��ͬ��˵���Ѿ����˸�Ŀ¼����ʱ�˳�ѭ�� */ + + while ((through_stream = readdir(pre_fstream)) != NULL) { /* ������Ŀ¼�µ�Ŀ¼�����ƥ�� */ + memcpy(through_name, through_stream->d_name, BUF_MAX); /* �������Ŀ¼������֣�����ʹ��stat������ȡ��״̬��Ϣ */ + stat(through_name, &through_state); /* �������Ŀ¼���״̬��Ϣ������ƥ�� */ + + if (current_direct_dev == through_state.st_dev && current_direct_inum == through_state.st_ino) { + memset(cwd, 0, sizeof(cwd)); /* ƥ�䵽�˵�ǰĿ¼����������׷�ӵ�cwd�� */ + strcat(cwd, "/"); + strcat(cwd, through_stream->d_name); + strcat(cwd, buf); /* buf��¼������һ��ѭ����cwd������׷�Ӹ���ǰѭ����cwd */ + strncpy(buf, cwd, BUF_MAX); /* ��cwd������buf */ + break; + } + } + closedir(pre_fstream); + chdir(".."); /* �ı䵱ǰĿ¼Ϊ�丸Ŀ¼ */ + } + return buf; +} \ No newline at end of file