APUE_chapter4 文件和目录 part2

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);(略)

一、access函数是按实际用户 I D和实际组I D进行存取许可权测试的,而非有效用户ID或有效组ID。
#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 
----------------------------------------------------------------------------------------------------------
[shiyang@localhost chapter4]$ ll
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
------------------------------------------------------------------------------------------------------------
1、非root用户无法直接访问SUID_HAS_BEEN_SET文件

2、但是非root用户可以调用a.out二进制文件间接打开SUID_HAS_BEEN_SET文件

3、这是因为a.out对SUID置位,且可以被其他用户执行

4.8 函数umask

一、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]$ ./a.out 
[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;
}
------------------------------------------------------------------------------------------------------------

-------------------------------------------- ----------------------------------------------------------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值