What is the 0x00 pwd command?
pwd is used to display the path to the current directory.
How does the 0x01 pwd command work?
We know that a directory contains two special directories. and.. Representing the current directory and the previous directory, respectively.We can first find the inode node number of.And then go back to the previous directory and get the name of that directory from the inode node number.
When does the recursion end?You've certainly reached the top of the catalog tree.When you reach the top of the tree, the inode number of.And..Is the same.
Introduction of 0x02 using functions
Our main operations here are
0x0201 Catalog Open
Header file required
#include <sys/types.h> #include <dirent.h>
Format of function
DIR *opendir(const char *name);
name points to the directory we need to open and returns a DIR structure pointer (which can be interpreted as a Directory Descriptor).
Read operation of 0x0202 directory
Header file required
#include <dirent.h>
Format of function
struct dirent *readdir(DIR *dirp);
The dirp points to our directory descriptor and returns a dirent structure.
struct dirent { ino_t d_ino; /* Inode number */ off_t d_off; /* Not an offset; see below */ unsigned short d_reclen; /* Length of this record */ unsigned char d_type; /* Type of file; not supported by all filesystem types */ char d_name[256]; /* Null-terminated filename */ };
We can get the file information in the directory by d_name.
Close operation of 0x0203 directory
Required header file
#include <sys/types.h> #include <dirent.h>
Function Prototype
int closedir(DIR *dirp);
dirp points to our directory descriptor and an error returns -1 during shutdown.
0x0204 Get File Information
Required header file
#include <sys/types.h> #include <sys/stat.h> #include <unistd.h>
Function Prototype
int stat(const char *pathname, struct stat *statbuf);
The pathname points to the file we need to get, and the stat is a structure that contains the file information.
struct stat { dev_t st_dev; /* ID of device containing file */ ino_t st_ino; /* Inode number */ mode_t st_mode; /* File type and mode */ nlink_t st_nlink; /* Number of hard links */ uid_t st_uid; /* User ID of owner */ gid_t st_gid; /* Group ID of owner */ dev_t st_rdev; /* Device ID (if special file) */ off_t st_size; /* Total size, in bytes */ blksize_t st_blksize; /* Block size for filesystem I/O */ blkcnt_t st_blocks; /* Number of 512B blocks allocated */ /* Since Linux 2.6, the kernel supports nanosecond precision for the following timestamp fields. For the details before Linux 2.6, see NOTES. */ struct timespec st_atim; /* Time of last access */ struct timespec st_mtim; /* Time of last modification */ struct timespec st_ctim; /* Time of last status change */ #define st_atime st_atim.tv_sec /* Backward compatibility */ #define st_mtime st_mtim.tv_sec #define st_ctime st_ctim.tv_sec };
Return-1 if there is an error getting information.
0x0205 Change directory location
Required header file
#include <unistd.h>
Function Prototype
int chdir(const char *path);
path points to the directory location we need to change.
0x03 Write a pwd
0x0301 First Edition
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <dirent.h> #include <string.h> #include <unistd.h> void printpathto(ino_t); void inum_to_name(ino_t inode_to_find, char *namebuf, int buflen); ino_t get_inode(char *filename); void printpathto(ino_t this_inode) { ino_t my_inode; char its_name[BUFSIZ]; if (get_inode("..") != this_inode) { chdir(".."); inum_to_name(this_inode, its_name, BUFSIZ); my_inode = get_inode("."); printpathto(my_inode); printf("/%s", its_name); } } void inum_to_name(ino_t inode_to_find, char *namebuf, int buflen) { DIR *dir_ptr; struct dirent *direntp; dir_ptr = opendir("."); if (dir_ptr == NULL) { perror("."); exit(1); } while ((direntp = readdir(dir_ptr)) != NULL) { if (direntp->d_ino == inode_to_find) { strncpy(namebuf, direntp->d_name, buflen); namebuf[buflen - 1] = '\0'; closedir(dir_ptr); return; } } fprintf(stderr, "error looking for inum %ld\n", inode_to_find); exit(1); } ino_t get_inode(char *filename) { struct stat info; if (stat(filename, &info) == -1) { fprintf(stderr, "Cannot stat"); perror(filename); exit(1); } return info.st_ino; } int main() { printpathto(get_inode(".")); putchar('\n'); return 0; }
Let's see the difference between our version and the actual version
The functionality is fine, but we did not recurse to the home directory.Is it a code problem?No, because unix allows storage on a disk to consist of multiple trees, with one directory tree per disk or partition on each disk.
I added a different language version of the problem to my GitHub Linux
If there are any questions, I hope you can point out!!!