一、文件权限

  1. 各种ID

  我在读这一章时遇到了各种ID,根据名字完全不清楚什么意思,幸好看到了这篇文章,http://blog.csdn.net/ccjjnn19890720/article/details/6990656,总结一下

  每一个进程其实对应了6个以上的ID,它们分别是:实际用户ID、实际组ID(我们实际上是谁,执行这个程序的用户和组),有效用户ID、有效组ID、附加组ID(用于文件访问权限检查),保存设置用户ID,保存设置组ID(由exec函数保存)

  实际用户ID/实际组ID:当前执行这个进程的ID,比如我现在是orlion用户,那么我执行foo程序,那么这个foo进程的实际用户ID就是orlion。组同理。一般来说就是当前登陆的用户。

  有效用户ID/有效组ID:这个ID是unix一直在使用的一个ID,因为即使你只是一个很简单的访问文件,那也是要通过这个有效用户ID的,因为每一个文件都有一定的访问权限,而一个进程或者一个程序去访问它,操作系统本身就是根据你的有效用户ID给与一定的权限.

  实际用户ID与有效用户ID到底什么区别?!:这两个ID在一般情况下是相同的,比如当前用户是orlion,那么它的实际用户ID是orlion,而有效用户ID也是orlion。可是在不一般的情况下那么这两个ID就可能不一样了,那么什么样的情况下是不一样的呢?那就是当一个用户要进行一个合理的特权的时候就需要啦,那么到底是怎么样的情况呢?

比如我们在Linux系统中的passwd这个命令或者这个passwd这个程序,一个用户对自己进行修改密码是一种很正常的事情,可是保存密码的文件/etc/passwd却是root用户可写的这样的权利,那么也就是用如果你要修改密码,必须通过root用户帮你修改

  这个事情的处理是这样的,让用户去运行passwd这个程序的时候,os给与root用户的权利,然后用户就可以修改自己的密码。具体的讲就是让用户去运行passwd这个程序的时候,unix将它的有效用户ID变成了拥有passwd的用户的ID,也就是root,所以就可以修改这个/etc/passwd这个文件。

  保存设置用户ID:这个ID是用来保存有效ID的副本,让我们运行程序的过程其实就是os调用exec系列函数来调用我们程序的main函数,exec函数是kernel唯一执行程序的方法,或者那么讲不管什么用户程序的运行,其实也就是os的exec的调用过程。而exec在调用过程中会将这个程序的有效用户ID拷贝给保存用户ID。

  在P O S I X . 1中,这些保存的I D是可选择的。一个应用程序在编译时可测试常数_ POSIX_SAVED_ IDS,或在运行时以参数_ SC_SAVED_IDS调用函数sysconf,以判断此实现是否支持这种特征。

  上边是与进程相关联的ID,下面提到的设置用户ID位则是文件方式字中的一位(与进程无关,是文件属性)。

  文件的设置用户ID位:每一个文件都有一个文件模式字(st_mode),这个字可以通过stat函数去获取,而这个模式字包含了很多文件的属性,包括文件的类型,以及文件的访问权限的,当然设置用户ID位也在其中。通过设置这个位,就能当执行这个文件的时候,进程的有效ID设置为该文件本身的用户,这里这个文件可以认为是可执行文件,当运行这个文件的时候,进程会改变其有效用户ID,变成这些文件本身的ID

  终端中我们查看/usr/bin/passwd这个文件

$ ll /usr/bin/passwd
-rwsr-xr-x. root root 2月 /usr/bin/passwd

  可以看到有一个s权限,这就是设置了设置用户ID位的标志。

  

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h> int main()
{
printf("real user ID = %d\n",getuid());
printf("effect user ID = %d\n",geteuid()); return ;
}

终端中执行:
orlion$ ./main
real user ID =
effect user ID = orlion$ su
root# chown root main
root# chmod u+s main
root# ll main
-rwsr-xr-x root orlion -- : main
root# exit
orlion$ exit
orlion$ ./main
real user ID =
effect user ID =

  从以上可以看到有效用户id发生了变化

 2. 新文件和目录的所有权

  新目录所有权与新文件的所有权的规则相同

  新文件的用户ID设置为进程的有效用户ID。组ID POSIX.1允许选择下列之一作为新文件的组ID

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

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

二、chmod和fchmod函数

  这两个函数使我们可以更改现存文件的存取许可权(权限)

#include <sys/types.h>
#include <sys/stat.h> int chmod(const char *pathname, mode_t mode); int fchmod(int fileds, mode_t mode); fileds即为文件句柄 返回值: 若成功则为0,若出错则为-1

  为了改变一个文件的权限,进程的有效用户ID必须等于文件的所有者,或者有root权限

  参数mode是下面所示逐位或运算

  

mode                说明明

S_ISUID            执行时设置 -用户-ID
S_ISGID 执行时设置 -组-ID
S_ISVTX 保存正文
S_IRWXU 用户(所有者)读、写和执行
S_IRUSR 用户(所有者)读
S_IWUSR 用户(所有者)写
S_IXUSR 用户(所有者)执行
S_IRWXG 组读、写和执行
S_IRGRP 组读
S_IWGRP 组写
S_IXGRP 组执行
S_IRWXO 其他读、写、和执行
S_IROTH 其他读
S_IWOTH 其他写
S_IXOTH 其他执行

   实例:

#include <stdio.h>
#include <sys/stat.h> int main(void)
{
struct stat statbuf; if (stat("foo", &statbuf) < ) {
fprintf(stderr, "stat error for foo\n");
} if (chmod("foo", (statbuf.st_mode & -S_IXGRP) | S_ISGID) < ) {
fprintf(stderr, "chmod error for foo\n");
} /* set absolute mode to "rw-r--r--" */
if (chmod("bar", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < ) {
fprintf(stderr, "chmod error for bar\n");
} return ;
}

三、 粘住位
  上一小节中S_ISVTX位,UNIX早期版本中,有一位被称为粘住位(sticky bit)。如果一个可执行程序文件的这一位被设置了,那么在该程序第一次执行并结束时,该程序正文的一个文本被保存在交换区。 (程序的正文部分是机器指令部分。 )这使得下次执行该程序时能较快地将其装入内存区。其原因是:在交换区,该文件是被连续存放的,而在一般的 U N I X文件系统中,文件的各数据块很可能是随机存放的。对于常用的应用程序,例如文本编辑程序和编译程序的各部分常常设置它们所在文件的粘住位。后来的UNIX版本称之为保存 -正文位( saved-text bit ),因此也就有了常数 S _ I S V T X。现今较新的UNIX系统大多数都具有虚存系统以及快速文件系统,所以不再需要使用这种技术。
S V R 4和4 . 3 + B S D中粘住位的主要针对目录。如果对一个目录设置了粘住位,则只有对该目录具有写许可权的用户并且满足下列条件之一,才能删除或更名该目录下的文件:
• 拥有此文件。
• 拥有此目录。
• 是超级用户。
目录/tmp和/var/spool/uucppublic是设置粘住位的候选者 —,这两个目录任何用户都可在其中创建文件。这两个目录对任一用户 (用户、组和其他 )的许可权通常都是读、写和执行。但是用户不应能删除或更名属于其他人的文件,为此在这两个目录的文件方式中都设置了粘住位。

四、 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,失败-.

  lchown更改符号连接本身的所有者,而不是符号链接所指向的文件

  根据_POSIX_CHOWN_RESTRICTED的值,POISX.1可以选择只有超级用户才能更改某个文件的所有者或者任何用户都能修改他们所拥有的文件的所有者。

  若_POSIX_CHOWN_RESTRICTED对指定的文件起作用,则

  (1) 只有超级用户进程能更改该文件的用户 ID。
  (2) 若满足下列条件,一个非超级用户进程可以更改该文件的组 ID:
    (a) 进程拥有此文件(其有效用户 ID等于该文件的用户 ID)。
    (b) 参数owner等于文件的用户ID,参数group等于进程的有效组ID或进程的添加组ID之一。
  这意味着,当 _ P O S I X _ C H O W N _ R E S T R I C T E D有效时,不能更改其他用户的文件的用户ID。你可以更改你所拥用的文件的组 ID,但只能改到你所属于的组。
  如果这些函数由非超级用户进程调用,则在成功返回时,该文件的设置 -用户-ID位和设置-组-ID位都被清除。

五、 文件长度
  stat结构的成员st_size包含了以字节为单位该文件的长度。此字段只对普通文件、目录、符号连接有意义。
  对于目录文件长度通常市一个数,例16或512的整数倍;
  对于符号连接,文件长度是实际文件的长度。

六、 文件截短
  有时我们需要在文件尾端截去一些数据以缩短文件,截短文件可以调用以下函数

#include <sys/types.h>
#include <unistd.h> int truncate(const char *pathname, off_t length);
int ftruncate(int filedes, off_t length);
返回值:成功0,失败-.

  这两个函数将文件的长度截短为length, 如果之前文件长度大于length,则超过length以外的数据就不再存取,如果以前的长度小于length,则其结果与系统有关。如果某个系统的处理是扩展该文件,则超过旧文件尾端与新文件尾端数据将读作0。

七、 文件系统

  传统的UNIX系统V文件系统,可以将一个硬盘分为多个分区,每个分区可以包含一个文件系统

  

    i节点是固定长度的记录项,包含有关文件的信息。

  

  • 上图中有两个目录指向同一i节点。每个i节点中都有一个连接计数,其值是指向该i节点的目录项数。只有当连接计数为0时才能删除该文件(也就是可以释放该文件所占的数据块)。在stat结构中连接计数包含在st_nlink中,其基本系统数据类型是nlink_t。这种连接称为硬连接。POSIX.1常数LINK_MAX指定了一个文件连接的最大值。
  • 另外一种连接是符号连接(symbolic link)。对于这种连接,该文件的实际内容(在数据块中)包含了该符号连接所指向的文件的名字。
  • i节点包含了所有与文件有关的信息:文件类型、文件存取许可权位、文件长度和指向该文件所占用的数据块的指针等。stat结构中大多数信息都取自i节点。只有两项数据存放在目录项中:文件名和i节点编号数。i节点编号数的数据类型是ino_t。
  • 因为目录项中的i节点编号数指向同一文件系统中的i节点,所以不能使一个目录项指向另一个文件系统的i节点。(所以ln命令不能跨文件系统)
  • 当在不更改文件系统的情况下为一个文件更名时,该文件的实际内容并未移动,只需构造一个指向现存i节点的新目录项。

  对于目录文件的连接计数字段:假如我们创建了一个testdir目录:

$ mkdir testdir

  下图显示了其结果,显式的显示了.和..目录项

  

  2549的i节点,其类型字段表示它是一个目录,其类型字段表示它是一个目录。而连接计数为2。任何一个叶目录(不包含任何目录(子目录)的目录)其连接计数总是2,数值2来自于命名该目录(testdir)的目录以及在该目录中的.项。编号为1267的i节点,其类型字段表示它是一个目录,而其连接计数则大于或等于3。它大于等于3的原因是至少有三个目录项指向它:一个是命名它的目录项,一个是在该目录中的.项,第三个是在自子目录testdir中的..项。

[APUE]文件和目录(上)的更多相关文章

  1. [APUE]文件和目录(中)

    一.link.unlink.remove和rename 一个文件可以有多个目录项指向其i节点.使用link函数可以创建一个指向现存文件连接 #include <unistd.h> int ...

  2. APUE 文件和目录

    文件和目录 Unix 所有的文件都对应一个 struct stat,包含了一个文件所有的信息. #include <sys/stat.h> struct stat { mode_t st_ ...

  3. [APUE]文件和目录(下)

    一.mkdir和rmdir函数 #include <sys/types.h> #include <sys/stat.h> int mkdir(const char *pathn ...

  4. APUE ☞ 文件和目录

    粘着位(Sticky Bit) S_ISVTX位被称为粘着位.如果一个可执行程序文件的这一位被设置了,程序第一次运行完之后,程序的正文部分的一个副本仍被保存在交换区(程序的正文部分是机器指令).这使得 ...

  5. (三) 一起学 Unix 环境高级编程 (APUE) 之 文件和目录

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  6. apue chapter 4 文件和目录

    1.文件信息结构体 struct stat{ mode_t st_mode; //file type and permissions ino_t st_ino; //i-node number (se ...

  7. apue学习笔记(第四章 文件和目录)

    本章将描述文件系统的其他特性和文件的性质. 函数stat.fstat.fstatat和lstat #include <sys/stat.h> int stat(const char *re ...

  8. asp.net上传文件时出现 404 - 找不到文件或目录。

    昨天客户网站反应上传较大文件时出现404-找不到文件或目录的错误.如图: 网站上给出的提示是上传文件不能超过50M,但是在38M和40M这样的文件都不能上传了,显然不对. 在网上查了很久,第一个是检查 ...

  9. [FTP] FTPClient--FTP操作帮助类,上传下载,文件,目录操作 (转载)

    点击下载 FTPClient.zip 这个类是关于FTP客户端的操作1.构造函数 2.字段 服务器账户密码3.属性4.链接5.传输模式6.文件操作7.上传和下载8.目录操作9.内容函数看下面代码吧 / ...

随机推荐

  1. java基础集合经典训练题

    第一题:要求产生10个随机的字符串,每一个字符串互相不重复,每一个字符串中组成的字符(a-zA-Z0-9)也不相同,每个字符串长度为10; 分析:*1.看到这个题目,或许你脑海中会想到很多方法,比如判 ...

  2. 一步步开发自己的博客 .NET版(11、Web.config文件的读取和修改)

    Web.config的读取 对于Web.config的读取大家都很属性了.平时我们用得比较多的就是appSettings节点下配置.如: 我们对应的代码是: = ConfigurationManage ...

  3. 使用webstorm+webpack构建简单入门级“HelloWorld”的应用&&引用jquery来实现alert

    使用webstorm+webpack构建简单入门级"HelloWorld"的应用&&构建使用jquery来实现 1.首先你自己把webstorm安装完成. 请参考这 ...

  4. 编写高质量代码:改善Java程序的151个建议(第7章:泛型和反射___建议106~109)

    建议106:动态代理可以使代理模式更加灵活 Java的反射框架提供了动态代理(Dynamic Proxy)机制,允许在运行期对目标类生成代理,避免重复开发.我们知道一个静态代理是通过主题角色(Prox ...

  5. iOS UITableView 与 UITableViewController

    很多应用都会在界面中使用某种列表控件:用户可以选中.删除或重新排列列表中的项目.这些控件其实都是UITableView 对象,可以用来显示一组对象,例如,用户地址薄中的一组人名.项目地址. UITab ...

  6. Atitit.研发管理软件公司的软资产列表指南

    Atitit.研发管理软件公司的软资产列表指南 1. Isv模型下的软资产1 2. 实现层面implet1 3. 规范spec层1 4. 法则定律等val层的总结2 1. Isv模型下的软资产 Sof ...

  7. vim环境变量配置、背景色配置

    我们使用vi或者vim的时候,如果想要显示行号,可能会这样做:切换到命令模式,然后输入set nu,再按回车键就显示了:还有就是咱们在编写程序的时候,有的时候会希望按下回车键后,光标不是每次都在行首, ...

  8. ASP.NET 5 Beta 7 版本

    在 VS2015 发布的同时,微软也发布了 ASP.NET 5 的路线图(详见ASP.NET 5 Schedule and Roadmap : https://github.com/aspnet/ho ...

  9. C#中实现并发的几种方法的性能测试

    C#中实现并发的几种方法的性能测试 0x00 起因 去年写的一个程序因为需要在局域网发送消息支持一些命令和简单数据的传输,所以写了一个C/S的通信模块.当时的做法很简单,服务端等待链接,有用户接入后开 ...

  10. To Java程序员:切勿用普通for循环遍历LinkedList

    ArrayList与LinkedList的普通for循环遍历 对于大部分Java程序员朋友们来说,可能平时使用得最多的List就是ArrayList,对于ArrayList的遍历,一般用如下写法: p ...