/* * getcwdʵ��˼·������֮ǰ����ʵѵ��дһ���Լ���ls * ��ʱ������c�⺯���е�opendir,readdir��closedir���� * ���Ծ�ȥc���������������������Ӧ�Ľṹ����˹��� * ���⣬�ٽ����ϵͳ���ú���read,fstat,stat��chdir * ��������������ʵ�������ͱȽϼ��� */ #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) /* open�����ļ����������ļ� */ _syscall2(int, fstat, int, fildes, struct stat*, stat_buf) /* fstat�����ļ���������ȡ�ļ�״̬��Ϣ������statָ��Ľṹ�� */ _syscall2(int, stat, const char*, filename, struct stat*, stat_buf) /* stat�����ļ�����ȡ�ļ�״̬��Ϣ������statָ��Ľṹ�� */ _syscall1(int, chdir, const char*, filename) /* chdir�л���filename����Ŀ¼ */ /* ������������������c���е�ʵ�� */ 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; } /* ʵ��getcwd */ 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; }