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

相关文章

SpringBoot使用Apache Tika检测敏感信息

《SpringBoot使用ApacheTika检测敏感信息》ApacheTika是一个功能强大的内容分析工具,它能够从多种文件格式中提取文本、元数据以及其他结构化信息,下面我们来看看如何使用Ap... 目录Tika 主要特性1. 多格式支持2. 自动文件类型检测3. 文本和元数据提取4. 支持 OCR(光学

JAVA系统中Spring Boot应用程序的配置文件application.yml使用详解

《JAVA系统中SpringBoot应用程序的配置文件application.yml使用详解》:本文主要介绍JAVA系统中SpringBoot应用程序的配置文件application.yml的... 目录文件路径文件内容解释1. Server 配置2. Spring 配置3. Logging 配置4. Ma

2.1/5.1和7.1声道系统有什么区别? 音频声道的专业知识科普

《2.1/5.1和7.1声道系统有什么区别?音频声道的专业知识科普》当设置环绕声系统时,会遇到2.1、5.1、7.1、7.1.2、9.1等数字,当一遍又一遍地看到它们时,可能想知道它们是什... 想要把智能电视自带的音响升级成专业级的家庭影院系统吗?那么你将面临一个重要的选择——使用 2.1、5.1 还是

C#实现获取电脑中的端口号和硬件信息

《C#实现获取电脑中的端口号和硬件信息》这篇文章主要为大家详细介绍了C#实现获取电脑中的端口号和硬件信息的相关方法,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 我们经常在使用一个串口软件的时候,发现软件中的端口号并不是普通的COM1,而是带有硬件信息的。那么如果我们使用C#编写软件时候,如

高效管理你的Linux系统: Debian操作系统常用命令指南

《高效管理你的Linux系统:Debian操作系统常用命令指南》在Debian操作系统中,了解和掌握常用命令对于提高工作效率和系统管理至关重要,本文将详细介绍Debian的常用命令,帮助读者更好地使... Debian是一个流行的linux发行版,它以其稳定性、强大的软件包管理和丰富的社区资源而闻名。在使用

Ubuntu系统怎么安装Warp? 新一代AI 终端神器安装使用方法

《Ubuntu系统怎么安装Warp?新一代AI终端神器安装使用方法》Warp是一款使用Rust开发的现代化AI终端工具,该怎么再Ubuntu系统中安装使用呢?下面我们就来看看详细教程... Warp Terminal 是一款使用 Rust 开发的现代化「AI 终端」工具。最初它只支持 MACOS,但在 20

windows系统下shutdown重启关机命令超详细教程

《windows系统下shutdown重启关机命令超详细教程》shutdown命令是一个强大的工具,允许你通过命令行快速完成关机、重启或注销操作,本文将为你详细解析shutdown命令的使用方法,并提... 目录一、shutdown 命令简介二、shutdown 命令的基本用法三、远程关机与重启四、实际应用

通过C#获取PDF中指定文本或所有文本的字体信息

《通过C#获取PDF中指定文本或所有文本的字体信息》在设计和出版行业中,字体的选择和使用对最终作品的质量有着重要影响,然而,有时我们可能会遇到包含未知字体的PDF文件,这使得我们无法准确地复制或修改文... 目录引言C# 获取PDF中指定文本的字体信息C# 获取PDF文档中用到的所有字体信息引言在设计和出

Debian如何查看系统版本? 7种轻松查看Debian版本信息的实用方法

《Debian如何查看系统版本?7种轻松查看Debian版本信息的实用方法》Debian是一个广泛使用的Linux发行版,用户有时需要查看其版本信息以进行系统管理、故障排除或兼容性检查,在Debia... 作为最受欢迎的 linux 发行版之一,Debian 的版本信息在日常使用和系统维护中起着至关重要的作

C#读取本地网络配置信息全攻略分享

《C#读取本地网络配置信息全攻略分享》在当今数字化时代,网络已深度融入我们生活与工作的方方面面,对于软件开发而言,掌握本地计算机的网络配置信息显得尤为关键,而在C#编程的世界里,我们又该如何巧妙地读取... 目录一、引言二、C# 读取本地网络配置信息的基础准备2.1 引入关键命名空间2.2 理解核心类与方法