1、stat、fstat 和 lstat
#include <sys/types.h>
#include <sys/stat.h>
int stat(const char *pathname, struct stat *buf);
int fstat(int filedes, struct stat *buf);
int lstat(const char *pathname, struct stat *buf);
/*三个函数返回:若成功则为0, 若失败则为-1 */
给定一个pathname, stat函数返回一个与些命名文件有关的信息结构。
fstat函数获得已在描述符filedes上打开的文件的有关信息。
lstat函数类似stat,但是当命名的文件是一个符号连接时,lstat返回该符号连接的有关信息,而不是由该符号连接引用的文件的信息。
2、文件类型
普通文件 目录文件 字符特殊文件 块特殊文件
FILO 套接口 符号连接
文件类型信息包含在stat结构的st_mode成员中。
eg:
/*
* 对每个命令行参数打印文件类型
*/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(int argc, char *argv[])
{
int i;
struct stat buf;
char *ptr;
for(i = 1; i < argc; i++)
{
printf("%s:",argv[i]);
if(lstat(argv[i],&buf) < 0)
{
printf("lstat error");
continue;
}
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 = "symbolic link";
else if(S_ISSOCK(buf.st_mode))
ptr = "socket";
printf("%s\n",ptr);
}
return 0;
}
3、设置-用户-ID 和设置-组-ID
4、文件存取许可权
st_mode值也包含了对文件的存取许可权位。
st_mode屏蔽 意义
S_IRUSR 用户-读
S_IWUSR 用户-写
S_IXUSR 用户-执行
S_IRGRP 组-读
S_IWGRP 组-写
S_IXGRP 组-执行
S_IROTH 其他-读
S_IWOTH 其他-写
S_IXOTH 其他-执行
注:重点理解书上说明。
5、新文件和目录的所有者
新文件的用户ID设置为进程的有效用户ID,关于组ID,POSIX.1允许选择下列之一作为新文件的组ID:
(1)新文件的组ID可以是进程的有效组ID;
(2)新文件的组ID可以是它所在目录的组ID;
6、access
当用open函数打开一个文件时,内核以进程的有效用户ID和有效组ID为基础执行其存取许可权测试。
#include <unistd.h>
int access(const char *pathname, int mode);
/*返回:若成功则为0,若出错则为-1 */
mode 参数是以下常数的逐位或运算
mode 说明
R_OK 测试读许可权
W_OK 测试写许可权
X_OK 测试执行许可权
F_OK 测试文件是否存在
eg:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
int main(int argc, char *argv[])
{
if(argc != 2)
{
printf("usage:a./out <pathname>");
exit (-1);
}
if(access(argv[1],R_OK) < 0)
{
printf("access error for %s",argv[1]);
exit (-2);
}
else
printf("read access OK\n");
if(open(argv[1],O_RDONLY) < 0)
{
printf("open error for %s",argv[1]);
exit (-3);
}
else
printf("open for reading OK\n");
return 0;
}
7、umask
#include <sys/types.h>
#include <sys/stat.h>
mode_t umask(mode_t cmask);
/*返回:以前的文件方式创建屏蔽字*/
8、chmod 和 fchmod
#include <sys/types.h>
#include <sys/stat.h>
int chmod(const char *pathname, mode_t mode);
int fchmod(int filedes, mode_t mode);
/*两个函数返回:若成功则为0,若出错则为-1 */
chmod函数在指定的文件上进行操作,而fchmod函数则对己打开的文件进行操作。
为了改变一个文件的许可权位,进程的有效用户ID必须等于文件的所有者,或者该进程必须具有超级用户许可权。
9、粘住位
10、chown, fchown, lchown
#include <sys/types.h>
#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 */
note:
SVR4, 4.3+BSD和XPG3允许将参数owner或group指定为-1,以表示不改变相应的ID。这不是POSIX.1的一部分。
11、文件长度
stat结构的成员st_size包含了以字节为单位的该文件的长度。此字段只对普通文件、目录文件和符号连接有意义。
对于普通文件,其文件长度可以是0,在读这种文件时,将得到文件结束指示。
对于目录,文件长度通常是一个数,例如16或512的整倍数。
对于符号连接,文件长度是在文件名中的实际字节数。
文件空洞:
空洞是由超过文件结尾端位移量设置,并写了某些数据造成的。
12、文件截短
#include <sys/types.h>
#include <unistd.h>
int truncate(const char *pathname, off_t length);
int ftruncate(int filedes, off_t length);
/*返回:若成功为0,若出错则为-1 */
这两个函数将由路径名为pathname 或打开文件描述符filedes指定的一个现存文件的长度截短为length.如果该文件以前的长度大于length,则超过length以外的数据就不再能存取。如果以前的长度短于length,则其后果与系统有关。如果某个实现的处理是扩展该文件,则在以前的文件尾端和新文件尾端之间的数据将读作0(也就是在文件中创建了一个空洞).
13、文件系统
重点理解书上内容。
14、link, unlink, remove, rename
#include <unistd.h>
int link(const char *oldpath, const char *newpath);
/*返回:若成功则为0,若出错则为-1 */
link函数创建一个新目录项newpath,它引用现存文件oldpath.如果newpath已经存在,则返回出错。
#include <unistd.h>
int unlink(const char *pathname);
/*返回:若成功则为0,若出错则为-1 */
eg:
/*
*打开一个文件,然后unlink它
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main(void)
{
if(open("tempfile",O_RDWR) < 0)
{
printf("open error");
return -1;
}
if(unlink("tempfile")) < 0)
{
printf("unlink error");
return -1;
}
printf("file unlinked");
sleep(15);
printf("done");
return 0;
}
#include <stdio.h>
int remove(const char *pathname);
/*返回:若成功则为0,若出错则为-1 */
对于文件,remove的功能与unlink相同。对于目录,remove的功能与rmdir相同。
#include <stdio.h>
int rename(const char *oldname, const char *newname);
/*返回:若成功则为0,若出错则为-1 */
15、符号连接
符号连接是对一个文件的间接指针,它与硬连接有所不同,硬连接直接指向文件的i节点。引进符号连接的原因是为了避免硬连接的一些限制:(1)硬连接通常要求连接和文件位于同一文件系统中。(2)只有超级用户才能创建到目录的硬连接。
16、symlink, readlink
#include <unistd.h>
int symlink(const char *actualpath, const char *sympath);
/*返回:若成功则为0,若出错则为-1 */
symlink函数创建一个指向actualpath的新目录项sympath,在创建些符号连接时,并不要求actualpath已经存在。并且,actualpath和sympath并不需要位于同一文件系统。
因为open函数跟随符号连接,所以需要一有种方法打开该连接本身,并读该连接中的名字。readlink函数提供了这种功能。
#include <unistd.h>
int readlink(const char *pathname, char *buf, int bufsize);
/*返回:若成功则为读的字节数,若出错则为-1 */
17、文件的时间
对每个文件保持有三个字段。
字段 说明 例子 ls(1)选项
st_atime 文件数据的最后存取时间 read -u
st_mtime 文件数据的最后修改时间 write 缺省
st_ctime i节点状态的最后更改时间 chmod, chown -c
18、utime
一个文件的存取和修改时间可以用utime函数更改。
#include <sys/types.h>
#include <utime.h>
int utime(const char *pathname, const struct utimbuf times);
/*返回:若成功则为0,若出错则为-1 */
此函数所使用的结构是:
struct utimbuf{
time_t actime; /*access time */
time_t modtime; /*modification time*/
}
注意,我们不能对更改状态时间st_ctime指定一个值,当调用 utime函数时,此字段被自动更新。
19、mkdir, rmdir
#include <sys/types.h>
#include <sys/stat.h>
int mkdir(const char *pathname, mode_t mode);
/*返回:若成功则为0,若出错则为-1 */
note:
常见的错误是指定与文件相同的mode(只指定读、写许可权),但是,对于目录通常至少要设置1个执行许可权位,以允许存取该目录中的文件名。
#include <unistd.h>
int rmdir(const char *pathname);
/*返回:若成功则为0,若出错则为-1 */
20、读目录
对某个目录具有存取许可权的任一用户都可读该目录,但是只有内核才能写目录(防止文件系统发生混乱)。
一个目录的写许可权位和执行许可权位决定了在该目录中能否创建新文件以及删除文件,它们并不表示能否写目录本身。
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *dp);
/*返回:若成功则为指针,若出错则为NULL */
struct dirent *readdir(DIR *dp);
/*返回:若成功则为指针,若出错或在目录尾则为 NULL */
void rewinddir(DIR *dp);
int closedir(DIR *dp);
/*返回:若成功则为0,若出错则为-1 */
21、chdir, fchdir, getcwd
#include <unistd.h>
int chdir(const char *pathname);
int fchdir(int filedes);
/*返回:若成功则为0,若出错则为-1 */
eg:
#include <unistd.h>
#include <stdio.h>
int main(void)
{
if(chdir("/tmp") < 0)
{
printf("chdir failed");
return -1;
}
printf("chdir to /tmp succeeded\n");
return 0;
}
#include <unistd.h>
char *getcwd(char *buf, size_t size);
/*返回:若成功则为buf, 若出错则为NULL */
向此函数传递两个参数,一个是缓存地址buf, 另一个是缓存的长度size. 该缓存必须有足够的长度以容纳绝对路径名加上一个null 终止字符,否则返回出错。
eg:
/*
*getcwd函数实例
*/
#include <unistd.h>
#include <stdio.h>
int main(void)
{
char *ptr;
int size;
if(chdir("/usr/spool/uucppublic") < 0)
{
printf("chdir failed");
return -1;
}
ptr = path_alloc(&size);
if(getcwd(ptr,size) == NULL)
{
printf("getcwd failed");
return -1;
}
printf("cwd = %s",ptr);
return 0;
}
22、 特殊设备文件