How do I program pwd commands on Linux?

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!!!

Keywords: Programming Linux Unix github

Added by defx on Sun, 12 May 2019 11:09:45 +0300