`

系统数据文件操作函数介绍

阅读更多
    UNIX 中有个和用户登录密切相关的口令文件 /etc/passwd,POSIX.1 定义了下面两个可获取口令文件项的函数。
#include <pwd.h>
struct passwd *getpwuid(uid_t uid);
struct passwd *getpwnam(const char *name);
                        /* 返回值:若成功,都返回指针;否则,都返回 NULL */

struct passwd{
    char    *pw_name;       // 用户名
    char    *pw_passwd;     // 加密口令
    uid_t   *pw_uid;        // 数值用户 ID
    gid_t   *pw_gid;        // 数值组 ID
    char    *pw_gecos;      // 注释字段
    char    *pw_dir;        // 初始工作目录
    char    *pw_shell;      // 初始 shell(用户程序)
    char    *pw_class;      // 用户访问类
    time_t  *pw_change;     // 下次更改口令时间
    time_t  *pw_expire;     // 账户有效期时间
};

    getpwuid 函数由 ls 程序使用,它将 i 节点中的数字用户 ID 映射为用户登录名。而在键入登录名时,getpwnam 函数由 login 程序使用。这两个函数都返回一个指向 passwd 结构的指针,该结构包含了组成 /etc/passwd 文件的各个字段,它通常是函数内部的静态变量,所以只要调用任一相关函数,其内容就会被重写。
    如果要查看的只是登录名或用户 ID,那么这两个函数能满足要求,而如果要查看整个口令文件时,则可使用 XSI 扩展中提供的下列 3 个函数。
#include <pwd.h>
struct passwd *getpwent(void);
           /* 返回值:若成功,返回指针;若出错或到达文件尾端,返回 NULL */
void setpwent(void);
void endpwent(void);

    调用 getpwent 时,它返回口令文件中的下一个记录项。每次调用此函数都会重写 passwd 结构。在第一次调用时,它就会打开它所使用的各个文件。函数 setpwent 打开(如果文件尚未打开)并反绕它所使用的文件,endpwent 则关闭这些文件。在使用 getpwent 查看完口令文件后,一定要调用 endpwent 关闭来这些文件。因为 getpwent 知道什么时间应当打开它所使用的文件(第一次被调用时),但是却不知道何时关闭它们。
    下面是一个利用这 3 个函数实现的一个 getpwnam 程序。
#include <pwd.h>
#include <stddef.h>
#include <string.h>

struct passwd *
getpwnam(const char *name){
	struct passwd	*ptr;

	setpwent();
	while((ptr=getpwent()) != NULL){
		if(strcmp(name, ptr->pw_name) == 0)
			break;
	}
	endpwent();
	return ptr;		// ptr is NULL if no match found.
}

    在函数开始处调用 setpwent 是自我保护性的措施,以便确保如果在此之前已经调用 getpwent 打开了有关文件的情况下,反绕这些文件使它们定位到开始处。getpwnam 和 getpwuid 完成后不应使有关文件仍处于打开状态,所以要调用 endpwent 关闭它们。
    不过为了安全,加密口令一般是存放在阴影口令文件 /etc/shadow 中,该文件至少要包含用户名和加密口令,与该口令相关的其它信息也可存放在该文件中。一般用户是不可以读取该文件的,仅有少数几个程序需要访问加密口令,如 login 和 passwd 等,这些程序常常是设置用户 ID 为 root 的程序。在 Linux 3.2.0 和 Solaris 10 中,与访问口令文件的一组函数相类似,有另一组函数可用于访问阴影口令文件(在 FreeBSD 8.0 和 Mac OS X 10.6.8 中,没有阴影口令结构,附加的账户信息存放在口令文件中)。
#include <shadow.h>
struct spwd *getspnam(const char *name);
struct spwd *getspent(void);
                  /* 返回值:若成功,都返回指针;否则,都返回 NULL */
void setspent(void);
void endspent(void);

struct spwd{
    char    *sp_namp;        // 用户登录名
    char    *sp_pwdp;        // 加密口令
    int     sp_lstchg;       // 上次更改口令以来经过的时间
    int     sp_min;          // 经多少天后允许修改
    int     sp_max;          // 要求更改尚余天数
    int     sp_warn;         // 超期警告天数
    int     sp_inact;        // 账户不活动之前尚余天数
    int     sp_expire;       // 账户超期天数
    unsigned int sp_flag;    // 保留
};

    UNIX 中的每个账户除了这些个人信息外,还拥有所属组的相关信息,这些信息保存在 /etc/group 文件中。UNIX 也提供了类似上面的一组函数来操作该文件。
#include <grp.h>
struct group *getgrgid(gid_t gid);
struct group *getgrnam(const char *name);
                         /* 返回值:若成功,都返回指针;否则,都返回 NULL */

struct group *getgrent(void);
                  /* 返回值:若成功,返回指针;若出错或到达文件尾端,返回 NULL */
void setgrent(void);
void endgrent(void);

struct group{
    char *gr_name;            // 组名
    char *gr_passwd;          // 加密口令
    int gr_gid;               // 数值组 ID
    char **gr_mem;            // 指向各用户名指针的数组,以 null 指针结尾
};

    当用户登录时,系统就按口令文件记录项中的数值组 ID 赋给他实际组 ID(可以在任何时候使用 newgrp 更改组 ID,执行不带参数的 newgrp 则可返回到原来的组)。在 4.2 BSD 引入了附属组 ID 的概念后,一个账户还可属于多至 16(由 NGROUPS_MAX 规定)个另外的组。所以文件访问权限检查时不仅将进程的有效组 ID 与文件的组 ID 相比较,而且也将所有附属组 ID 与文件的组 ID 进行比较。
    可使用下面 3 个函数来获取和设置附属组 ID。
#include <unistd.h>
int getgroups(int gidsetsize, gid_t grouplist[]);
                        /* 返回值:若成功,返回附属组 ID 数量;否则,返回 -1 */
#include <grp.h>        // on Linux
#include <unistd.h>     // on FreeBSD, Mac OS X, and Solaris
int setgroups(int ngroups, const gid_t groupslist[]);
#include <grp.h>        // on Linux and Solaris
#include <unistd.h>     // on FreeBSD and Mac OS X
int initgroups(const char *username, gid_t basegid);
                         /* 返回值:若成功,都返回 0;否则,都返回 -1 */

    getgroups 将进程所属用户的各附属组填写到数组 grouplist 中,填写入的附属组 ID 数最多为 gidsetsize 个,实际填写的附属组 ID 数由函数返回。特殊地,如若 gidsetsize 为 0,则函数只返回附属组 ID 数,而不修改 grouplist(这使得调用者可以确定 grouplist 的长度,以便进行分配)。
    setgroups 可由超级用户调用以便为调用进程设置附属组 ID 表。grouplist 是组 ID 数组,而 ngroups 说明了数组中的元素数,ngroups 的值不能大于 NGROUPS_MAX。
    通常,只有 initgroups 函数调用 setgroups,initgroups 使用 getgrent 等函数读整个组文件,然后对 username 确定其组的成员关系,然后调用 setgroups,以便为该用户初始化附属组 ID 表。除了在组文件中找到 username 是成员的所有组,initgroups 也在附属组 ID 表中包括了 basegid,basegid 是 username 在口令文件中的组 ID。只有 login 等少数几个程序会调用 initgroups 函数。
    除了口令文件和组文件外,UNIX 系统还使用很多其他文件。比如,记录各网络服务器所提供服务的数据文件 /etc/services,记录协议信息的数据文件 /etc/protocols,以及记录网络信息的数据文件 /etc/networks 等。这些数据文件一般都至少提供了类似的 get、set 和 end 函数。如果数据文件支持某种形式的键搜索,则也提供类似于口令文件中的 getpwnam 和 getpwuid 之类的可搜索具有指定键的记录的例程。下表列出了 UNIX 常用的这类例程。
  • 大小: 20 KB
分享到:
评论

相关推荐

    C文件操作函数

    以下是一些主要的C文件操作函数的详细说明: 1. `clearerr(stream)`:这个函数用于清除文件流的错误标志和结束标志。当你发现文件流可能存在错误但不希望立即关闭文件时,可以调用`clearerr()`,它不会产生任何实际...

    常用C语言文件操作函数大全.doc

    C语言文件操作函数大全 C语言中文件操作函数是指程序中对文件进行读、写、关闭、检测等操作的函数。这些函数都是C语言标准库stdio.h中的一部分,用于实现文件的输入/输出操作。 1. clearerr() 函数 函数说明:...

    c语言文件操作函数

    C语言文件操作函数是C语言标准库中用于进行文件读写、控制和管理的一组函数,这些函数为程序提供了访问和操作磁盘文件的能力。在进行C语言文件操作时,通常要涉及到几个基本步骤,包括打开文件、读写文件、关闭文件...

    文件操作基础API函数

    在 Windows 操作系统中,文件操作可以分为文件的创建、打开、读取、写入、关闭等几个过程。 首先,需要了解文件操作的基本概念。文件操作的基本概念包括文件的创建、文件的打开、文件的读取、文件的写入、文件的...

    C语言文件操作函数大全.doc

    这里我们详细讨论几个重要的C语言文件操作函数。 1. `clearerr()` 函数:这个函数用于清除文件流的错误标志。当你调用`clearerr(stream)`时,它会将指定文件流`stream`的错误状态清零,这意味着之后的文件操作将...

    c语言文件操作函数总结

    本文将全面总结C语言中的文件操作函数,帮助你深入理解和掌握这些核心概念。 1. **文件操作的基础** - **文件流的概念**:在C语言中,文件被看作是字节流,我们通过`stdio.h`库中的函数来处理这些字节流。 - **...

    FatFs 文件系统-API函数详解

    以上介绍了FatFs文件系统的两个核心函数:`f_mount` 和 `f_open`。通过这些函数,开发人员可以轻松地在嵌入式系统中实现基本的文件系统操作。此外,FatFs还提供了其他许多实用的API函数,如`f_close`、`f_read`、`f_...

    C语言文件操作函数大全

    C语言文件操作函数大全 本文档总结了C语言中常用的文件操作函数,包括文件流错误旗标清除、文件关闭、文件描述词转换、文件流是否读到文件尾检查、缓冲区更新、从文件中读取一个字符、从文件中读取一字符串等操作。...

    Linux-c常用文件操作函数.doc

    Linux 操作系统中的文件操作函数是指在 C 语言中用来处理文件的函数,这些函数都是通过头文件 `stdio.h` 定义的。下面是常用的文件操作函数: 1. `clearerr` 函数:清除文件流的错误旗标 `clearerr` 函数的功能是...

    c文件读写函数

    在 Linux 操作系统中,C 语言提供了多种文件读写函数,包括非标准文件读写函数和标准文件读写函数。下面将对这两种类型的文件读写函数进行详细介绍。 非标准文件读写函数 非标准文件读写函数主要用于读写二进制...

    操作系统c语言模拟文件管理系统

    `fclose()`函数则用于结束文件操作,释放系统资源。 4. **文件读取和写入**:`fread()`和`fwrite()`用于从文件读取和写入数据,而`fgets()`和`fprintf()`则适用于读取和写入字符串。在写入时,需要确保有足够的磁盘...

    linux文件操作 linux操作系统 文件操作 常用命令

    在Linux操作系统中,文件操作是日常任务的核心部分。文件操作主要通过系统调用和应用程序编程接口(API)来实现,这些接口提供了与操作系统内核交互的途径。在Linux中,系统调用是一组特殊的接口,允许用户程序请求...

    操作系统课程设计报告Linux二级文件系统设计.doc

    本报告详细介绍了 Linux 操作系统下的二级文件系统设计报告,涵盖了文件系统的设计目的、设计容、实验环境、设计思路、数据结构、主要函数等方面的内容,旨在帮助读者更好地理解文件系统的基本功能和实现机制。

    操作系统实验报告-文件系统

    5. **关闭文件**:完成文件操作后,调用`close()`函数关闭文件流,释放资源。 6. **文件删除**:在操作系统层面,可以使用`remove()`函数删除文件。在模拟文件系统时,我们需要维护一个文件元数据结构,如文件名、...

    linux文件操作系统

    【Linux 文件操作系统】是Linux操作系统中的核心组成部分,它负责管理和控制系统的文件系统,提供对文件的创建、读取、写入、删除等基本操作。在Linux环境下,C语言编程经常被用于实现对文件系统的交互,因为C语言...

    介绍API函数的中文帮助文件

    Windows操作系统提供了大量的API函数,使得程序员能够实现各种复杂的任务,如文件操作、网络通信、用户界面构建等。本篇文章将围绕“介绍API函数的中文帮助文件”这一主题,深入探讨API函数的基本概念、使用方法以及...

    delphi 文件目录操作函数

    除了这些基本的文件操作函数,Delphi还提供了其他高级功能,如目录操作(如`DirectoryExists`、`CreateDir`、`DeleteDir`)、文件属性查询(如`GetFileAttributes`、`SetFileAttributes`)以及文件搜索(如`Find...

    操作系统模拟实现单级目录的文件系统

    这个系统能够完成基本的文件操作,如创建、删除、读取和写入。 首先,我们需要理解文件系统的概念。文件系统是操作系统用于组织和存储数据的一种方式,它定义了文件如何在磁盘或其他存储介质上存储和检索。在单级...

    图形方面文件操作函数

    在计算机科学领域,图形文件操作函数是用于处理各种图像文件的核心工具。这些函数涉及读取、写入、编辑和转换图像文件,使我们能够在不同应用和系统之间共享和使用图像。在本文中,我们将深入探讨“图形方面文件操作...

Global site tag (gtag.js) - Google Analytics