4.6 新文件和目录的所有权
- 新文件的用户ID设置为进程的有效用户ID。
- 新文件的组ID可以是进程的有效组ID。
- 新文件的组ID也可以是它所在目录的组ID。
4.7 函数access和 faccessat
#include <unistd.h>
int access (const char* pathname, int mode);
int access (int fd, const char* pathname, int mode, int flag);(略)
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
int main(int argc, char* argv[]){
if (argc < 2)
printf("usage: a.out <pathname>\n");
else{
for (int i = 1; i < argc; ++i){
if (access(argv[i], R_OK) < 0)
printf ("access error for %s\n", argv[i]);
else
printf ("access ok for %s\n", argv[i]);
if (open(argv[i],O_RDONLY) < 0)
printf ("open error for %s\n", argv[i]);
else
printf ("open ok for %s\n", argv[i]);
}
}
return 0;
}// a.out
total 24
-rw-rw-r--. 1 shiyang shiyang 611 Sep 22 02:18 access.c
-rwsrwxr-x. 1 root root 8658 Sep 22 02:18 a.out
-rw-rw-r--. 1 shiyang shiyang 1292 Sep 21 22:10 S_ISxxx.cpp
-rw-rw----. 1root root 12 Sep 22 02:34SUID_HAS_BEEN_SET
[shiyang@localhost chapter4]$ ./a.out SUID_HAS_BEEN_SET
access error for SUID_HAS_BEEN_SET
open ok for SUID_HAS_BEEN_SET
------------------------------------------------------------------------------------------------------------
4.8 函数umask
一、umask函数为进程设置文件方式创建屏蔽字,并返回以前的值。 (这是少数几个没有出错返回的函数中的一个。) 用户设置umask值以控制他们所创建文件的默认权限
#include <fcntl.h>
#include <stdio.h>
int main(void){
umask(0);
if (creat("foo",S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IWOTH | S_IROTH) < 0)
printf("creat error for foo");
umask( S_IRGRP | S_IWGRP | S_IWOTH | S_IROTH);
if (creat("bar",S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IWOTH | S_IROTH) < 0)
printf("creat error for bar");
}
[shiyang@localhost chapter4]$ ls -l foo bar
-rw-------. 1 shiyang shiyang 0 Sep 22 03:25 bar
-rw-rw-rw-. 1 shiyang shiyang 0 Sep 22 03:25 foo
[shiyang@localhost chapter4]$ umask
0000
------------------------------------------------------------------------------------------------------------
三、注意第三四行bar和foo文件的文件模式的不同
四、更改进程的文件模式创建屏蔽字并不影响其父进程(通常是shell)的屏蔽字
4.9 函数chmod、fchmod 和fchmodat
#include<sys/stat.h>
int chmod (const char *pathname, mode_t mode);
int fchmod (int fd, mode_t mode);
int fchmodat(int fd, const char* pathname, mode_t mode, int flag);(略)
一、三个函数使我们可以更改现有文件的访问权限
二、为了改变一个文件的许可权位,进程的有效用户ID必须等于文件的所有者,或者该进程必须具有超级用户许可权。
三、如果新文件的组ID不等于进程的有效组ID或者进程添加组ID中的一个,以及进程没有超级用户优先数,那么设置 组ID位自动被关闭。这就防止了用户创建一个设置组ID文件,而该文件是由并非该用户所属的组拥有的。
#include <fcntl.h>
#include <unistd.h>
#include<sys/stat.h>
#include <stdio.h>
int main(void){
struct stat statbuf;
if (stat("foo", &statbuf) < 0)
printf("stat error for foo\n");
else{
if (chmod("foo", (statbuf.st_mode & ~S_IXGRP) | S_ISGID) < 0)
printf("chmod error for foo\n");
if (chmod("bar", S_IRWXU | S_IRWXG | S_IRWXO) < 0)
printf("chmod error for bar\n");
}
return 0;
}
------------------------------------------------------------------------------------------------------------
[shiyang@localhost chapter4]$ ls -l bar foo
-rw-------. 1 shiyang shiyang 0 Sep 22 03:37 bar
-rw-rw-rw-. 1 shiyang shiyang 0 Sep 22 03:37 foo
[shiyang@localhost chapter4]$ ./a.out
[shiyang@localhost chapter4]$ ls -l bar foo
-rwxrwxrwx. 1 shiyang shiyang 0 Sep 22 03:37 bar
-rw-rwSrw-. 1 shiyang shiyang 0 Sep 22 03:37 foo
------------------------------------------------------------------------------------------------------------
4.13 文件截断
int truncate(const char* pathname, off_t length);
int ftruncate(int fd, off_t length);
#include <fcntl.h>
#include <unistd.h>
#include<sys/stat.h>
#include <stdio.h>
int main(void){
if (truncate("shiyang.txt", 1000) <0)
printf("truncate error in shiyang.txt\n");
}
------------------------------------------------------------------------------------------------------------
[root@localhost chapter4]# ls -l shiyang.txt (长度包括文件空洞)
-rwxrwxrwx. 1 shiyang shiyang 12 Sep 22 08:16 shiyang.txt
[root@localhost chapter4]# ./a.out
[root@localhost chapter4]# ls -l shiyang.txt
-rwxrwxrwx. 1 shiyang shiyang 1000 Sep 22 08:16 shiyang.txt
[root@localhost chapter4]# wc -c shiyang.txt (长度不包括文件空洞)
1000 shiyang.txt // 是1000 不是12, 挺奇怪的
------------------------------------------------------------------------------------------------------------
4.14 文件系统
任何一个叶目录(不包含其他目录的目录)的链接计数总是2,来源于命名该目录的目录项以及在该目录中的 . 项
4.15 函数link、 linkat、unlinkat和remove
#include <fcntl.h>
#include <unistd.h>
#include<sys/stat.h>
#include <stdio.h>
int main(int argc, char* argv[]){
if (argc != 3)
printf("usage: a.out <existingpath> <newpath>\n");
else{
if (link(argv[1], argv[2]) < 0)
printf("link error\n");
}
return 0;
}
#include <unistd.h>
#include<sys/stat.h>
#include <stdio.h>
int main(int argc, char* argv[]){
if (argc != 3)
printf("usage: a.out <existingpath> <newpath>\n");
else{
if (linkat(AT_FDCWD, argv[1], AT_FDCWD, argv[2], 0) < 0)
printf("link error\n");
}
return 0;
}
#include <fcntl.h>
#include <unistd.h>
#include<sys/stat.h>
#include <stdio.h>
int main(int argc, char* argv[]){
if (argc != 2)
printf("usage: a.out <path>\n");
else{
if (unlink(argv[1]) < 0)
printf("unlink error\n");
}
return 0;
}
#include <fcntl.h>
#include <unistd.h>
#include<sys/stat.h>
#include <stdio.h>
int main(int argc, char* argv[]){
if (argc != 2)
printf("usage: a.out <path>\n");
else{
if (link(AT_FDCWD, argv[1], AT_REMOVEDIR) < 0) // 没有成功删除目录,why
printf("link error\n");
}
return 0;
}
- linux 不允许创建指向目录的硬连接(link -d diretory hard_link_diretory : error)
- 为了解除对文件的连接,必须对包含该目录项的目录具有写和执行许可权。
- 如果对该目录设置了粘住位,则对该目录必须具有写许可权,并且
具备下面三个条件之一:
• 拥有该文件。
• 拥有该目录。
• 具有超级用户优先权
- 只有当连接计数达到0时,该文件的内容才可被删除。另一个条件也阻止删除文件的内容:只要有进程打开了该文件,其内容也不能删除。关闭一个文件时,内核首先检查使该文件打开的进程计数。如果该计数达到0,然后内核检查其连接计数,如果这也是0,那么就删除该文件的内容。
#include <fcntl.h>
#include <unistd.h>
#include<sys/stat.h>
#include <stdio.h>
int main(int argc, char* argv[]){
if (argc != 2)
printf("usage: a.out <path>\n");
else{
int fd;
if ((fd = open (argv[1], O_RDWR) )< 0)
printf("open error\n");
if (unlink(argv[1]) <0)
printf("unlink error\n");
else
printf("unlink success\n");
sleep(30);
printf("done\n");
}
return 0;
}
------------------------------------------------------------------------------------------------------------