`
javasee
  • 浏览: 926759 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Linux环境(四)--临时文件与用户信息

阅读更多
临时文件

通常,程序需要以文件的形式使用临时存储。这也许是存储计算的中间结果,或者是在实际操作之前所做的文件拷贝备份。例如,一个数据程序在删除记录时会使用临时文件。文件会收集需要保存的数据库实体,然后在操作结束时,临时文件会成为新的数据库而原始的会被删除。

临时文件的大量使用隐藏了他的一个缺点。我们必须小心来确保程序会选择一个唯一的名字来使用临时文件。如果不是这样,因为Linux是一个多任务系统,也许会有另一个程序选择了相同的名字,而这两个彼此之间会相互影响。

一个唯一的临时文件名可以由tmpnam函数生成:

#include <stdio.h>
char *tmpnam(char *s);

tmpnam函数会返回一个与现存的文件不同的可用的文件名。如果字符串不为null,文件名也就会被写入其中。后续的tmpnam函数调用会覆盖返回值所用的表态存储区,所以如果tmpnam函数被调用多次,实际上是使用一个字符串参数。这个字符串假定至少为L_tmpnam字符长。一个程序中,tmpnam至多可以被调用TMP_MAX次,而且每次都会生成一个不同的文件名。

如果临时文件被立即使用,那么我们可以同时使用tmpfile函数来对其命名并且打开。这一点很重要,因为另一个程序会使用tmpnam返回的相同的名字创建一个文件。tmpfile函数避免这种情况的发生:

#include <stdio.h>
FILE *tmpfile(void);

tmpfile函数会返回一个指向唯一的临时文件的流指针。这个文件会为读和写打开,而且在所有到文件的引用被关闭以后,这个文件会被自动删除。

如果发生错误,tmpfile会返回一个空指针,并且设置errno变量。

试验--tmpnam与tmpfile

下面让我们实际的看一下这两个函数的使用:

#include <stdio.h>
int main()
{
char tmpname[L_tmpnam];
char *filename;
FILE *tmpfp;
filename = tmpnam(tmpname);
printf(“Temporary file name is: %s\n”, filename);
tmpfp = tmpfile();
if(tmpfp)
printf(“Opened a temporary file OK\n”);
else
perror(“tmpfile”);
exit(0);
}

当我们编译运行程序tmpnam.c时,我们可以看到由tmpnam生成的唯一的文件名:

$ ./tmpnam
Temporary file name is: /tmp/file2S64zc
Opened a temporary file OK

工作原理

这个程序调用tmpnam生成一个唯一文件名的临时文件。如果我们要使用这个临时文件,我们可以立即打开,从而来减小另一个程序会使用同一个文件名打开这个文件的风险。tmpfile调用会同时创建并打开一个临时文件,从而避免了这种风险。实际上,当编译一个使用这个函数的程序时,GNU C编译器也会给出一个使用tmpnam的警告。

老版本Unix系统还有另一个使用mktemp与mkstemp函数来生成临时文件名的方法。这些与被Linux系统支持,并且与tmpnam相似,所不同的是我们可以为临时文件名指定一个模板,这样我们就可以更好的控制其位置与名字:

#include <stdlib.h>
char *mktemp(char *template);
int mkstemp(char *template);

mktemp函数由指定的模板生成一个唯一的文件名。template必须以6个x开始。mktemp函数使用唯一可用的文件名字符来替换这些x字符。他返回一个指向所生成的字符串的指针,如果不可以生成一个唯一的文件名,则会返回一个null指针。

mkstemp函数在创建与打开临时文件方面与tmpfile相类似。文件名由与mktemp相同的方式生成的,但是返回的结果是一个打开的,底层文件描述符。

通常,我们应使用创建与打开函数tmpfile与mkstemp,而不是tmpnam与mktemp。

用户信息

所有了Linux程序,除了init之外,都是由其他程序或用户启动的。我们将会在第11章中了解更多的如何运行程序,或进程,交互等内容。用户通常由一个负责命令的shell来启动程序。我们已经看到,程序可以通过检测其环境变量以及读取系统时钟来确定其环境信息。一个程序也可以查看正使用他的用户信息。

当一个用户登陆进Linux系统时,他就有一个用户名与密码。如果这些通过验证,系统就会用户提供一个shell。通常,用户具有一个称之为UID的唯一的用户标识。Linux运行的所有程序都是运行在用户的行为以及与其相关的UID上的。

我们可以设置一个程序的运行,使其看起来就像是另一个用户启动的。当一个程序具有其UID的权限集合时,他的运行看起来就像是可执行文件的拥有者启动的。当执行su命令时,程序的运行看起来就像是超级用户启动的。然后他会验证用户的访问权限,将其UID改变为目标用户的UID,然后执行目标用户的登陆shell。这会允许一个程序的运行看起来就像是另一个不同的用户启动的,而这通常为系统管理员用来执行维护任务。

因为UID是用户标识的关键,我们就从这里开始讨论。

UID有其自己的类型--uid_t--在sys/types.h中进行了定义。他通常是一个小整数。一些是由系统预先定义的;另一个些是当有新用户要添加到系统时,由系统管理员创建的。通常,用户的UID值大于100。

#include <sys/types.h>
#include <unistd.h>
uid_t getuid(void);
char *getlogin(void);

getuid函数会返回与程序相关的UID值。这通常是启动程序的用户的UID值。

getlogin函数会返回与当前用户相关联的登陆名。

系统文件/etc/passwd包含一个处理用户帐户的数据库。每个用户一行,其中包含用户名,加密密码,用户标识UID,组标识GID,全名,主目录,以及默认的shell。下面是其中的一个例子:

neil:zBqxfqedfpk:500:100:Neil Matthew:/home/neil:/bin/bash

如果我们要编写一个程序来确定启动程序的用户UID,我们会对其进行扩展来查看密码文件以查找用户的登陆名与全名。我们并不推荐这样做,因为现在的类Unix系统都由使用简单的密码文件迁移到加强的系统安全。许多系统,包括Linux,有一个选项可以使用影子密码(shadwo password)文件,其中根本就不包含任何有用的加密密码信息(这通常存放在用户不可读取的/etc/shadow中)。正是因为这个原因,系统定义了一系列函数来为用户信息提供标准而高效的程序接口:

#include <sys/types.h>
#include <pwd.h>
struct passwd *getpwuid(uid_t uid);
struct passwd *getpwnam(const char *name);

密码数据库结构,passwd,定义在pwd.h中,包含下列成员:

成员 描述
char *pw_name 用户登陆名
uid_t pw_uid UID值
gid_t pw_gid GID值
char *pw_dir 用户主目录
char *pw_gecos 用户全名
char *pw_shell 用户默认shell

一些Unix系统会使用一个不同的名字来表示用户全名域:在一些系统上例如Linux为pw_gecos,而在另一个系统上为pw_comment。这就意味着我们并不推荐使用这个域。

getpwuid与getpwnam函数都会返回一个指向对应于一个用户的密码结构指针。对于getpwuid函数,用户是由UID标识的,而对于getpwnam函数,用户是由登陆来标识的。如果出错,他们都会返回一个空指针并且设置errno变量。

试验--用户信息

这里有一个程序,user.c,这会由密码数据库中得到一些用户信息:

#include <sys/types.h>
#include <pwd.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
uid_t uid;
gid_t gid;
struct passwd *pw;
uid = getuid();
gid = getgid();
printf(“User is %s\n”, getlogin());
printf(“User IDs: uid=%d, gid=%d\n”, uid, gid);
pw = getpwuid(uid);
printf(“UID passwd entry:\n name=%s, uid=%d, gid=%d, home=%s, shell=%s\n”,
pw->pw_name, pw->pw_uid, pw->pw_gid, pw->pw_dir, pw->pw_shell);
pw = getpwnam(“root”);
printf(“root passwd entry:\n”);
printf(“name=%s, uid=%d, gid=%d, home=%s, shell=%s\n”,
pw->pw_name, pw->pw_uid, pw->pw_gid, pw->pw_dir, pw->pw_shell);
exit(0);
}

其程序输出如下所示,也许在不同的系统上其输出结果会略有不同:

$ ./user
User is neil
User IDs: uid=500, gid=100
UID passwd entry:
name=neil, uid=500, gid=100, home=/home/neil, shell=/bin/bash
root passwd entry:
name=root, uid=0, gid=0, home=/root, shell=/bin/bash

工作原理

这个程序会调用getuid函数来得到当前用户的UID值。这个UID会用在getpwuid函数中来得到详细的密码文件信息。作为一个对照,我们演示了如何在getpwnam函数中指定用户名root来得到用户信息。

要遍历密码文件信息,我们可以使用getpwent函数。这会取得连续的文件实体:

#include <pwd.h>
#include <sys/types.h>
void endpwent(void);
struct passwd *getpwent(void);
void setpwent(void);

getpwent函数会依次返回每个用户信息。当到达文件结尾时,他会返回一个空指针。一旦搜索完毕所有的有效实体,我们可以使用endpwent函数来结束处理过程。setpwent函数可以在密码文件中重新设置指针使其指向文件的开头,这样当下次调用getpwent函数时可以重新开始遍历。这些函数的操作与我们在第3章所讨论的目录遍历函数opendir,readdir,closedir相类似。

用户与组标识可由其他的一个通常不用的函数来得到:

#include <sys/types.h>
#include <unistd.h>
uid_t geteuid(void);
gid_t getgid(void);
gid_t getegid(void);
int setuid(uid_t uid);
int setgid(gid_t gid);

我们可以查看系统手册页来得到关于组标识与有效用户标识的更为详细的内容,尽管我们会发现我们根本就不需要来操作这些函数。
分享到:
评论

相关推荐

    Linux环境搭建

    /tmp:这个目录是用来存放一些临时文件的。 /usr: 这是一个非常重要的目录,用户的很多应用程序和文件都放在这个目录下,类似与windows下的program files目录。 /var:这个目录中存放着在不断扩充着的东西,我们...

    UDP文件传送|开源|linux文件传送工具Legend

    Legend文件传送软件是运行在Linux下的一款自由软件,它提供了在linux环境下局域网文件传送的方法,目前次版本支持多个文件同时传送接收,添加临时用户,修改用户个性头像,修改自己昵称的功能。在软使用方面,以用户...

    Linux 完全定制指南(中文)

    5. 构建临时编译环境 简介 工具链技术说明 Binutils-2.16.1 - 第一遍 GCC-4.0.3 - 第一遍 Linux-Libc-Headers-2.6.12.0 Glibc-2.3.6 调整工具链 Tcl-8.4.13 Expect-5.43.0 DejaGNU-1.4.4 GCC-4.0.3 - 第二...

    linux文件传送工具Legend

    Legend文件传送软件是运行在Linux下的一款自由软件,它提供了在linux环境下局域网文件传送的方法,目前次版本支持多个文件同时传送接收,添加临时用户,修改用户个性头像,修改自己昵称的功能。在软使用方面,以用户...

    Linux常用的命令。。。。。

    group file 改文件的用户与所属组 chgrp group file 改文件所有组 usermod –G(g覆盖原组) grpup user改用户属于什么组(共享的组,即同时可以在多个组中) df 查看分区信息 sda 串口硬盘 —h 可读的 du 查看当前...

    linux文件传送工具Legend源码

    Legend文件传送软件是运行在Linux下的一款自由软件,它提供了在linux环境下局域网文件传送的方法,目前次版本支持多个文件同时传送接收,添加临时用户,修改用户个性头像,修改自己昵称的功能。在软使用方面,以用户...

    Linux指令一周通 (技术图书大系).azw3

    1.72 tmpwatch指令:删除临时文件 1.73 touch指令:更改文件/目录时间 1.74 umask指令:指定在建立文件时权限掩码 1.75 umount指令:卸除文件系统 1.76 unarj指令:解压缩文件 1.77 uncompress指令:解压缩.z文件 ...

    LINUX系统管理白皮书

    8.5 临时禁用用户 242 第9章 备份 243 9.1 备份的重要性 243 9.2 选择备份媒体 243 9.3 选择备份工具 244 9.4 简单备份 244 9.4.1 如何利用tar进行备份 245 9.4.2 如何利用tar恢复文件 246 9.5 多级备份 247...

    Linux操作系统基础教程

    Linux 是在 1991 年发展起来的与 UNIX兼容的操作系统,可以免费使用,它的源代码 可以自由传播且可任人修改、充实、发展,开发者的初衷是要共同创造一个完美、理想并 可以免费使用的操作系统。 我们并不能使同学...

    Linux 多tomcat服务 统一安装 统一部署 工具 shell编写 自动化部署与统一安装升级 - 类ansible工具

    Temp 存放临时文件 临时文件将及时删除无任何冗积 Workapp 存放war包 上传war包 3 功能描述 3.1 获取配置文件 通过本系统获取配置文件非常简单,只需用户提供服务列表,其他无需操作。服务列表如下: ...

    LINUX与UNIX SHELL编程指南(很全)

    第1章 文件安全与权限 1 1.1 文件 1 1.2 文件类型 2 1.3 权限 2 1.4 改变权限位 4 1.4.1 符号模式 4 1.4.2 chmod命令举例 5 1.4.3 绝对模式 5 1.4.4 chmod命令的其他例子 6 1.4.5 可以选择使用符号模式或绝对模式 7 ...

    Linux服务器命令.doc

    6 查看环境变量 6 进入到用户的起始目录 6 退出并重新登陆 6 ftp命令 6 文件拷贝命令 7 拷贝文件夹命令 7 查看进程打开文件数 7 查看临时目录某个文件大小 7 查看环境变量 7 Linux清理mysql日志 7 1.进入路径查看...

    UNIX环境高级编程_第2版.part2

    5.13 临时文件127 5.14 标准i/o的替代软件130 5.15 小结130 习题130 第6章系统数据文件和信息133 6.1 引言133 6.2 口令文件133 6.3 阴影口令136 6.4 组文件137 6.5 附加组id138 6.6 实现的区别139 6.7 ...

    Linux程序设计 第4版.haozip01

    第4章 linux环境 114 4.1 程序参数 114 4.1.1 getopt 116 4.1.2 getopt_long 118 4.2 环境变量 120 4.2.1 环境变量的用途 122 4.2.2 environ变量 122 4.3 时间和日期 123 4.4 临时文件 129 4.5 用户信息 ...

    nServer-v2.1023[FTP + MYSQL + HTTP + PHP(FCGI)]

    - MySQL数据、生成配置文件、模块临时文件均放入mydata目录,方便设置安全权限 2012年05月25日 - 配置文件放到到anrip/config目录 - 控制台代码模块化 2012年05月20日 - 更新PHP版本为5.4.3 - 优化配置文件编译...

Global site tag (gtag.js) - Google Analytics