码迷,mamicode.com
首页 > 其他好文 > 详细

unix环境高级编程笔记(4)—— 文件和目录(1)

时间:2014-11-13 22:07:18      阅读:183      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   io   color   ar   使用   sp   for   

1 引言

本文将描述文件系统的一些特征和文件的性质,从stat函数开始,逐个讲解stat结构的成员以了解文件的属性。

2 stat,fstat 和 lstat函数

#include <sys/stat.h>
int stat(const char *restrict pathname,struct stat *restrict buf);
int fstat(int filedes,struct stat *restrict buf);
int lstat(const char *restrict pathname,struct stat *restrict buf);
                                                                          成功返回0,失败返回-1。

以上三个函数在 buf 中返回文件的信息结构,fstat使用文件描述符,而不是pathname。lstat和stat差不多,当pathname是符号链接时,lstat返回的是符号链接的有关信息,而不是其所引用文件的信息。

buf  是一个struct stat结构指针,函数会自动填写结构内容。

struct stat{
	mode_t       st_mode;	                /* file type & mode (permissions) */
	ino_t        st_ino;			/* i-node number */
	dev_t        st_dev;			/* device number (file system) */
	dev_t	     st_rdev;			/* device number for special files */
	nlink_t      st_nlink;			/* number of links */
	uid_t        st_uid;			/* user ID of owner */
	gid_t        st_gid;			/* group ID of owner */
	off_t        st_size;			/* size in byte,for regular files */
	time_t       st_atime;			/* time of last access */
	time_t       st_mtime;			/* time of last modification */
	time_t       st_ctime;			/* time of last file status change */
	blksize_t    st_blksize;		/* best I/O block size */
	blkcnt_t     st_blocks;		        /* number of disk blocks allocated*/
};

3 文件类型

  • 普通文件(regular file)   :最常用文件类型,二进制文件也是普通文件。UNIX不区分普通的文本文件和二进制文件。
  • 目录文件(directory file):包含其他文件的名字以及这些文件信息的指针。
  • 块特殊文件(block special file):这种文件提供对设备带缓冲的访问,每次访问长度固定。
  • 字符特殊文件(character special file):这种文件提供对设备不带缓冲的访问,每次访问长度可变。系统中的设备要么是block special file,要么是character special file。
  • FIFO:这种文件用于进程间通讯,也称为命名管道(named pipe)。
  • 套接字(socket):这种文件用于进程间的网络通讯,也可以用于一台计算机上进程间的非网络通讯。
  • 符号链接(symobic link):指向另一个文件。

文件类型的信息包含在stat结构的st_mode成员中,可以用下列宏进行测试,例如:S_ISREG(buf.st_mode)。

        S_ISREG( )      regular file

        S_ISDIR( )       directory file

        S_ISBLK( )         block special file

        S_ISCHR( )      character special file

        S_ISFIFO( )      FIFO

        S_ISLINK( )      symobic link

        S_ISSOCK( )      socket

另外进程间通信(IPC)对象也可作为文件。用相应的宏进行测试,不过不是用st_mode成员作为参数,而是指向stat的指针。

下面这个程序对每个参数打印文件类型。

#include <stdio.h>
#include <sys/stat.h>
int main(int argc,char* argv[])
{
    int i;
    struct stat buf;
    char *ptr;
    for(i = 1;i < argc;i++)
    {
        if(lstat(argv[i],&buf)< 0)
            {
                printf("lstat error\n");
                continue;
            }
        printf("%s: ",argv[i]);
        if(S_ISREG(buf.st_mode))
            ptr = "regular";
        else if(S_ISDIR(buf.st_mode))
            ptr = "directory";
        else if(S_ISCHR(buf.st_mode))
            ptr = "character special";
        else if(S_ISBLK(buf.st_mode))
            ptr = "block special";
        else if(S_ISFIFO(buf.st_mode))
            ptr = "fifo";
        else if(S_ISLNK(buf.st_mode))
            ptr = "link";
        else if(S_ISSOCK(buf.st_mode))
            ptr = "socket";
        else
            ptr = "unknow mode";
        printf("%s\n",ptr);
    }
    return 0;
}

编译执行:

root@debian:/program# ./4-1 /etc/passwd /etc /dev/log /dev/tty /dev/cdrom
/etc/passwd: regular
/etc: directory
/dev/log: socket
/dev/tty: character special
/dev/cdrom: link
root@debian:/program# 

4 设置用户和组ID

  • 实际用户ID和实际组ID:标识我们实际是谁,这两个字段一般在登录时取自口令文件中的登录项。
  • 有效用户ID,有效组ID和附加组ID:决定了我们对文件的访问权限。
  • 保存的设置用户ID和保存的设置组ID:执行了一个程序时包含了有效用户ID和有效组ID副本。

文件所有者由stat结构中的st_uid表示,组所有者由st_gid表示。

设置用户ID位和设置组ID位在stat结构的st_mode成员中,可由常量S_ISUID和S_ISGID测试。

5 文件访问权限

st_mode值也包含文件访问权限位,前面所提到的文件都有访问权限(access permission)。

每次打开,创建或删除一个文件时,内核都对文件访问权限进行测试,涉及到所有者(st_uid,st_gid)和 进程有效ID(有效用户ID和有效组ID),附加组ID。前两个是文件的性质,后面的是进程的性质,内核进行测试的过程:按顺序测试。

  1. 若进程的有效ID是0(超级用户),则允许访问。
  2. 若进程的有效用户ID等于文件的有效用户ID(也就是进程拥有此文件),那么,若所有者适当的访问权限位被设置则允许访问,否则拒绝访问。
  3. 若进程有效组ID或进程的附加组ID 等于文件的组ID,若适当的访问权限位被设置则允许访问。
  4. 若其他用户适当的访问权限位被设置,则允许访问。

6 新文件和目录的所有权

当创建新文件或目录时,其文件的用户ID为进程的有效ID,组ID由两种选择:

  1)进程的有效组ID。

  2)所在目录的组ID(如果所在目录的设置组ID位被设置的话)。

7 access 函数

也可以用access函数进行以实际用户或组进行测试(也是四步,有效改为实际)。

#include <unistd.h>
int access(const char *pathname,int mode);
                                                    若成功返回0,失败返回-1.

参数mode用以下常量按位或 取得:

      R_OK      可读

      W_OK      可写

      X_OK        可执行

      F_OK       测试文件是否存在

8 umusk 函数

umusk为进程设置文件模式创建屏蔽字,并返回以前的值。(此函数没有出错返回)

#include <sys/stat.h>
mode_t umask(mode_t cmask);
                    返回以前的文件模式创建屏蔽字

参数cmask的值是9个文件访问权限按位或构成的。

任何文件模式创建屏蔽字中为1 的位 ,在文件mode中相应的位都被关闭。

下面的程序创建两个文件,使用不同的文件模式创建屏蔽字。

#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#define RWRWRW (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
int main()
{
    umask(0);
    if(creat("foo",RWRWRW) < 0)
        printf("creat foo error\n");
    umask( S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH );
    if(creat("bar",RWRWRW) < 0)
        printf("creat bar error\n");
    return 0;
}

第一个umask把文件创建模式屏蔽字清零,所以创建的文件就是指定的文件访问权限,第二个umask把组和其他用户的读,写权限屏蔽了,所以只有用户能读,写。

    root@debian:/program# ./4-3

root@debian:/program# ls -l bar foo
-rw------- 1 root root 0 Nov  9 21:24 bar
-rw-rw-rw- 1 root root 0 Nov  9 21:24 foo
root@debian:/program# 

 9 chmod 和 fchmod 函数

这两个函数可以更改现有文件的访问权限

#include<sys/stat.h>
int chmod(const char *pathname,mode_t mode);
int fchmod(int filedes,mode_t mode);
            成功返回0,出错返回-1。

  

pathname :指定文件。

filedes:指定文件描述符。

mode:文件访问权限位。

10 chown fchown 和 lchown

这三个函数用于更改文件的用户ID和组ID

#include<unistd,h>
int chown(const char *pathname,uid_t owner,gid_t group);
int fchown(int filedes,uid_t owner,gid_t group);
int lchown(const char *pathname,uid_t owner,gid_t group);
              成功返回0,失败返回-1.

  

lchown 修改的是符号链接本身的所有者。

如果 owner 和group中任意一个为 -1 ,则对应的ID值不变。

如果这些函数由非超级用户调用,则该文件的设置用户ID位和设置组ID位被清除  

 

unix环境高级编程笔记(4)—— 文件和目录(1)

标签:des   style   blog   io   color   ar   使用   sp   for   

原文地址:http://www.cnblogs.com/avengervirus/p/4085943.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!