Linux高级环境编程之5磁盘文件属性管理

课程目标

  1. 编程目标:
    (a)实现ls –l全部功能。
    (b)实现tree工具全部功能。
  2. 理解文件系统对磁盘文件的管理策略。
  3. 掌握文件属性获取与修改的API应用。
  4. 特殊文件的基本信息。

主要知识点

  1. VFS文件系统以及ext2/3/4文件系统结构。
  2. 文件信息存储inode以及文件类型,文件属性的获取。
  3. 文件属性的获取与修改。
  4. 编程应用。

1—Linux一切都是文件及文件系统

  • 一切皆文件的概念
    Linux一切皆为文件的思想是基于虚拟文件系统(Virtual File System,VFS)实现。把底层的硬件实现全部隐藏,用户操作普通文件或者其它的硬件设备,都基于文件系统的方式,即基本上都可以使用open/read/write/close这些文件操作的系统调用来访问。便于应用层的程序开发。
  • Linux下根据设备的属性将文件分为7类:
文件类型 类别 标识符
普通文件 磁盘文件 -
目录文件 磁盘文件 d
链接文件 磁盘文件 l
字符设备文件 设备文件 c
块设备文件 设备文件 b
管道文件 进程通信文件 p
socket文件 网络通信文件 s
  • 磁盘文件系统怎么来管理文件?

    struct inode结构体存储了文件的**基本属性,这个属性在内核中定义。
    在终端中输入man 2 stat查看stat相关信息:
       #include <sys/types.h>
       #include <sys/stat.h>
       #include <unistd.h>

       int stat(const char *path, struct stat *buf);
       int fstat(int fd, struct stat *buf);
       int lstat(const char *path, struct stat *buf);
以上三个函数可以获取某个文件的详细的属性,
可以通过 strut stat结构体查看

           struct stat {
               dev_t     st_dev;     /* ID of device containing file */
               ino_t     st_ino;     /* inode number */  文件在当前文件系统下的唯一编号
               mode_t    st_mode;    /* protection */ 存放的是文件的类型以及权限
               nlink_t   st_nlink;   /* number of hard links */ 硬链接个数
               uid_t     st_uid;     /* user ID of owner */ 拥有者ID
               gid_t     st_gid;     /* group ID of owner */ 拥有组ID
               dev_t     st_rdev;    /* device ID (if special file) */
               off_t     st_size;    /* total size, in bytes */ 文件的大小
               blksize_t st_blksize; /* blocksize for file system I/O */ 块的大小
               blkcnt_t  st_blocks;  /* number of 512B blocks allocated */ 块的个数
               time_t    st_atime;   /* time of last access */ 最近访问时间
               time_t    st_mtime;   /* time of last modification */ 最近修改熟悉的时间
               time_t    st_ctime;   /* time of last status change */ 最近修改内容的时间
           };

查看文件编号ls -li

2—文件类型及文件模式

mode_t st_mode; /* protection */ 存放的是文件的类型以及权限

3个bit的权限修饰位
  • setuid位
  • setgid位
    以上两个bit被设置后,相应的执行这个文件时,会提升它的执行权限
    /usr/bin/passwd可执行文件为例。用户的密码存储在/etc/passwd/shadow文件中:
delphi@delphi-vm:~/code/test$ ll /etc/shadow
-rw-r----- 1 root shadow 1010 2014-08-26 21:53 /etc/shadow

从以上可以看出,普通用户对这个文件没有写的权限,因此,如果用vi编辑器修改肯定是不可以的。但是,普通用户可以使用passwd这个命令来修改自己的密码,也就是修改了/etc/shadow这个文件。原因时/usr/bin/passwd这个可执行文件被设置了setuid

delphi@delphi-vm:~/code/test$ ll /usr/bin/passwd
-rwsr-xr-x 1 root root 37100 2011-02-15 06:12 /usr/bin/passwd*

当普通用户执行这个程序时,因为设置了setuid位,相应的这个进程对文件的访问权限上升到该可执行文件拥有者的权限,在这个地方就是普通用户执行时,对文件的读写的权限被提升为这个文件的拥有者root的权限,而root用户对/etc/shadow文件有写的权限,因此,可以修改密码成功。

  • 粘贴位:在早期计算机,如果一个可执行文件被设置此位,期望这个可执行文件常驻内存,提高运行的速率

3—磁盘文件属性读取与修改编程

1. 权限的修改

man 2 chmod

       #include <sys/stat.h>

       int chmod(const char *path, mode_t mode);
       int fchmod(int fd, mode_t mode);

man 2 umask

mode_t umask(mode_t mask);//修改和获取当前的umask值。默认0022

源码中对于权限的宏定义

#define S_IRWXU 00700      //拥有者读写执行的权限
#define S_IRUSR 00400       //拥有者读的权限
#define S_IWUSR 00200      //拥有者写的权限
#define S_IXUSR 00100       //拥有者执行的权限

#define S_IRWXG 00070
#define S_IRGRP 00040
#define S_IWGRP 00020
#define S_IXGRP 00010

#define S_IRWXO 00007
#define S_IROTH 00004
#define S_IWOTH 00002
#define S_IXOTH 00001

新创建的文件的权限
如果使用以下权限新创建文件

S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH
(octal 0666) when creating a new file, the permissions on the resultingfile will be:
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
(because 0666 & ~022 = 0644; i.e., rw-r--r--).

最终这个文件的权限:0666& ~022 = 0644,而~022就是umask值

  • 默认新创建文件的权限:0666&~umask
  • 默认新创建的目录的权限:0777&~umask

2.用户的信息

uid_t     st_uid;     /* user ID of owner */ 拥有者ID
gid_t     st_gid;     /* group ID of owner */ 拥有组ID

/etc/passwd存储的是用户的ID以及相关信息。
/etc/group存储的是组的ID以及相关信息。
通过 stat返回的是用户的ID,要获取它的用户名,实际是读取对应的文件。

       #include <sys/types.h>
       #include <pwd.h>

       struct passwd *getpwnam(const char *name);
       struct passwd *getpwuid(uid_t uid);

返回的是一个struct passwd指针:
           struct passwd {
               char   *pw_name;       /* username */
               char   *pw_passwd;     /* user password */
               uid_t   pw_uid;        /* user ID */
               gid_t   pw_gid;        /* group ID */
               char   *pw_gecos;      /* real name */
               char   *pw_dir;        /* home directory */
               char   *pw_shell;      /* shell program */
           };
       #include <sys/types.h>
       #include <grp.h>

       struct group *getgrnam(const char *name);
       struct group *getgrgid(gid_t gid);
返回一个 struct group指针:
           struct group {
               char   *gr_name;       /* group name */
               char   *gr_passwd;     /* group password */
               gid_t   gr_gid;        /* group ID */
               char  **gr_mem;        /* group members */
           };

3. 相关时间

struct stat中时间分为以下三种:

time_t    st_atime;   /* time of last access */ 最近访问时间
time_t    st_mtime;   /* time of last modification */ 最近修改熟悉的时间
time_t    st_ctime;   /* time of last status change */ 最近修改内容的时间

查找man 2 utime

#include <sys/types.h>
#include <utime.h>

int utime(const char *filename, const struct utimbuf *times);

struct utimbuf {
     time_t actime;       /* access time */
     time_t modtime;      /* modification time */
};

struct timeval {
     long tv_sec;        /* seconds */
     long tv_usec;       /* microseconds */
};

4. 文件大小

文件的大小:可以把一个文件截短或扩展

  • 截断:truncate
       #include <unistd.h>
       #include <sys/types.h>

       int truncate(const char *path, off_t length);
       int ftruncate(int fd, off_t length);

如果length小于当前文件大小,截短;如果大于,依赖于系统,有些系统会扩展。

5. 链接问题

  • 硬链接:用ln -d来创建,实际上时增加某个为你教案的属性中硬链接数值。
    编程中用link()函数实现
创建硬链接
NAME
       link - make a new name for a file (为文件创建一个新名字即为硬链接)

SYNOPSIS
       #include <unistd.h>

       int link(const char *oldpath, const char *newpath);

========================
删除硬链接
NAME
       unlink - delete a name and possibly the file it refers to

SYNOPSIS
       #include <unistd.h>

       int unlink(const char *pathname);
仅仅是将某个文件的硬链接数自动减1,
有时候用来删除文件是因为文件没有
创建硬链接时,硬链接数为1,而减去1
变为0,从而删除文件。
  • 符号链接:类似于windows的快解方式类似,创建了一个新文件,只是不分配新数据空间,符号链接文件的大小为源文件路径字符串长度
    在控制台中创建符号链接:
delphi@delphi-vm:~/code/test$ ln -s copy copy.lk
delphi@delphi-vm:~/code/test$ ll copy copy.lk
-rwxrw-r-- 1 delphi delphi 1000 2018-08-07 12:20 copy*
lrwxrwxrwx 1 delphi delphi    4 2018-08-07 15:36 copy.lk -> copy*

在编程中创建符号链接:

创建符号链接:
NAME
       symlink - make a new name for a file

SYNOPSIS
       #include <unistd.h>

       int symlink(const char *oldpath, const char *newpath);

读取符号链接:
NAME
       readlink - read value of a symbolic link

SYNOPSIS
       #include <unistd.h>

       ssize_t readlink(const char *path, char *buf, size_t bufsiz);
默认情况下,读取符号链接的内容和属性时得到源文件的信息,
因此,针对符号链接有专门的函数:
stat ==> lstat
chmod ==> lchmod

6. 编程实现ls -l

  1. 参数列表问题
    ls -l后面可以跟一个或者多个文件和目录。要解决这个问题可以使用命令行参数解析的工具getopt/getopt_long
    另外,遍历非-l其他参数,有可能是目录,有可能是文件,是目录则读取目录下所有的子文件及子目录信息;如果是普通文件,列出文件信息;如果没有指定参数,则列出当前目录下的文件信息。
    怎么来判断文件是文件还是目录呢?**lstat()函数能够获取给定的路径类型。

  2. 信息的问题

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,635评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,628评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,971评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,986评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,006评论 6 394
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,784评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,475评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,364评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,860评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,008评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,152评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,829评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,490评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,035评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,156评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,428评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,127评论 2 356

推荐阅读更多精彩内容