1. 程式人生 > >20155227 實現mypwd

20155227 實現mypwd

clu 所有 一級目錄 into type std dpt mark unistd.h

20155227 實現mypwd

1 學習pwd命令
2 研究pwd實現需要的系統調用(man -k; grep),寫出偽代碼
3 實現mypwd
4 測試mypwd

課堂學習筆記

技術分享圖片

技術分享圖片

實現mypwd

在linux 中的文件系統中,文件=N(N>=1)個inode +M(M>=1)個數據塊

數據塊,存放文件的內容數據,數據塊的數目根據文件內容的大小而定。

i-node稱為信息節點,作用有:

1、存儲跟文件相關的屬性信息,如修改時間、所有者、文件類型和文
2、存儲指向文件內容數據塊的指針信息。

技術分享圖片

在一個文件系統中,一個inode代表一個文件,並使用一個整數值來標誌該inode,稱為inode-number,該值對於一個文件系統而言是唯一的,即通過該值可以找到其對應的inode

。一般情況下,一個文件只有一個inode信息用來描述它。
技術分享圖片

目錄,在linux中,其實也是一種文件,所以它也是由“inode+數據塊”構成的。而其文件內容是一個列表,每一個列表項記錄“inode-number+filename"

因此,我們通常所說的目錄a"包含"文件b,其實現層面上的意思是,目錄a的內容列表裏有一個關於文件b的列表項,即“b的inode-number+ b的filename”

綜上,linux中,一個文件(包括目錄)的文件名,及文件名與inode的對應關系,都是由包含該文件的目錄所描述的。

其中,有兩個特殊的文件名“.” 和 “..”,“.”代表當前目錄自身,".."代表包含當前目錄的上一級目錄。

結構體stat:

struct stat {
    dev_t         st_dev;       //文件的設備編號
    ino_t         st_ino;       //節點
    mode_t        st_mode;      //文件的類型和存取的權限
    nlink_t       st_nlink;     //連到該文件的硬連接數目,剛建立的文件值為1
    uid_t         st_uid;       //用戶ID
    gid_t         st_gid;       //組ID
    dev_t         st_rdev;      //(設備類型)若此文件為設備文件,則為其設備編號
    off_t         st_size;      //文件字節數(文件大小)
    unsigned long st_blksize;   //塊大小(文件系統的I/O 緩沖區大小)
    unsigned long st_blocks;    //塊數
    time_t        st_atime;     //最後一次訪問時間
    time_t        st_mtime;     //最後一次修改時間
    time_t        st_ctime;     //最後一次改變時間(指屬性)
};

dirent結構體:

struct dirent
{
    long d_ino; //inode number 索引節點號
    off_t d_off; //offset to this dirent 在目錄文件中的偏移
    unsigned short d_reclen;// length of this d_name 文件名長
    unsigned char d_type; //the type of d_name 文件類型 
    char d_name [NAME_MAX+1]; //file name (null-terminated) 文件名,最長255字符
};

DIR結構體:

struct __dirstream
{
    void *__fd; // `struct hurd_fd‘ pointer for descriptor.
    char *__data; // Directory block.
    int __entry_data; // Entry number `__data‘ corresponds to.
    char *__ptr; // Current pointer into the block.
    int __entry_ptr; // Entry number `__ptr‘ corresponds to.
    size_t __allocation;// Space allocated for the block.
    size_t __size; // Total valid data in the block.
    __libc_lock_define (, __lock) // Mutex lock for this structure.
};
typedef struct __dirstream DIR;

mypwd.c:

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <unistd.h>

#define MAX_DIR_DEPTH (256) 
#define TRUE 1
#define FALSE 0


ino_t get_ino_byname(char *filename)
{
    struct stat file_stat;
    if(0 != stat(filename, &file_stat))
    {
        perror("stat");
        exit(-1);
    }

    return file_stat.st_ino;
}

char *find_name_byino(ino_t ino)
{
    DIR *dp = NULL;
    struct dirent *dptr = NULL;
    char *filename = NULL;
    
    if(NULL == (dp = opendir(".")))
    {
        fprintf(stderr, "Can not open Current Directory\n");
        exit(-1);
    }
    else
    {
        while(NULL != (dptr = readdir(dp)))
        {
            if(dptr->d_ino == ino)
            {
                filename = strdup(dptr->d_name);
                break;
            }
        }

        closedir(dp);
    }

    return filename;
}

int main(int argc, char *argv[])
{
    
    char *dir_stack[MAX_DIR_DEPTH];
    unsigned current_depth = 0;

    while(TRUE)
    {
        ino_t current_ino = get_ino_byname("."); 
        ino_t parent_ino = get_ino_byname(".."); 

        if(current_ino == parent_ino)
            break;                      /*兩個inode-number不一樣*/
        chdir(".."); 
        dir_stack[current_depth++] = find_name_byino(current_ino); 
        if(current_depth >= MAX_DIR_DEPTH)      {
            fprintf(stderr, "Directory tree is too deep.\n");
            exit(-1);
        }
    }

    int i = current_depth - 1;
    for(i = current_depth - 1; i >= 0; i--) 
    {
        fprintf(stdout, "/%s", dir_stack[i]);
    }
    fprintf(stdout, "%s\n", current_depth == 0 ? "/" : "");


    return 0;
}

運行截圖

技術分享圖片

20155227 實現mypwd