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

2024-08-22 04:38

本文主要是介绍APUE读书笔记-第六章 系统数据文件和信息,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

昨天看完了,今天来看看第六章。感觉第六章的内容不是非常重要。简单看看吧

 6.2 口令文件

口令文件其实就是/etc文件夹下的passwd文件,但处于安全性的考虑,我们无法直接读取它。就是通过直接限制权限的方式对其进行保护,passwd文件具体权限如下:

-rw-r--r-- 1 root root

可以看到只有root用户具有读写权限,与root同组的用户与其他用户仅具有读权限。

不过为了解决以上问题,Linux中给出了一系列数据结构与函数帮助我们操纵口令文件,首先是关键数据结构,定义位于/include/pwd.h

struct passwd
{char *pw_name;		/* Username.  */char *pw_passwd;		/* Password.  */__uid_t pw_uid;		/* User ID.  */__gid_t pw_gid;		/* Group ID.  */char *pw_gecos;		/* Real name.  */char *pw_dir;			/* Home directory.  */char *pw_shell;		/* Shell program.  */
};

给出用户登录名与数值用户ID后,通过以下两个函数就能获得passwd结构体,该结构体中包含有我们需要的信息。

#include <pwd.h>
extern struct passwd *getpwuid (__uid_t __uid);
extern struct passwd *getpwnam (const char *__name);

getpwuid函数由ls程序使用。getpwnam函数由login程序使用。passwd结构通常是函数内部的静态变量,只要调用任一相关函数,其内容就会被重写。

以上两个函数仅能查看某一个用户的口令信息,但如果不知道其他用户的登录名或数值ID,则无法获得这些信息。因此Linux中又给出了以下三个函数来查看整个口令文件。

#include <pwd.h>
extern struct passwd *getpwent (void); //若成功,返回指针,指向口令文件中的下一个记录项。第一次调用时,它打开所使用的各个文件。
extern void setpwent (void); //回到口令文件开头
extern void endpwent (void); //关闭口令文件

6.3节中所提到的阴影口令文件感觉与口令文件的内容并没有多大的差距,在此就先不深入研究了,以后遇到了再说。

6.4组文件

还是相同的思路,如果用户程序想访问组相关信息,这些信息虽然存放在/etc/group中,但还是由于权限的限制导致一般的用户无法直接访问这一问题。Linux中给出的方法是通过相关的函数与数据结构进行访问,首先来看关键数据结构。

struct group{char *gr_name;		/* Group name.	*/char *gr_passwd;		/* Password.	*/__gid_t gr_gid;		/* Group ID.	*/char **gr_mem;		/* Member list.	*/};

通过组名与数值ID可以获得这一数据结构。

#include <grp.h>
extern struct group *getgrgid (__gid_t __gid);
extern struct group *getgrnam (const char *__name);

搜索整个口令文件则需要以下三个函数,思路也是一样的。

#include <grp.h>
extern void setgrent (void);
extern void endgrent (void);
extern struct group *getgrent (void);

6.5 附属组

引入附属组的一个原因是:一个用户会参与多个项目,因此也就要同时属于多个组。为了解决上述问题,4.2BSD引入了附属组的概念,用户不再简单的属于一个组,也可以属于多至16个另外的组。

用户程序可通过以下函数获取和设置附属组ID。

extern int getgrouplist (const char *__user, __gid_t __group,__gid_t *__groups, int *__ngroups);
extern int setgroups (size_t __n, const __gid_t *__groups) __THROW;
extern int initgroups (const char *__user, __gid_t __group);

其中setgroups需要超级用户权限调用,而由于initgroups需要调用setgroups,因此initgroups也同样只有超级用户才能调用。

6.7其他数据文件

除了上面提到的口令文件和组文件,Linux还有多个具有类似概念的文件。书中给出了一个表对上述内容进行总结。

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

6.8登录账户记录

Linux通过“/var/run/utmp”对当前登录到系统的各个用户进行记录;通过“/var/log/wtmp”文件跟踪各个登录和注销事件。以上两个文件是二进制文件,不能直接打开。

Linux通过以下几个函数与数据结构对以上两个文件进行修改。首先来看看关键数据结构,定义位于/usr/include/x86_64-linux-gnu/bits/utmp.h中

struct utmp
{short int ut_type;		/* Type of login.  */pid_t ut_pid;			/* Process ID of login process.  */char ut_line[UT_LINESIZE];	/* Devicename.  */char ut_id[4];		/* Inittab ID.  */char ut_user[UT_NAMESIZE];	/* Username.  */char ut_host[UT_HOSTSIZE];	/* Hostname for remote login.  */struct exit_status ut_exit;	/* Exit status of a process markedas DEAD_PROCESS.  */
/* The ut_session and ut_tv fields must be the same size when compiled32- and 64-bit.  This allows data files and shared memory to beshared between 32- and 64-bit applications.  */
#ifdef __WORDSIZE_TIME64_COMPAT32int32_t ut_session;		/* Session ID, used for windowing.  */struct{int32_t tv_sec;		/* Seconds.  */int32_t tv_usec;		/* Microseconds.  */} ut_tv;			/* Time entry was made.  */
#elselong int ut_session;		/* Session ID, used for windowing.  */struct timeval ut_tv;		/* Time entry was made.  */
#endifint32_t ut_addr_v6[4];	/* Internet address of remote host.  */char __glibc_reserved[20];		/* Reserved for future use.  */
};

再来看看相关函数:

extern void login (const struct utmp *__entry) __THROW;

登录时,login程序填写此类型结构,然后将其写入到utmp文件中,同时也将其添写到wtmp文件中。通过login函数的参数也可以验证这一点。

注销时,init进程将utmp文件中相应的记录擦除,并将一个新记录添写到wtmp文件中。

6.9 系统标识

POSIX.1 定义了uname函数,它返回与主机和操作系统有关的信息。定义位于/usr/include/x86_64-linux-gnu/sys/utsname.h。

extern int uname (struct utsname *__name) __THROW; //__name即是输入参数也是输出参数。若程序运行成功返回非负值,若出错返回-1。

参数定义如下:

struct utsname{/* Name of the implementation of the operating system.  */char sysname[_UTSNAME_SYSNAME_LENGTH];/* Name of this node on the network.  */char nodename[_UTSNAME_NODENAME_LENGTH];/* Current release level of this implementation.  */char release[_UTSNAME_RELEASE_LENGTH];/* Current version level of this release.  */char version[_UTSNAME_VERSION_LENGTH];/* Name of the hardware type the system is running on.  */char machine[_UTSNAME_MACHINE_LENGTH];#if _UTSNAME_DOMAIN_LENGTH - 0/* Name of the domain of this node on the network.  */
# ifdef __USE_GNUchar domainname[_UTSNAME_DOMAIN_LENGTH];
# elsechar __domainname[_UTSNAME_DOMAIN_LENGTH];
# endif
#endif};

utsname结构体中的信息通常可用uname命令打印。我的机器上uname的返回结果非常简单

Linux

仅此而已,再无其他。

还有一个返回主机名的函数,该名字通常就是TCP/IP网络上主机的名字。

extern int gethostname (char *__name, size_t __len) __THROW __nonnull ((1));

其中name即是输入参数也是输出参数。

hostname命令可用来获取和设置主机名。主机名通常在系统自举时设置,它由/etc/rc或init取自一个启动文件。

6.10 时间和日期例程

由UNIX内核提供的基本时间服务是计算自协调世界时(Coordinated Universal Time,UTC)公元1970年1月1日00:00:00这一特定时间以来经过的秒数。这一秒数通过以下函数获得:

#include <time.h>
extern time_t time (time_t *__timer) __THROW;

通过clock_gettime同样可以获得这一秒数,但其时间精度更高:

#include <time.h>
extern int clock_gettime (clockid_t __clock_id, struct timespec *__tp) __THROW;

time与clock_gettime函数的结果可以直接相互转化。

time_t类型的参数可以通过gmtime函数转化为协调统一时间的年、月、日、时、分、秒、周日分解。这一格式的时间通过以下结构体表示。

struct tm
{int tm_sec;			/* Seconds.	[0-60] (1 leap second) */int tm_min;			/* Minutes.	[0-59] */int tm_hour;			/* Hours.	[0-23] */int tm_mday;			/* Day.		[1-31] */int tm_mon;			/* Month.	[0-11] */int tm_year;			/* Year	- 1900.  */int tm_wday;			/* Day of week.	[0-6] */int tm_yday;			/* Days in year.[0-365]	*/int tm_isdst;			/* DST.		[-1/0/1]*/# ifdef	__USE_MISClong int tm_gmtoff;		/* Seconds east of UTC.  */const char *tm_zone;		/* Timezone abbreviation.  */
# elselong int __tm_gmtoff;		/* Seconds east of UTC.  */const char *__tm_zone;	/* Timezone abbreviation.  */
# endif
};

这一类型需要通过strftime转化为字符串模式并输出。

extern size_t strftime (char *__restrict __s, size_t __maxsize,const char *__restrict __format,const struct tm *__restrict __tp) __THROW;

一个格式化的时间字符串可通过以下函数转化为结构体struct tm。

extern char *strptime (const char *__restrict __s,const char *__restrict __fmt, struct tm *__tp)__THROW;

struct tm结构体又可以通过mktime函数转化为time_t类型参数。

extern time_t mktime (struct tm *__tp) __THROW;

最后给大家附上各时间结构体之间的转化关系。



这篇关于APUE读书笔记-第六章 系统数据文件和信息的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1095267

相关文章

基于Python实现一个简单的题库与在线考试系统

《基于Python实现一个简单的题库与在线考试系统》在当今信息化教育时代,在线学习与考试系统已成为教育技术领域的重要组成部分,本文就来介绍一下如何使用Python和PyQt5框架开发一个名为白泽题库系... 目录概述功能特点界面展示系统架构设计类结构图Excel题库填写格式模板题库题目填写格式表核心数据结构

Linux系统中的firewall-offline-cmd详解(收藏版)

《Linux系统中的firewall-offline-cmd详解(收藏版)》firewall-offline-cmd是firewalld的一个命令行工具,专门设计用于在没有运行firewalld服务的... 目录主要用途基本语法选项1. 状态管理2. 区域管理3. 服务管理4. 端口管理5. ICMP 阻断

Windows 系统下 Nginx 的配置步骤详解

《Windows系统下Nginx的配置步骤详解》Nginx是一款功能强大的软件,在互联网领域有广泛应用,简单来说,它就像一个聪明的交通指挥员,能让网站运行得更高效、更稳定,:本文主要介绍W... 目录一、为什么要用 Nginx二、Windows 系统下 Nginx 的配置步骤1. 下载 Nginx2. 解压

如何确定哪些软件是Mac系统自带的? Mac系统内置应用查看技巧

《如何确定哪些软件是Mac系统自带的?Mac系统内置应用查看技巧》如何确定哪些软件是Mac系统自带的?mac系统中有很多自带的应用,想要看看哪些是系统自带,该怎么查看呢?下面我们就来看看Mac系统内... 在MAC电脑上,可以使用以下方法来确定哪些软件是系统自带的:1.应用程序文件夹打开应用程序文件夹

windows系统上如何进行maven安装和配置方式

《windows系统上如何进行maven安装和配置方式》:本文主要介绍windows系统上如何进行maven安装和配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不... 目录1. Maven 简介2. maven的下载与安装2.1 下载 Maven2.2 Maven安装2.

使用Python实现Windows系统垃圾清理

《使用Python实现Windows系统垃圾清理》Windows自带的磁盘清理工具功能有限,无法深度清理各类垃圾文件,所以本文为大家介绍了如何使用Python+PyQt5开发一个Windows系统垃圾... 目录一、开发背景与工具概述1.1 为什么需要专业清理工具1.2 工具设计理念二、工具核心功能解析2.

Linux系统之stress-ng测压工具的使用

《Linux系统之stress-ng测压工具的使用》:本文主要介绍Linux系统之stress-ng测压工具的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、理论1.stress工具简介与安装2.语法及参数3.具体安装二、实验1.运行8 cpu, 4 fo

Linux查看系统盘和SSD盘的容量、型号及挂载信息的方法

《Linux查看系统盘和SSD盘的容量、型号及挂载信息的方法》在Linux系统中,管理磁盘设备和分区是日常运维工作的重要部分,而lsblk命令是一个强大的工具,它用于列出系统中的块设备(blockde... 目录1. 查看所有磁盘的物理信息方法 1:使用 lsblk(推荐)方法 2:使用 fdisk -l(

SpringBoot如何对密码等敏感信息进行脱敏处理

《SpringBoot如何对密码等敏感信息进行脱敏处理》这篇文章主要为大家详细介绍了SpringBoot对密码等敏感信息进行脱敏处理的几个常用方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录​1. 配置文件敏感信息脱敏​​2. 日志脱敏​​3. API响应脱敏​​4. 其他注意事项​​总结

ubuntu20.0.4系统中安装Anaconda的超详细图文教程

《ubuntu20.0.4系统中安装Anaconda的超详细图文教程》:本文主要介绍了在Ubuntu系统中如何下载和安装Anaconda,提供了两种方法,详细内容请阅读本文,希望能对你有所帮助... 本文介绍了在Ubuntu系统中如何下载和安装Anaconda。提供了两种方法,包括通过网页手动下载和使用wg