首页 > 其他 > 详细

文件和目录

时间:2019-06-18 09:26:00      阅读:108      评论:0      收藏:0      [点我收藏+]

  遍历目录下的文件时要用lstat而不能用stat

#include <sys/stat.h>

int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);//丢弃跟随属性,只针对符号链接本身,不针对符号链接对应的文件
int fstatat(int fd,const char *path, struct stat *buf,int flag);
//当flag被设置为AT_SYMLINK_NOFOLLOW时,fstatat不跟随符号链接,只返回符号链接本身的信息
//fd为AT_FDCWD时,fstatat会计算针对当前目录的path参数
//以上函数成功返回0失败返回-1

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 */
    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; /* 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 */
};

文件类型

  1. 普通文件:在 UNIX/Linux 系统中通常所见到的文件,一个文件包括两部分数据,一部分是元数据,如文件的类型、权限、大小、用户、组、各种时间戳等,存储在 i 节点中,另一部分是内容数据,存储在数据块中。对于数据是文本数据还是二进制数据无区别(例外:二进制可执行文件,为了执行程序,内核必须理解其格式,这种格式确定程序文本和数据加载的位置)。
  2. 目录文件:系统通过 i 节点唯一地标识一个文件的存在,但人们更愿意使用有意义的文件名来访问文件,目录就是用来建立文件名和 i 节点之间的映射的。目录的本质就是一个普通文件,与其它普通文件唯一的区别就是它仅仅存储文件名和 i 节点号的映射,每一个这样的映射,用目录中的一个条目表示,谓之硬链接
  3. 块特殊文件:这种类型的文件提供对设备(如磁盘)带缓冲的访问,每次访问以固定长度为单位进行。
  4. 字符特殊文件:这种类型的文件提供对设备不带缓冲的访问,每次访问长度可变。系统中的所有设备要么是字符特殊文件,要么是块特殊文件。
  5. FIFO:这种类型的文件用于进程间通信,有时也称为命名管道。
  6. 套接字:这种类型的文件用于进程间的网络通信。套接字也可用于一台宿主机上进程之间的非网络通信。
  7. 符号链接:这种类型的文件指向另一个文件。
//文本信息包含在st_mode中,以下宏确定st_mode成员类型
S_ISREG(m)  is it a regular file  (普通文件)
S_ISDIR(m)  directory  (目录文件)
S_ISCHR(m)  character device  (字符特殊文件)
S_ISBLK(m)  block device  (块特殊文件)
S_ISFIFO(m) FIFO (named pipe)  (管道或 FIFO)
S_ISLNK(m)  symbolic link (符号链接)(Not in POSIX.1-1996.)
S_ISSOCK(m) socket (套接字)(Not in POSIX.1-1996.)

  也可从stat结构体中确定IPC对象类型,他们的参数并非st_mode,而是指向stat结构体指针

S_TYPEISMQ()//消息队列
S_TYPEISSEM()//信号量
S_TYPEISSHM()//共享存储对象

设置用户ID和设置组ID

与一个进程关联的ID有6个或更多,如下图所示:

实际用户ID

实际组ID

我们实际是谁

有效用户ID

有效组ID

附加组ID

用于文件访问权限检索

保存的设置用户ID

保存的设置组ID

由exec函数保存
  1. 实际用户ID和实际组ID标识我们究竟是谁,这两个字段在登录时取自口令文件中的登录项。通常,在一个登录会话间这些值并不改变,但是超级用户进程有方法改变它们。
  2. 有效用户ID,有效组ID以及附加组ID决定了我们的文件访问权限。
  3. 保存的设置的用户ID和保存的设置组ID在执行一个程序时包含了有效用户ID和有效组ID的副本。

st_uid和st_gid

  通常,有效用户ID等于实际用户ID,有效组ID等于实际组ID。

  每个文件都有一个所有者和组所有者,所有者由stat结构中的st_uid成员表示,组所有者则由st_gid成员表示——只针对可执行文件有效

  当执行一个程序文件时,进程的有效用户ID通常就是实际用户ID,有效组ID通常是实际组ID。但是可以在文件模式字中设置一个特殊标志,其含义是“当执行此文件时,将进程的有效用户ID设置为文件所有者的用户ID(st_uid)”。与此类似,在文件模式字中可以设置另一位,它使得将执行此文件的进程的有效组ID设置为文件的组所有者(st_gid)。在文件模式字中的这两位被称为设置用户ID(set_user-ID)位和设置组ID(set-group-ID)位。

  例如,若文件所有者是超级用户,而且设置了该文件的设置用户ID位,然后当该程序由一个进程执行时,则该进程具有超级用户特权。不管执行此文件的进程的实际用户ID是什么,都进行这样的处理。例如,UNIX程序password允许任一用户改变其口令,该程序是一个设置用户ID程序。因为该程序应能将用户的新口令写入口令文件中,而只有超级用户才具有对该文件的写权限,所以需要使用设置用户ID特征。因为运行设置用户ID程序的进程通常得到额外的权限,所以编写这样程序时要特别谨慎。

  再返回到stat函数,设置用户ID位及设置组ID位都包含在st_mode值中。这两位可用常量S_ISUID和S_ISGID测试。

文件访问权限

  stat 结构的st_mode 值中包含了针对文件的访问权限位。所有文件类型都具有访问权限。每个文件有 9 个访问权限位

 

st_mode 屏蔽 意义
S_IRUSR 用户 -读
S_IWUSR 用户 -写
S_IXUSR 用户 -执行
S_IRGRP 组 -读
S_IWGRP 组 -写
S_IXGRP 组 -执行
S_IROTH 其他 -读
S_IWOTH 其他 -写
S_IXOTH 其他 -执行

  1. 用名字打开任一类型的文件时,对该名字中包含的每一个目录,包括它可能隐含的当前工作目录都应具有执行权限,这就是对目录的执行权限称为搜索位。例如,为了打开文件/usr/include/stdio.h,需要对目录/、/usr 和/usr/include具有执行权限。然后,需要具有对该文件本身的适当权限。如果当前工作目录是/usr/include,那么为了打开文件 stdio.h,则需要有对该工作目录的执行权限。注意:对于目录的读权限和执行权限的意义是不相同的。读权限允许我们读目录,获取在该目录中所有文件名的列表当一个目录是我们要访问文件的路径名的一个组成部分时,对该目录的执行权限使我们可通过该目录(也就是搜索该目录,寻找一个特定的文件名。)
  2. 文件的读权限决定了我们是否能够打开该文件进行读操作。
  3. 文件的写权限决定了我们是否能够打开该文件进行写操作。
  4. 为了要在一个目录中创建一个新文件,必须对该目录具有写权限和执行权限
  5. 为了删除一个现有的文件,必须对包含该文件的目录具有写权限和执行权限。对该文件本身则不需要有读、写权限
  6. 如果用7个exec 函数中的任何一个执行某个文件,都必须对该文件具有执行权限。该文件还必须是一个普通文件

测试文件访问权限位

  进程每次打开、创建或删除一个文件时,内核就进行文件访问权限测试。这种测试可能涉及文件的所有者(st_uid 和st_gid)、进程的有效 ID(有效用户 ID 和有效组 ID)以及进程的附加组 ID。内核进行的测试按下面步骤依次进行:

  1. 若进程的有效用户 ID 为 0(即超级用户),则允许访问。
  2. 若进程的有效用户 ID 等于文件的所有者 ID,那么:若所有者适当的访问权限位被设置,则允许访问,否则拒绝访问。适当的访问权限位指的是:若进程为读而打开该文件,则用户读位应为 1;若进程为写而打开该文件爱你,则用户写位应为 1;若进程将执行该文件,则用户执行位应为 1.
  3. 若进程有效组 ID 或进程附加组 ID 之一等于文件的组 ID,那么,若组适当的访问权限位被设置,则允许访问,否则拒绝访问。
  4. 若其他用户适当的访问权限位被设置,则允许访问,否则拒绝访问。

  顺序的执行以上四步,如果进程拥有此文件(2步)按用户访问权限位批准或拒绝该进程对文件的访问——不看组访问权限,如果进程不拥有此文件,单进程属于某个适当的组,按组访问权限位批准或拒绝该进程对文件的访问权限——不看其他用户的访问权限。

新文件的目录和所有权限

  新文件的用户 ID 设置为进程的有效用户 ID。关于组 ID,POSIX.1 允许实现选择下列之一作为新文件的组 ID。

  • 新文件的组 ID 可以是进程有效组 ID。
  • 新文件的组 ID 可以是它所在目录的组 ID。

  对于 Linux 2.4.22,新文件的组 ID 取决于它所在目录的设置组 ID 为是否被设置。如果该目录的这一位被设置,则新文件的组 ID 设置为目录的组 ID;否则,将新文件的组 ID 设置为进程的有效组 ID。

#include <unistd.h>
int access(const char *pathname, int mode);
int faccessat(int fd,const char *pathname, int mode,int flag);
//以上函数成功返回0出错返回-1

/* Values for the second argument to access.
   These may be OR‘d together.  */
#define R_OK    4       /* Test for read permission.  */
#define W_OK    2       /* Test for write permission.  */
#define X_OK    1       /* Test for execute permission.  */
#define F_OK    0       /* Test for existence.  */

注意:

  open打开文件时,内核以进程有效用户ID和有效组ID为基础测试文件访问权限位。次函数按实际用户ID和实际组ID进行文件访问权限位测试

#include <sys/stat.h>
int chmod(const char *path, mode_t mode);
int fchmod(int fd, mode_t mode);
int fchmodat(int fd,const char *path,mode_t mode,int flag);
//以上函数成功返回0失败返回-1
The new file permissions are specified in mode, which is a bit mask created by ORing together zero or more of the 
following:
 
S_ISUID  (04000)  set-user-ID (set process effective user ID on execve(2))
S_ISGID  (02000)  set-group-ID (set process effective group ID on execve(2); mandatory locking, as described in fcntl(2); 
                            take a new  files group from parent directory, as described in chown(2) and mkdir(2))
S_ISVTX  (01000)  sticky bit (restricted deletion flag, as described in unlink(2))

S_IRUSR  (00400)  read by owner
S_IWUSR  (00200)  write by owner
S_IXUSR  (00100)  execute/search  by  owner  ("search"  applies  for directories, and means that entries within the 
                                              directory can beaccessed)
S_IRGRP  (00040)  read by group
S_IWGRP  (00020)  write by group
S_IXGRP  (00010)  execute/search by group

S_IROTH  (00004)  read by others
S_IWOTH  (00002)  write by others
S_IXOTH  (00001)  execute/search by others

注意:

  1. chomd只更新i结点最后一次访问时间
  2. 对普通文件赋予粘着位,有没有超级用户权限,则mode中的粘着位自动关闭,防止用户恶意设置粘着位,影响系统性能
  3. 新创建文件的组ID可能不是调用进程的所属的组。如果新文件的组ID不等于该进程有效组ID或进程复述数组ID其中之一,而且进程没有超级用户权限,那么设置组ID会被清除。防止用户创建了一个设置组ID文件,而该文件是由非该用户所属的组拥有的

粘着位

对于文件:

  在以前旧的系统当中,如果一个程序文件一旦设置了粘着位,那么当该程序中止的时候他的所有指令段将被保存到系统的交换分区当中,再次运行时可以更快的调入系统.不过现在的操作系统已经不再使用这种功能了.但这并不表示这功能已经完全被废弃

对于目录:

  当一个目录设置为粘着位时,它将发挥特殊的作用,即当一个目录被设置为"粘着位"(用chmod a+t),则该目录下的文件只能由

  1. 超级管理员删除
  2. 该目录的所有者删除
  3. 该文件的所有者删除

  也就是说,即便该目录是任何人都可以写,但也只有文件的属主才可以删除文件

文件和目录

原文:https://www.cnblogs.com/tianzeng/p/11042840.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!