APUE笔记---第六章系统数据文件和信息操作

APUE笔记—第六章系统数据文件和信息操作

1. 口令文件

Linux系统口令文件包含以下字段:

struct passwd {
    char   *pw_name;       /* username */
    char   *pw_passwd;     /* user password */
    uid_t   pw_uid;        /* user ID */
    gid_t   pw_gid;        /* group ID */
    char   *pw_gecos;      /* user information */
    char   *pw_dir;        /* home directory */
    char   *pw_shell;      /* shell program */
};
//The passwd structure is defined in <pwd.h>

口令文件是/etc/passwd,是一个ASCLL文件,/etc/passwd 为每个用户账户包含一行,包含使用冒号 (“:”)

1.1函数getpwuid和getpenam可以获取口令文件项的函数

如果给出登录名或者用户ID就可以获取相关项。

#include <sys/types.h>
#include <pwd.h>

struct passwd *getpwnam(const char *name);
struct passwd *getpwuid(uid_t uid);
//返回值:若成功,返回指针,若出错,返回NULL
  • getpwuid函数由ls(1)程序使用,将inode中的数字用户ID映射为用户登录名;在键入登录名时,getpwnam函数由login(1)程序使用。
  • 这两个函数都返回一个指向passwd结构的指针,passwd通常是函数内部的静态变量。

1.2 函数getpwent查看登录名或用户的ID

#include <sys/types.h>
#include <pwd.h>

struct passwd *getpwent(void);
//返回值:若成功,返回指针,若出错或到达文件末尾,返回NULL
void setpwent(void);
void endpwent(void);
  • getpwent函数,返回口令文件中的下一个记录项,并填写到passwd结构中返回。
  • setpwent函数,反绕它所使用的文件,就是指到口令文件的开头。
  • endpwent函数,关闭这些文件。

2. 阴影口令

加密口令是经过单向加密算法处理过的用户口令副本,系统将加密口令存放在另一个通常成为阴影口令(shadow passwd)的文件里,文件至少包含用户名和加密口令,其他信息如下:

struct spwd {
    char *sp_namp;     /* 登录名 Login name */
    char *sp_pwdp;     /* 加密口令 Encrypted password */
    long  sp_lstchg;   /* 上次更改口令经过的时间 Date of last change
                          (measured in days since
                          1970-01-01 00:00:00 +0000 (UTC)) */
    long  sp_min;      /* 经过多少天允许更改 Min # of days between changes */
    long  sp_max;      /* 要求更改还剩天数 Max # of days between changes */
    long  sp_warn;     /* 超期警告天数 # of days before password expires
                          to warn user to change it */
    long  sp_inact;    /* 账户不活动之前还剩的天数 # of days after password expires
                          until account is disabled */
    long  sp_expire;   /* 账户超期天数 Date when account expires
                          (measured in days since
                          1970-01-01 00:00:00 +0000 (UTC)) */
    unsigned long sp_flag;  /* 保留 Reserved */
};
//The shadow password structure is defined in <shadow.h> 

阴影口令文件一般用户不应该读取,少数程序需要访问加密口令,如login(1)和passwd(1),这些程序常常是设置用户ID为root的程序。

2.1 函数getspnam和getspent可以用于访问阴影口令文件

#include <shadow.h>

struct spwd *getspnam(const char *name);
struct spwd *getspent(void);
//返回值:若成功,返回指针,若出错,返回NULL
void setspent(void);
void endspent(void);

3. 组文件

Linux组文件包含由以下字段:

struct group {
    char   *gr_name;        /* group name */
    char   *gr_passwd;      /* group password */
    gid_t   gr_gid;         /* group ID */
    char  **gr_mem;         /* 指向各用户名指针的数组NULL-terminated array of pointers
                               to names of group members */
};
//The group structure is defined in <grp.h>

字段是一个数组指针,其中每一个指针指向一个属于该组的用户名。该数组以null结尾。

3.1 函数getgrgid和getgrnam查看组名或组ID

 #include <sys/types.h>
 #include <grp.h>

 struct group *getgrnam(const char *name);
 struct group *getgrgid(gid_t gid);
//返回值:若成功,返回指针,若出错,返回NULL

如同口令文件操作一样,函数返回一个静态变量的指针,在每次调用函数时重写该静态变量。

3.2 函数getgrent搜索整个组文件

#include <sys/types.h>
#include <grp.h>

struct group *getgrent(void);
//返回值:若成功,返回指针,若出错或到达文件末尾,返回NULL
void setgrent(void);
void endgrent(void);
  • setgrent函数打开组文件并反绕它。
  • getgrent函数从组文件读写一个记录,如果文件没有打开则打开它。
  • endgrent函数关闭组文件。

4. 附属组ID

附属组的优点:一个用户可以参与多个项目,因此也就可以设置多个组。

 #include <sys/types.h>
 #include <unistd.h>

 int getgroups(int size, gid_t list[]);
//返回值:若成功,返回附属组ID数量,若出错返回-1

 #include <grp.h>

 int setgroups(size_t size, const gid_t *list);
 //返回值:若成功,返回0,如出错,返回-1

#include <sys/types.h>
#include <grp.h>

int initgroups(const char *user, gid_t group);
 //返回值:若成功,返回0,如出错,返回-1
  • getgroups函数将进程所属用户的各附属组ID填写到数组list中,写入数组的附属组ID最多size个,实际填写数函数返回。
  • setgroups函数可由超级用户调用以便调用进程设置附属组ID表。list是组ID表,size说明了数组中的元素数。
  • 通常只有initgroups函数调用setgroups,initgroups函数读整个组文件,然后对username确定其组的成员关系,调用setgroups函数初始化附属组ID表。除了在组文件中找到username是成员的所有组,initgroups也在附属组ID表中包括group,group是username在口令文件中的组ID。

5. 其他数据文件

说明数据文件头文件结构附加的键搜索函数
口令/etc/passwd< pwd.h >passwdgetpwnam、getpwuid
/etc/group< grp.h >groupgetgrnam、getgrgid
阴影/etc/shadow< shadow.h >spwdgetspnam
主机/etc/hosts< netdb.h >hostentgetnameinfo、getaddrinfo
网络/etc/networks< netdb.h >netentgetnetbyname、getnetbyaddr
协议/etc/protocols< netdb.h >protoentGetprotobyname、getprotobynumber
服务/etc/services< netdb.h >serventgetservbyname、getservbyport

一般情况下,对于每个数据文件至少有3个函数

  • get函数:对下一个记录,如果需要,还打开文件。
  • set函数:打开相应数据文件,然后反绕该文件。
  • end函数:关闭相应数据文件。

6. 系统标识

uname函数,返回与主机和操作系统有关的信息。

#include <sys/utsname.h>

int uname(struct utsname *buf);
//返回值:若成功,返回非负值,若出错,返回-1

通过该函数的参数向其传递一个struct utsname结构的地址,然后填写结构。

struct utsname {
    char sysname[];    /* Operating system name (e.g., "Linux") */
    char nodename[];   /* Name within "some implementation-defined
                          network" */
    char release[];    /* Operating system release (e.g., "2.6.28") *

    char version[];    /* Operating system version */
    char machine[];    /* Hardware identifier */
#ifdef _GNU_SOURCE
    char domainname[]; /* NIS or YP domain name */
#endif
};
//每个字符串都是以null字节结尾,该结构通常用uname(1)命令打印

6.1 gethostname函数返回主机名

改名字通常就是TCP/IP网络上的主机的名字

#include <unistd.h>

int gethostname(char *name, size_t len);
int sethostname(const char *name, size_t len);
//返回值:若成功,返回0;若出错,返回-1
  • gethostname函数参数len指定name缓冲区长度,若缓冲区空间足够,则通过name返回的字符串以null结尾,若空间不够,则没有说明通过name返回的字符串是否以null结尾。
  • sethostname函数由超级用户设置主机名。

7. 时间和日期例程

Linux内核提供的基本时间服务是计算自协调时间时(UTC)公园1970年1月1日00:00:00这一特定时间以经过的描述

7.1 time函数返回当前时间和日期

 #include <time.h>

 time_t time(time_t *tloc);
//返回值:若成功,返回时间值,若出错,返回-1

时间值作为函数值返回。如果参数非空,则时间值保存在由calptr指向的单元内。

7.2 关于指定时钟时间

#include <time.h>

int clock_getres(clockid_t clk_id, struct timespec *res);
int clock_gettime(clockid_t clk_id, struct timespec *tp);
int clock_settime(clockid_t clk_id, const struct timespec *tp);
//返回值:若成功,返回0,若出错,返回-1

struct timespec {
    time_t   tv_sec;        /* seconds */
    long     tv_nsec;       /* nanoseconds */
};
  • clock_gettime函数可用于获取指定时钟的时间,精度比time函数高
  • clock_getres函数把参数tp指向的timespec结构初始化为与clk_id参数对应的时钟精度。
  • clock_settime函数用于设置特定的时钟。

7.3 函数localtime和gmtime

这两个函数将日历时间转换成分解的时间,并存放在tm结构中

struct tm {
    int tm_sec;    /* Seconds (0-60) */
    int tm_min;    /* Minutes (0-59) */
    int tm_hour;   /* Hours (0-23) */
    int tm_mday;   /* Day of the month (1-31) */
    int tm_mon;    /* Month (0-11) */
    int tm_year;   /* Year - 1900 */
    int tm_wday;   /* Day of the week (0-6, Sunday = 0) */
    int tm_yday;   /* Day in the year (0-365, 1 Jan = 0) */
    int tm_isdst;  /* Daylight saving time */
};

#include <time.h>

struct tm *gmtime(const time_t *timep);
struct tm *localtime(const time_t *timep);
//返回值:指向分解的tm结构的指针,若出错,返回NULL
  • localtime将日历时间装换成本地时间(考虑本地时区和夏令时标志)
  • gmtime函数将日历转换成协调统一的时间的年、月、日、时、分、秒、周日分解结构。

mktime函数以本地时间的年、月、日等作为参数,将其装换成time_t值

time_t mktime(struct tm *tm);
//返回值:若成功,返回日历时间,若出错,返回-1

函数strftime是一个类似于printf的时间值函数,可以产生特定的字符串

#include <time.h>

size_t strftime(char *s, size_t max, const char *format,  const struct tm *tm);
//返回值:若有空间,返回存入数组的字符数,否则,返回0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值