`
xitonga
  • 浏览: 586470 次
文章分类
社区版块
存档分类
最新评论

Linux/UNIX之文件和目录(1)

 
阅读更多

文件和目录(1)

stat、fstat和lstat函数

#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);

一旦给出path,stat函数返回与词文件相关的信息结构。fstat获取已在描述符fd上打开的有关信息。lstat类似于stat,但当命名的文件是一个符号连接时,lstat返回该符号链接的有关信息,而不是该符号链接引用文件的信息。

第二个参数buf是一个结构指针,该结构返回文件有关信息,其基本形式如下:

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

};

文件类型

文件类型包括以下几种:

普通文件、目录文件、块特殊文件、字符特殊文件、FIFO、套接字和符号链接。

文件类型信息包含在stat结构的st_mode成员中,可用下面的宏来确定文件类型:

S_ISREG(): 普通文件

S_ISDIR(): 目录文件

S_ISCHR(): 字符特殊文件

S_ISBLK(): 块特殊文件

S_ISFIFO(): 管道或FIFO

S_ISLINK(): 符号链接

S_ISSOCK(): 套接字

如下程序取其命令参数,然后针对每一个命令参数打印其文件类型:

#include<unistd.h>

#include<stdio.h>

#include<sys/stat.h>

int main(int argc, char *argv[])

{

int i;

structstat buf;

char *ptr;

for(i = 1; i < argc; i++) {

printf("%s:", argv[i]);

if(lstat(argv[i], &buf) < 0) {

perror("lstaterror");

continue;

}

if(S_ISREG(buf.st_mode))

ptr= "regular";

elseif (S_ISDIR(buf.st_mode))

ptr= "directory";

elseif (S_ISCHR(buf.st_mode))

ptr= "character special";

elseif (S_ISBLK(buf.st_mode))

ptr= "block special";

elseif (S_ISFIFO(buf.st_mode))

ptr = "fifo";

elseif (S_ISLNK(buf.st_mode))

ptr= "symbolic link";

elseif (S_ISSOCK(buf.st_mode))

ptr= "socket";

else

ptr= "** unknown mode **";

printf("%s\n",ptr);

}

exit(0);

}

设置用户ID和设置组ID

每个进程相关联的ID有6个或更多,如下:

实际用户ID、实际组ID:我们实际上是谁

有效用户ID、有效组ID、附加组ID:用于文件访问权限的检查

保存的设置用户ID、保存的设置组ID:由exec函数保存

每个文件都有一个所有者和组所有者,所有者由stat结果中的st_uid成员表示,组所有者则由st_gid成员表示。

当执行一个程序文件时,进程的有效用户ID通常是实际用户ID,有效组ID通常是实际组ID。但可以在文件模式(st_mode)中可以通过设置用户ID位(S_ISUID)和设置组ID位(S_ISGID)将进程的有效用户ID设置为文件所有者的用户ID,将有效组ID设置为文件的组所有者的ID。

文件访问权限

st_mode值也包含了针对文件的访问权限位。

每个文件有9个访问权限,分为三类。chmod命令用于修改这9个权限值,改名了允许我们用u表示用户,用g表示组,用o表示其他。以下是9个访问权限位:

S_IRUSR 用户读

S_IWUSR 用户写

S_IXUSR 用户执行

S_IRGRP 用户读

S_IWGRP 用户写

S_IXGRP 用户执行

S_IROTH 用户读

S_IWOTH 用户写

S_IXOTH 用户执行

目录的读权限允许我们读目录,获得在该目录中所有文件名的列表。

当一个目录是我们要访问文件路径的一个组成部分时,对该目录的执行权限使我们可通过该目录。

当需要创建或删除有一个目录中的文件时,必须对包含该文件的目录具有写权限和执行权限。

进程每次打开、创建或删除一个文件时,内核就进行文件访问权限测试,这种测试可能涉及文件的所有者、进程的有效ID以及进程的附加组ID。两个所有者ID是文件的性质,而两个有效组ID和附加组ID则是进程的性质。内核测试如下:
1.若进程有效用户ID是0(超级用户),则允许访问

2.若进程有效用户ID等于文件所有者ID,那么可通过所有者设置适当的访问权限访问文件,否则拒绝访问。

3.若进程有效组ID或附加组ID等于文件组ID,那么可通过文件组设置的适当访问权限访问文件,否则拒绝访问。

4.若其他用户适当的访问权限被设置,则允许访问;否则拒绝访问。

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

1)新文件的组ID可以是进程的有效组ID

2)新文件的组ID可以是它所在目录的组ID

access函数

#include <unistd.h>

int access(const char *pathname, int mode);

该函数按实际用户ID和实际组ID进行文件访问权限测试。成功返回0,出错返回-1。

其中第一个参数为测试文件名,第二个参数是以下所列常量的按位或

R_OK 测试读权限

W_OK 测试写权限

X_OK 测试执行权限

F_OK 测试文件是否存在

以下显示了access函数的使用方法:

#include "apue.h"

#include <fcntl.h>

int

main(int argc, char *argv[])

{

if (argc != 2)

err_quit("usage: a.out <pathname>");

if (access(argv[1], R_OK) < 0)

err_ret("access error for %s", argv[1]);

else

printf("read access OK\n");

if (open(argv[1], O_RDONLY) < 0)

err_ret("open error for %s", argv[1]);

else

printf("open for reading OK\n");

exit(0);

}

下面是该程序的示例会话:

chen123@ubuntu:~/user/apue.2e$ ls -l a.out

-rwxrwxr-x 1 chen123 chen123 78392014-04-18 19:59 a.out

chen123@ubuntu:~/user/apue.2e$ ./a.out a.out

read access OK

open for reading OK

chen123@ubuntu:~/user/apue.2e$ ls -l /etc/shadow

-rw-r----- 1 root shadow 1047 2014-04-1506:03 /etc/shadow

chen123@ubuntu:~/user/apue.2e$ ./a.out /etc/shadow

access error for /etc/shadow: Permissiondenied

open error for /etc/shadow: Permissiondenied

chen123@ubuntu:~/user/apue.2e$ su

Password:

root@ubuntu:/home/chen123/user/apue.2e# chown root a.out

root@ubuntu:/home/chen123/user/apue.2e# chmod u+s a.out

root@ubuntu:/home/chen123/user/apue.2e# ls -l a.out

-rwsrwxr-x 1 root chen123 7839 2014-04-1819:59 a.out

root@ubuntu:/home/chen123/user/apue.2e# exit

exit

chen123@ubuntu:~/user/apue.2e$ ./a.out /etc/shadow

access error for /etc/shadow: Permissiondenied

open for reading OK

这里的测试首先显示a.out的文件信息和/etc/shadow的文件信息。当执行./a.out /etc/shadow命令时,access不能通过,因为/etc/shadow的文件用户为root,而进程实际用户是chen123,所以没有读权限。open也不能通过,因为测试的是用户也是实际用户。但将a.out的用户ID改变为root,并打开设置用户ID位后,当执行a.out程序时,可以认为执行这个程序的进程有效用户ID变成了a.out文件用户ID root。但access函数测试的实际用户ID仍然是chen123。所以access不能通过,而open可以通过。但若没有打开设置用户ID位,open也不能通过。

umask函数

#include <sys/types.h>

#include <sys/stat.h>

mode_t umask(mode_t mask);

umask函数为进程设置文件模式创建屏蔽字,并返回以前的值。

参数mask是由文件访问权限中的9个常量中的若干个按位或构成的。在进程创建文件或新目录时,一定会使用文件模式创建屏蔽字。对于任何在文件模式创建屏蔽字中为1的为,在文件mode中的相应位一定被关闭。

chmod和fchmod函数

#include <sys/stat.h>

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

int fchmod(int fd, mode_t mode);

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

chown、fchown和lchown函数

#include <unistd.h>

int chown(const char *path, uid_t owner,gid_t group);

int fchown(int fd, uid_t owner, gid_tgroup);

int lchown(const char *path, uid_t owner,gid_t group);

以上函数可用于更改文件的用户ID和组ID。

在符号链接的情况下,lchown更改符号链接本身的所有者,而不是符号链接所指向的文件。

如若两个参数owner和group中的任意一个是-1,则个的ID不变。

文件长度

stat结构成员st_size表示一字节为单位的文件长度。此字段只对普通文件、目录文件和符号链接有意义。

对普通文件,其文件长度可以是0,在读这种文件时,将得到文件结束指示。

对于目录,文件长度通常是一个数(例如16或512)的倍数。

对于链接,文件长度是文件名(包括路径)中的实际字节数。

UNIX提供st_blksize字段,当我们将该字段用于读操作时,读一个文件的时间量最少。

文件截短

#include <unistd.h>

#include <sys/types.h>

int truncate(const char *path, off_tlength);

int ftruncate(int fd, off_t length);

这两个函数可以把现有的文件长度截短为length字节。如果该文件以前的长度大于length,则超过length以外的数据就不在能访问。如果以前的长度短语length,则扩张该文件,在旧文件尾端与新文件尾端填充0(也就是创建了空洞)。

讲一个文件清空为0可以在打开文件时使用O——TRUNC标志。

分享到:
评论

相关推荐

    LINUX.UNIX系统编程手册(下册)

    linux编程资深专家michael kerrisk在书中详细描述了linux/unix系统编程所涉及的系统调用和库函数,并辅之以全面而清晰的代码示例。《linux/unix系统编程手册(上、下册)》涵盖了逾500个系统调用及库函数,并给出逾200...

    Linux/UNIX系统编程手册.part1

    Linux编程资深专家Michael Kerrisk在书中详细描述了Linux/UNIX系统编程所涉及的系统调用和库函数,并辅之以全面而清晰的代码示例。《Linux/UNIX系统编程手册(上、下册)》涵盖了逾500个系统调用及库函数,并给出逾200...

    Linux-UNIX系统编程手册.pdf

    该资源是很好的学习Linux/Unix编程的手册,看豆瓣书评挺高的就先自己下载看一下,防止自己的文件意外删除,先放到CSDN上,一来可以做一个备份,二来有需要的也可以自己下载(分享才能更好的成长)

    Linux/UNIX系统编程手册.part2

    Linux编程资深专家Michael Kerrisk在书中详细描述了Linux/UNIX系统编程所涉及的系统调用和库函数,并辅之以全面而清晰的代码示例。《Linux/UNIX系统编程手册(上、下册)》涵盖了逾500个系统调用及库函数,并给出逾200...

    Linux/UNIX系统编程手册 上册

    linux编程资深专家michael kerrisk在书中详细描述了linux/unix系统编程所涉及的系统调用和库函数,并辅之以全面而清晰的代码示例。《linux/unix系统编程手册(上、下册)》涵盖了逾500个系统调用及库函数,并给出逾200...

    ftp命令详解--linux/unix

    ftp命令的详细讲解,对于经常在linux/unix下进程文件传输的人员是份不错的参考资料。

    Linux UNIX系统编程手册

    Linux编程资深专家Michael Kerrisk在书中详细描述了Linux/UNIX系统编程所涉及的系统调用和库函数,并辅之以全面而清晰的代码示例。 《Linux/UNIX系统编程手册(上、下册)》涵盖了逾500个系统调用及库函数,并给出逾...

    Linux/Unix sed命令中文详解图

    sed 是一种在线编辑器,它一次处理一行...接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有 改变,除非你使用重定向存储输出。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。

    LinuxUNIX系统编程手册(上)

    linux编程资深专家michael kerrisk在书中详细描述了linux/unix系统编程所涉及的系统调用和库函数,并辅之以全面而清晰的代码示例。《linux/unix系统编程手册(上、下册)》涵盖了逾500个系统调用及库函数,并给出逾200...

    Cacti for Linux/Unix(网络流量监测图形分析工具) v1.2.4.zip

    Cacti for Linux/Unix安装方法 在文件夹include下的config.php中可配置你的数据库信息。 $database_type = "mysql"; //数据库类型 $database_default = "cacti"; //数据库名称 $database_hostname = "localhost...

    《linux/UNIX系统编程手册》书上daemon章节测试实例代码(及简化)

    根据《linux/UNIX系统编程手册》的daemon章节写的一个测试become_daemon()函数程序。代码内容99%以上都是书上给的源码。此处仅注释掉不需要的内容,以及为了简化理解,做了不同平台的适配,(对于源码来说是种倒退,...

    LINUX/UNIX Shell编程大作业

    在Linux系统的/etc目录下有这样一个文件passwd,该文件里包含系统中所有用户信息的记录,记录里包含每个用户的如下信息:用户名、密码、用户ID、组ID、用户全名、用户主目录和用户登录所用的shell。请设计一个脚本...

    Linux/unix最全解压命令

    这里面包含了所有关于unix/Linux下的解压命令,并且还包含教你如何自己制作一个万能解压命令,对所有的压缩包都能解压

    LINUX/UNIX环境高级编程

    本书的前15章着重于理论知识的阐述,主要内容包括UNIX文件和目录、进程环境、进程控制、进程间通信以及各种I/O。在此基础上,分别按章介绍了多个应用实例,包括如何创建数据库函数库,PostScript 打印机驱动程序,...

    Linux UNIX系统编程手册 下

    linux编程资深专家michael kerrisk在书中详细描述了linux/unix系统编程所涉及的系统调用和库函数,并辅之以全面而清晰的代码示例。《linux/unix系统编程手册(上、下册)》涵盖了逾500个系统调用及库函数,并给出逾200...

    C语言 cp 指令 在linux/unix 运行

    cp 指令 在unix里运行 ./cp1 file1 file2 copy 一个文件file1 然后写入到 创建文件file2

Global site tag (gtag.js) - Google Analytics