🦄 refactor(C13, C14, C115): 更新了linux系统开发部分的结构
This commit is contained in:
34
C14-文件系统/100days.c
Normal file
34
C14-文件系统/100days.c
Normal file
@@ -0,0 +1,34 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#define TIMESTRSIZE 128
|
||||
|
||||
/**
|
||||
* @brief 找出100天以后是哪一天
|
||||
* @details
|
||||
*
|
||||
* @param argc
|
||||
* @param argv
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
time_t stamp;
|
||||
struct tm *tm;
|
||||
char timestr[TIMESTRSIZE];
|
||||
|
||||
time(&stamp);
|
||||
tm = localtime(&stamp);
|
||||
strftime(timestr, TIMESTRSIZE, "Now: %Y-%m-%d", tm);
|
||||
puts(timestr);
|
||||
|
||||
tm->tm_mday += 100;
|
||||
// mktime 会先调整tm溢出的情况
|
||||
mktime(tm);
|
||||
strftime(timestr, TIMESTRSIZE, "100 days later: %Y-%m-%d", tm);
|
||||
puts(timestr);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
594
C14-文件系统/C14-文件系统.md
Normal file
594
C14-文件系统/C14-文件系统.md
Normal file
@@ -0,0 +1,594 @@
|
||||
# 目录
|
||||
- [目录](#目录)
|
||||
- [文件系统](#文件系统)
|
||||
- [目录和文件](#目录和文件)
|
||||
- [系统数据文件和信息](#系统数据文件和信息)
|
||||
- [进程环境](#进程环境)
|
||||
- [`main`函数](#main函数)
|
||||
- [进程的终止](#进程的终止)
|
||||
- [命令行参数的分析](#命令行参数的分析)
|
||||
- [环境变量](#环境变量)
|
||||
- [C程序的存储空间布局](#c程序的存储空间布局)
|
||||
- [库](#库)
|
||||
- [函数之间正常的跳转](#函数之间正常的跳转)
|
||||
- [资源的获取及控制](#资源的获取及控制)
|
||||
|
||||
|
||||
# 文件系统
|
||||
|
||||
类`ls`的实现,如`myls -l -a -i -n`
|
||||
|
||||
`cmd --长格式 -短格式 非选项的传参`
|
||||
|
||||
|
||||
|
||||
## 目录和文件
|
||||
|
||||
1. 获取文件属性
|
||||
|
||||
```c
|
||||
/**
|
||||
* 将文件的属性存储到buf中
|
||||
* stat : 通过文件路径获取属性,面对符号链接文件时,
|
||||
* 获取的是指向的目标文件的属性
|
||||
* fstat: 通过文件描述符获取属性
|
||||
* lstat: 通过文件路径获取属性,面对符号链接文件时,
|
||||
*/
|
||||
int stat(const char *path, struct stat *buf);
|
||||
int fstat(int fd, struct stat *buf);
|
||||
int lstat(const char *path, struct stat *buf);
|
||||
|
||||
struct stat {
|
||||
dev_t st_dev; /* ID of device containing file */
|
||||
ino_t st_ino; /* inode number */
|
||||
// 文件唯一标识,身份证号
|
||||
|
||||
mode_t st_mode; /* protection */
|
||||
// st_mode: 文件权限+文件类型
|
||||
// 文件权限
|
||||
// 七种文件类型:dcb-lsp
|
||||
|
||||
nlink_t st_nlink; /* number of hard links */
|
||||
uid_t st_uid; /* user ID of owner */
|
||||
gid_t st_gid; /* group ID of owner */
|
||||
dev_t st_rdev; /* device ID (if special file) */
|
||||
off_t st_size; /* total size, in bytes */
|
||||
// 在linux下,与windows不同,size值仅仅是属性
|
||||
// 不能实际体现占用磁盘大小,详见 big.c
|
||||
|
||||
blksize_t st_blksize; /* blocksize for file system I/O */
|
||||
blkcnt_t st_blocks; /* number of 512B blocks allocated */
|
||||
time_t st_atime; /* time of last access */
|
||||
time_t st_mtime; /* time of last modification */
|
||||
time_t st_ctime; /* time of last status change */
|
||||
};
|
||||
```
|
||||
|
||||
2. 文件访问权限
|
||||
`st_mode`是一个16位的二进制数,文件类型,文件权限,特殊权限。
|
||||
|
||||
3. `umask`
|
||||
作用:防止产生权限过松的文件。
|
||||
`0666 &~umask`
|
||||
`umask`也是一个终端命令,可以查看和设置。
|
||||
`mode_t umask(mode_t mask);`
|
||||
|
||||
4. 文件权限的更改/管理
|
||||
|
||||
```c
|
||||
/**
|
||||
* 更改文件权限
|
||||
*/
|
||||
int chmod(const char *path, mode_t mode);
|
||||
int fchmod(int fd, mode_t mode);
|
||||
```
|
||||
|
||||
5. 粘住位
|
||||
t位,例如`/tmp`目录。
|
||||
|
||||
6. 文件系统:`FAT`, `UFS`
|
||||
文件或数据的存储格式。
|
||||
1. `FAT`:静态存储的单链表
|
||||
|
||||
```c
|
||||
struct node_st{
|
||||
int next[N];
|
||||
char data[N][SIZE];
|
||||
};
|
||||
```
|
||||
|
||||
2. `UFS`:
|
||||
缺点:不善于处理大量的小文件,因为每个文件都有一个`inode`,占用空间。
|
||||
|
||||
|
||||
> 面试题:
|
||||
> 不用比较,比较两个uint32_t的大小
|
||||
> 使用位图
|
||||
|
||||
7. 硬链接,符号链接
|
||||
|
||||
- 硬链接
|
||||
`ln bigfile bigfile_link`
|
||||
与目录项是同义词
|
||||
相当于目录项又弄了一份,使用`ls -i`可以看到`inode`号相同。
|
||||
|
||||
限制:不能给分区建立,不能给目录建立
|
||||
|
||||
|
||||
- 符号链接
|
||||
`ln -s bigfile_link bigfile_s`
|
||||
|
||||
优点:可以跨分区,可以给目录建立
|
||||
|
||||
|
||||
```c
|
||||
int link(const char *oldpath, const char *newpath);
|
||||
|
||||
/**
|
||||
* 只有没有引用的数据才会真正删除
|
||||
* 可以利用这一点创建匿名文件
|
||||
*/
|
||||
int unlink(const char *pathname);
|
||||
|
||||
int remove(const char *pathname);
|
||||
|
||||
/**
|
||||
* 改变文件的路径或者名字
|
||||
*/
|
||||
int rename(const char *oldpath, const char *newpath);
|
||||
```
|
||||
|
||||
8. `utime`
|
||||
|
||||
```c
|
||||
/**
|
||||
* 更改文件最后读/写的时间
|
||||
*/
|
||||
int utime(const char *filename, const struct utimbuf *times);
|
||||
|
||||
struct utimbuf {
|
||||
time_t actime; /* access time */
|
||||
time_t modtime; /* modification time */
|
||||
};
|
||||
|
||||
struct time_t {
|
||||
long tv_sec; /* seconds */
|
||||
long tv_usec; /* microseconds */
|
||||
};
|
||||
```
|
||||
|
||||
9. 目录的创建和销毁
|
||||
`mkdir, rmdir`
|
||||
|
||||
```c
|
||||
int mkdir(const char *pathname, mode_t mode);
|
||||
|
||||
/**
|
||||
* 只有目录为空才能删除
|
||||
*/
|
||||
int rmdir(const char *pathname);
|
||||
```
|
||||
|
||||
10. 更改当前工作路径
|
||||
`cd, pwd`
|
||||
|
||||
```c
|
||||
/**
|
||||
* 改变当前工作路径
|
||||
* 可以突破假根目录
|
||||
* 但是不能突破chroot
|
||||
*/
|
||||
int chdir(const char *path);
|
||||
int fchdir(int fd);
|
||||
|
||||
/**
|
||||
* 获取当前工作路径
|
||||
*/
|
||||
long getcwd(char *buf, unsigned long size);
|
||||
```
|
||||
|
||||
11. 分析目录/读取目录内容
|
||||
|
||||
```c
|
||||
/**
|
||||
* 法一
|
||||
* 解析模式/通配符
|
||||
*
|
||||
* @prarm: pattern 匹配模式
|
||||
* @prarm: flags 匹配标志
|
||||
* @prarm: errfunc 错误回调函数
|
||||
* @prarm: pglob 匹配结果
|
||||
*
|
||||
* @return 匹配的文件数量
|
||||
*/
|
||||
int glob(const char *restrict pattern, int flags,
|
||||
int (*errfunc)(const char *epath, int eerrno),
|
||||
glob_t *restrict pglob);
|
||||
/**
|
||||
* 释放glob_t结构体
|
||||
*/
|
||||
void globfree(glob_t *pglob);
|
||||
|
||||
/**
|
||||
* 与argc, argv类似
|
||||
*/
|
||||
typedef struct {
|
||||
size_t gl_pathc; /* Count of paths matched so far */
|
||||
char **gl_pathv; /* List of matched pathnames */
|
||||
size_t gl_offs; /* Slots to reserve in gl_pathv */
|
||||
} glob_t;
|
||||
|
||||
/**
|
||||
* 法二
|
||||
*/
|
||||
|
||||
/**
|
||||
* 打开一个目录
|
||||
* 返回一个指向DIR结构体的指针
|
||||
* 是堆区,需要 closedir 释放
|
||||
*/
|
||||
DIR *opendir(const char *name);
|
||||
DIR *fdopendir(int fd);
|
||||
|
||||
/**
|
||||
* 关闭一个目录
|
||||
*/
|
||||
int closedir(DIR *dirp);
|
||||
|
||||
/**
|
||||
* 读取一个目录
|
||||
*
|
||||
* 返回指针指向静态区
|
||||
*/
|
||||
struct dirent *readdir(DIR *dirp);
|
||||
int readdir_r(DIR *restrict dirp,
|
||||
struct dirent *restrict entry,
|
||||
struct dirent **restrict result);
|
||||
|
||||
struct dirent {
|
||||
ino_t d_ino; /* inode number */
|
||||
off_t d_off; /* offset to the next dirent */
|
||||
unsigned short d_reclen; /* length of this record */
|
||||
unsigned char d_type; /* type of file; not supported
|
||||
by all file system types */
|
||||
char d_name[256]; /* filename */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 重置一个目录
|
||||
*/
|
||||
void rewinddir(DIR *dirp);
|
||||
|
||||
void seekdir(DIR *dirp, long offset);
|
||||
|
||||
long telldir(DIR *dirp);
|
||||
|
||||
/**
|
||||
* du 命令
|
||||
* 以字节为单位,统计目录下所有文件的大小
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
```
|
||||
|
||||
作业:用另一套函数实现`mydu`
|
||||
|
||||
|
||||
|
||||
## 系统数据文件和信息
|
||||
|
||||
> 不同环境可能有区别,以具体查询为准,这里以Linux为例
|
||||
|
||||
1. `/etc/passwd`
|
||||
|
||||
```c
|
||||
/**
|
||||
* 通过用户名获取用户信息
|
||||
*/
|
||||
struct passwd *getpwuid(uid_t uid);
|
||||
|
||||
/**
|
||||
* 通过用户ID获取用户信息
|
||||
*/
|
||||
struct passwd *getpwnam(const char *name);
|
||||
|
||||
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 */
|
||||
};
|
||||
```
|
||||
|
||||
2. `/etc/group`
|
||||
|
||||
```c
|
||||
/**
|
||||
* 通过组ID获取组信息
|
||||
*/
|
||||
struct group *getgrgid(gid_t gid);
|
||||
|
||||
/**
|
||||
* 通过组名获取组信息
|
||||
*/
|
||||
struct group *getgrnam(const char *name);
|
||||
|
||||
struct group {
|
||||
char *gr_name; /* group name */
|
||||
char *gr_passwd; /* group password */
|
||||
gid_t gr_gid; /* group ID */
|
||||
char **gr_mem; /* group members */
|
||||
};
|
||||
```
|
||||
|
||||
3. `/etc/shadow`
|
||||
`ll`显示**root**用户也不可读写,但是只有**root**用户才可读写
|
||||
这样是提醒你,即便是**root**用户,也不要随便读写这个文件
|
||||
|
||||
> 密码
|
||||
>
|
||||
> hash - 混淆,不可逆
|
||||
>
|
||||
> 如果原串一样,hash值也一样
|
||||
>
|
||||
> 防备管理员监守自盗
|
||||
>
|
||||
> 加密 - 解密
|
||||
>
|
||||
> 加密为了安全,攻击成本大于收益
|
||||
>
|
||||
> 安全?穷举:口令随机校验(第一遍明明对了给你报错,让你连续两遍成功输入正确)
|
||||
>
|
||||
> 推荐书籍:《应用密码学》
|
||||
|
||||
```c
|
||||
/**
|
||||
* 获得用户的密码信息
|
||||
*/
|
||||
struct *spwd getspnam(const char *name);
|
||||
|
||||
/**
|
||||
* 加密密码
|
||||
*
|
||||
* @prarm: key 密码
|
||||
* @prarm: salt 盐 杂字串
|
||||
*
|
||||
* 默认 md5 加密方式
|
||||
*/
|
||||
char *crypt(const char *key, const char *salt);
|
||||
|
||||
struct spwd {
|
||||
char *sp_namp; /* login name */
|
||||
char *sp_pwdp; /* encrypted password */
|
||||
long sp_lstchg; /* last change */
|
||||
long sp_min; /* min days between changes */
|
||||
long sp_max; /* max days between changes */
|
||||
long sp_warn; /* warning days before password
|
||||
expires */
|
||||
long sp_inact; /* days before account inactive */
|
||||
long sp_expire; /* days since 1970-01-01 until account
|
||||
expires */
|
||||
unsigned long sp_flag; /* reserved */
|
||||
};
|
||||
|
||||
/**
|
||||
* 输入提示符
|
||||
*/
|
||||
char *getpass(const char *prompt);
|
||||
```
|
||||
|
||||
4. 时间戳
|
||||
机器喜欢大整数 `time_t`
|
||||
人类喜欢字符串 `char *`
|
||||
程序员喜欢结构体 `struct tm`
|
||||
|
||||
```c
|
||||
/**
|
||||
* 从内核获取以秒为单位的一个时戳
|
||||
* 从 UTC 1970年1月1日0时0分0秒 到现在的秒数
|
||||
*/
|
||||
time_t time(time_t *t);
|
||||
|
||||
// eg: 两种用法
|
||||
time_t stamp;
|
||||
time(&stamp);
|
||||
stamp=time(NULL);
|
||||
|
||||
/**
|
||||
* 将时间戳转换为结构体
|
||||
*/
|
||||
struct tm *gmtime(const time_t *timep);
|
||||
struct tm *localtime(const time_t *timep);
|
||||
|
||||
sturct tm {
|
||||
int tm_sec; /* seconds */
|
||||
int tm_min; /* minutes */
|
||||
int tm_hour; /* hours */
|
||||
int tm_mday; /* day of the month */
|
||||
int tm_mon; /* month */
|
||||
int tm_year; /* year */
|
||||
int tm_wday; /* day of the week */
|
||||
int tm_yday; /* day in the year */
|
||||
int tm_isdst; /* daylight saving time */
|
||||
/* daylight 夏令时调整 */
|
||||
};
|
||||
|
||||
/**
|
||||
* 将结构体转换为时间戳
|
||||
* ! 没有 const,可能更改 tm
|
||||
*/
|
||||
time_t mktime(struct tm *tm);
|
||||
|
||||
/**
|
||||
* 格式化输出时间
|
||||
*/
|
||||
size_t strftime(char *s, size_t max, const char *format,
|
||||
const struct tm *tm);
|
||||
|
||||
// eg
|
||||
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm);
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 进程环境
|
||||
|
||||
### `main`函数
|
||||
|
||||
```c
|
||||
int main(int argc, char *argv[]);
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 进程的终止
|
||||
|
||||
1. 正常终止:
|
||||
|
||||
- 从`main`函数返回
|
||||
- 调用`exit`
|
||||
`void exit(int status);`
|
||||
status & 0377 有符号的char -128~127
|
||||
|
||||
- 调用`_exit`或者`_Exit`(系统调用)
|
||||
|
||||
> `exit`与`_exit _Exit`的区别
|
||||
> `_exit`不执行`atexit`注册的函数,不刷新`stdio`缓冲区
|
||||
> 这样可以防止错误扩散
|
||||
|
||||
- 最后一个线程从其启动例程返回
|
||||
- 最后一个线程调用了`pthread_exit`
|
||||
|
||||
2. 异常终止
|
||||
|
||||
- 调用`abort`
|
||||
- 接到一个信号并终止
|
||||
- 最后一个线程对其取消请求作出响应
|
||||
|
||||
|
||||
```c
|
||||
/**
|
||||
* 注册一个函数,当进程终止时调用
|
||||
*
|
||||
* 钩子函数:逆序执行
|
||||
* 可以进行资源释放
|
||||
*/
|
||||
int atexit(void (*function)(void));// 钩子函数
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 命令行参数的分析
|
||||
|
||||
```c
|
||||
#include <unistd.h>
|
||||
|
||||
extern char *optarg; // 选项参数
|
||||
// optind: 下一个要处理的参数的索引
|
||||
extern int optind, opterr, optopt;
|
||||
|
||||
int getopt(int argc, char *const argv[], const char *optstring);
|
||||
|
||||
int getopt_long(int argc, char *const argv[], const char *optstring,
|
||||
const struct option *longopts, int *longindex);
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 环境变量
|
||||
|
||||
**KEY = VALVE**
|
||||
可以通过`export`命令查看
|
||||
|
||||
```c
|
||||
char *getenv(const char *name);
|
||||
|
||||
/*
|
||||
* change or add
|
||||
*
|
||||
* @prarm: overwrite 是否覆盖
|
||||
*
|
||||
* 覆盖时是释放原来的空间,重新分配
|
||||
*/
|
||||
int setenv(const char *name, const char *value, int overwrite);
|
||||
int unsetenv(const char *name);
|
||||
|
||||
/*
|
||||
* 和getenv一样的作用,change or add
|
||||
* 用法不一样,且没有const修饰
|
||||
*/
|
||||
int putenv(char *string);
|
||||
```
|
||||
|
||||
|
||||
|
||||
### C程序的存储空间布局
|
||||
|
||||
`pmap`命令,查看进程空间布局
|
||||
|
||||
|
||||
|
||||
### 库
|
||||
|
||||
- 动态库
|
||||
|
||||
- 静态库
|
||||
|
||||
- 手工装载库
|
||||
|
||||
```c
|
||||
void *dlopen(const char *filename, int flag);
|
||||
char *dlerror(void);
|
||||
int dlclose(void *handle);
|
||||
void *dlsym(void *handle, const char *symbol);
|
||||
// Link with -ldl
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 函数之间正常的跳转
|
||||
|
||||
`goto`无法跨函数跳转。
|
||||
|
||||
```c
|
||||
/*
|
||||
* 设置跳转点
|
||||
*
|
||||
* @return 0 说明是在设置跳转点
|
||||
* @return 非0 说明是通过 longjmp 返回
|
||||
*/
|
||||
int setjmp(jmp_buf env);
|
||||
|
||||
/*
|
||||
* 跳转到跳转点
|
||||
*
|
||||
* @prarm: env 跳转点
|
||||
* @prarm: val 传递给 setjmp 的值
|
||||
*/
|
||||
void longjmp(jmp_buf env, int val);
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 资源的获取及控制
|
||||
|
||||
`ulimit -a`
|
||||
|
||||
```c
|
||||
// get/set resource limits
|
||||
int getrlimit(int resource, struct rlimit *rlim);
|
||||
int setrlimit(int resource, const struct rlimit *rlim);
|
||||
|
||||
// 普通用户不能设置超过硬限制
|
||||
// root 用户可以 升高/降低 硬限制
|
||||
struct rlimit {
|
||||
rlim_t rlim_cur; /* soft limit */
|
||||
rlim_t rlim_max; /* hard limit */
|
||||
};
|
||||
```
|
||||
|
||||
205
C14-文件系统/W_process_excel.c
Normal file
205
C14-文件系统/W_process_excel.c
Normal file
@@ -0,0 +1,205 @@
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if 1
|
||||
# define debug(fmt, args...) printf(fmt, ##args)
|
||||
#else
|
||||
# define debug(fmt, args...)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief 读取一行
|
||||
* @details
|
||||
* 循环读入一个字符
|
||||
* 如何判断读完一行? 读到0x0d, 0x0a
|
||||
*
|
||||
* @param fd
|
||||
* @param buf
|
||||
*
|
||||
* @return int 读到的一行数据的数据个数( n>=0 )
|
||||
* -1: 读到文件尾部或者出错
|
||||
*/
|
||||
static int read_line(int fd, unsigned char *buf)
|
||||
{
|
||||
unsigned char c;
|
||||
int len;
|
||||
int i = 0;
|
||||
int err = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
len = read(fd, &c, 1);
|
||||
if (len <= 0)
|
||||
{
|
||||
err = -1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c != '\n' && c != '\r')
|
||||
{
|
||||
buf[i] = c;
|
||||
i++;
|
||||
}
|
||||
else /* 碰到回车换行 */
|
||||
{
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buf[i] = '\0';
|
||||
|
||||
if (err && (0 == i))
|
||||
/* 读到文件尾部且无有效数据 */
|
||||
return -1;
|
||||
else
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 处理一行的数据, 计算出总分和评价
|
||||
* @details
|
||||
*
|
||||
* @param data_buf
|
||||
* @param result_buf
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
static void process_data(unsigned char *data_buf, unsigned char *result_buf)
|
||||
{
|
||||
/**
|
||||
* eg1: data_buf=",语文,数学,英语,总分,评价"
|
||||
* result_buf=",语文,数学,英语,总分,评价"
|
||||
*
|
||||
* eg2: data_buf="张三,90,91,92,,"
|
||||
* result_buf="张三,90,91,92,273,A+"
|
||||
*
|
||||
*/
|
||||
|
||||
char name[100];
|
||||
int scores[3];
|
||||
int sum;
|
||||
char *levels[] = {"A+", "A", "B"};
|
||||
int level;
|
||||
|
||||
// debug("data_buf[0]: %x\n", data_buf[0]);
|
||||
if (0xef == data_buf[0]) /* 对于UTF-8, 前三个字符是0xef 0xbb 0xbf */
|
||||
{
|
||||
strcpy(result_buf, data_buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
// debug("data_buf: %s\n", data_buf);
|
||||
// debug("进入了\n");
|
||||
/**
|
||||
* @brief 从字符串得到数据
|
||||
* @details
|
||||
* 拆分信息: scanf分隔符
|
||||
* %[^,]: 读数据直到碰到逗号
|
||||
*
|
||||
*/
|
||||
sscanf(data_buf,
|
||||
"%[^,],%d,%d,%d,,",
|
||||
name,
|
||||
&scores[0],
|
||||
&scores[1],
|
||||
&scores[2]);
|
||||
|
||||
debug("name: %s, scores: %d, %d, %d\n",
|
||||
name,
|
||||
scores[0],
|
||||
scores[1],
|
||||
scores[2]);
|
||||
|
||||
sum = scores[0] + scores[1] + scores[2];
|
||||
if (sum >= 270)
|
||||
level = 0;
|
||||
else if (sum >= 240)
|
||||
level = 1;
|
||||
else
|
||||
level = 2;
|
||||
|
||||
sprintf(result_buf,
|
||||
"%s,%d,%d,%d,%d,%s",
|
||||
name,
|
||||
scores[0],
|
||||
scores[1],
|
||||
scores[2],
|
||||
sum,
|
||||
levels[level]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 处理csv表格
|
||||
* @details
|
||||
* Usage: ./W_process_excel data.csv result.csv
|
||||
*
|
||||
* @param argc
|
||||
* @param argv
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int fd_data, fd_result;
|
||||
int len;
|
||||
unsigned char data_buf[1000];
|
||||
unsigned char result_buf[1000];
|
||||
|
||||
if (argc != 3)
|
||||
{
|
||||
printf("Usage: %s data.csv result.csv\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fd_data = open(argv[1], O_RDONLY);
|
||||
if (fd_data < 0)
|
||||
{
|
||||
perror("open data.csv");
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
printf("data file fd: %d\n", fd_data);
|
||||
|
||||
fd_result = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
if (fd_result < 0)
|
||||
{
|
||||
perror("open result.csv");
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
printf("result file fd: %d\n", fd_result);
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* 读取1行 */
|
||||
len = read_line(fd_data, data_buf);
|
||||
if (-1 == len)
|
||||
break;
|
||||
|
||||
// if (len != 0)
|
||||
// debug("%s\n\r", data_buf);
|
||||
|
||||
if (len != 0)
|
||||
{
|
||||
/* 处理1行 */
|
||||
process_data(data_buf, result_buf);
|
||||
|
||||
/* 写入结果文件 */
|
||||
write(fd_result, result_buf, strlen(result_buf));
|
||||
write(fd_result, "\r\n", 2);
|
||||
}
|
||||
}
|
||||
|
||||
close(fd_data);
|
||||
close(fd_result);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
37
C14-文件系统/atexit.c
Normal file
37
C14-文件系统/atexit.c
Normal file
@@ -0,0 +1,37 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static void f1(void)
|
||||
{
|
||||
puts("f1() is working!");
|
||||
}
|
||||
|
||||
static void f2(void)
|
||||
{
|
||||
puts("f2() is working!");
|
||||
}
|
||||
|
||||
static void f3(void)
|
||||
{
|
||||
puts("f3() is working!");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
puts("Begin!");
|
||||
|
||||
atexit(f1);
|
||||
atexit(f2);
|
||||
atexit(f3);
|
||||
|
||||
puts("End!");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
// out:
|
||||
// *[main][~/Linux-C-Notes/C13-Linux系统编程/fs]$ ./atexit
|
||||
// Begin!
|
||||
// End!
|
||||
// f3() is working!
|
||||
// f2() is working!
|
||||
// f1() is working!
|
||||
34
C14-文件系统/big.c
Normal file
34
C14-文件系统/big.c
Normal file
@@ -0,0 +1,34 @@
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "Usage:...\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int fd;
|
||||
|
||||
fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
||||
if (fd < 0)
|
||||
{
|
||||
perror("open()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// 生成一个5G的文件
|
||||
// !!! 整数溢出
|
||||
lseek(fd, 5LL * 1024LL * 1024LL * 1024LL - 1LL, SEEK_SET);
|
||||
|
||||
// 写入尾0
|
||||
write(fd, "", 1);
|
||||
|
||||
close(fd);
|
||||
exit(0);
|
||||
}
|
||||
46
C14-文件系统/check.c
Normal file
46
C14-文件系统/check.c
Normal file
@@ -0,0 +1,46 @@
|
||||
#include <crypt.h>
|
||||
#include <shadow.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/**
|
||||
* @brief 加密输入的密码并与shadow文件中的密码进行比较
|
||||
* @details
|
||||
* !!! compile: gcc check.c -o check -lcrypt
|
||||
* !!! 需要root权限运行
|
||||
*
|
||||
* @param argc
|
||||
* @param argv [in] 用户名
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "Usage:...\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *input_pass;
|
||||
struct spwd *shadowline;
|
||||
char *crypt_pass;
|
||||
|
||||
//* getpass()函数在输入密码时不会回显密码
|
||||
input_pass = getpass("PassWord: ");
|
||||
|
||||
//* getspnam()函数通过用户名获取shadow文件中的密码
|
||||
shadowline = getspnam(argv[1]);
|
||||
|
||||
//* 加密输入的密码
|
||||
crypt_pass = crypt(input_pass, shadowline->sp_pwdp);
|
||||
|
||||
if (0 == strcmp(crypt_pass, shadowline->sp_pwdp))
|
||||
puts("OK!");
|
||||
else
|
||||
puts("Error!");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
4
C14-文件系统/data.csv
Normal file
4
C14-文件系统/data.csv
Normal file
@@ -0,0 +1,4 @@
|
||||
,语文,数学,英语,总分,评价
|
||||
张三,90,91,92,,
|
||||
李四,80,81,82,,
|
||||
王五,70,71,72,,
|
||||
|
41
C14-文件系统/flen.c
Normal file
41
C14-文件系统/flen.c
Normal file
@@ -0,0 +1,41 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
// !!! 不是int
|
||||
static off_t flen(char *fname)
|
||||
{
|
||||
struct stat statres;
|
||||
|
||||
if (stat(fname, &statres) < 0)
|
||||
{
|
||||
perror("stat()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return statres.st_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取文件大小
|
||||
* @details
|
||||
* Usage: ./flen filename
|
||||
*
|
||||
* @param argc
|
||||
* @param argv
|
||||
* @return int
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "Usage:...\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// !!! 通过makefile指定off_t 64位
|
||||
printf("%lld\n", flen(argv[1]));
|
||||
|
||||
exit(0);
|
||||
}
|
||||
54
C14-文件系统/ftype.c
Normal file
54
C14-文件系统/ftype.c
Normal file
@@ -0,0 +1,54 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
static int ftype(const char *fname)
|
||||
{
|
||||
struct stat statres;
|
||||
|
||||
if (stat(fname, &statres) < 0)
|
||||
{
|
||||
perror("stat()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (S_ISREG(statres.st_mode))
|
||||
return '-';
|
||||
else if (S_ISDIR(statres.st_mode))
|
||||
return 'd';
|
||||
else if (S_ISSOCK(statres.st_mode))
|
||||
return 's';
|
||||
else if (S_ISFIFO(statres.st_mode))
|
||||
return 'p';
|
||||
else if (S_ISBLK(statres.st_mode))
|
||||
return 'b';
|
||||
else if (S_ISCHR(statres.st_mode))
|
||||
return 'c';
|
||||
else if (S_ISLNK(statres.st_mode))
|
||||
return 'l';
|
||||
else
|
||||
return '?';
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取文件类型
|
||||
* @details
|
||||
* Usage: ftype <filename>
|
||||
*
|
||||
* @param argc
|
||||
* @param argv
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "Usage:...\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("%c\n", ftype(argv[1]));
|
||||
|
||||
exit(0);
|
||||
}
|
||||
17
C14-文件系统/getenv.c
Normal file
17
C14-文件系统/getenv.c
Normal file
@@ -0,0 +1,17 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
puts(getenv("PATH"));
|
||||
|
||||
getchar();
|
||||
/**
|
||||
* ./getenv
|
||||
* ps axf | grep getenv
|
||||
* pmap 4938
|
||||
*/
|
||||
|
||||
exit(0);
|
||||
}
|
||||
46
C14-文件系统/glob.c
Normal file
46
C14-文件系统/glob.c
Normal file
@@ -0,0 +1,46 @@
|
||||
#include <glob.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// #define PAT "/etc/a*.conf"
|
||||
#define PAT "/etc/*" // 不包括隐藏文件 .*
|
||||
|
||||
#if 0
|
||||
static int errfunc_(const char *errpath, int eerrno)
|
||||
{
|
||||
puts(errpath);
|
||||
fprintf(stderr, "ERROR MSG: %s\n", strerror(eerrno));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ls /etc/a*.conf
|
||||
* @details
|
||||
*
|
||||
* @param argc
|
||||
* @param argv
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
glob_t globres;
|
||||
int err;
|
||||
|
||||
err = glob(PAT, 0, NULL, &globres);
|
||||
if (err)
|
||||
{
|
||||
printf("ERROR CODE = %d\n", err);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < globres.gl_pathc; i++)
|
||||
{
|
||||
puts(globres.gl_pathv[i]);
|
||||
}
|
||||
|
||||
// !!!
|
||||
globfree(&globres);
|
||||
exit(0);
|
||||
}
|
||||
99
C14-文件系统/jmp.c
Normal file
99
C14-文件系统/jmp.c
Normal file
@@ -0,0 +1,99 @@
|
||||
#include <setjmp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static jmp_buf save;
|
||||
|
||||
static void d(void)
|
||||
{
|
||||
printf("%s():Begin.\n", __FUNCTION__);
|
||||
|
||||
printf("%s():Jump now.\n", __FUNCTION__);
|
||||
longjmp(save, 6);
|
||||
// longjmp(save, 0); // !!! 如果返回0,实际会返回1,避免与另一种情况冲突
|
||||
|
||||
printf("%s():End.\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
static void c(void)
|
||||
{
|
||||
printf("%s():Begin.\n", __FUNCTION__);
|
||||
printf("%s():Call d().\n", __FUNCTION__);
|
||||
|
||||
d();
|
||||
|
||||
printf("%s():d() returned.\n", __FUNCTION__);
|
||||
printf("%s():End.\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
static void b(void)
|
||||
{
|
||||
printf("%s():Begin.\n", __FUNCTION__);
|
||||
printf("%s():Call c().\n", __FUNCTION__);
|
||||
|
||||
c();
|
||||
|
||||
printf("%s():c() returned.\n", __FUNCTION__);
|
||||
printf("%s():End.\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
static void a(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
printf("%s():Begin.\n", __FUNCTION__);
|
||||
|
||||
ret = setjmp(save);
|
||||
if (0 == ret)
|
||||
{
|
||||
printf("%s():Call b().\n", __FUNCTION__);
|
||||
b();
|
||||
printf("%s():b() returned.\n", __FUNCTION__);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%s():Jumped back here with code %d.\n", __FUNCTION__, ret);
|
||||
}
|
||||
|
||||
printf("%s():End.\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief jmp
|
||||
* @details
|
||||
* d跳回a
|
||||
*
|
||||
* @param argc
|
||||
* @param argv
|
||||
* @return int
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
printf("%s():Begin.\n", __FUNCTION__);
|
||||
printf("%s():Call a().\n", __FUNCTION__);
|
||||
|
||||
a();
|
||||
|
||||
printf("%s():a() returned.\n", __FUNCTION__);
|
||||
printf("%s():End.\n", __FUNCTION__);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
// ! out
|
||||
// main():Begin.
|
||||
// main():Call a().
|
||||
// a():Begin.
|
||||
// a():Call b().
|
||||
// b():Begin.
|
||||
// b():Call c().
|
||||
// c():Begin.
|
||||
// c():Call d().
|
||||
// d():Begin.
|
||||
// d():Jump now.
|
||||
// a():Jumped back here with code 6.
|
||||
// a():End.
|
||||
// main():a() returned.
|
||||
// main():End.
|
||||
15
C14-文件系统/main.c
Normal file
15
C14-文件系统/main.c
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
printf("argc = %d\n", argc);
|
||||
|
||||
// for (int i = 0; i < argc; i++)
|
||||
for (int i = 0; argv[i] != NULL; i++)
|
||||
{
|
||||
puts(argv[i]);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
13
C14-文件系统/main1.c
Normal file
13
C14-文件系统/main1.c
Normal file
@@ -0,0 +1,13 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
printf("Hello, World!\n");
|
||||
|
||||
return 0;
|
||||
/*
|
||||
* echo $?
|
||||
* 0
|
||||
*/
|
||||
}
|
||||
109
C14-文件系统/mydate.c
Normal file
109
C14-文件系统/mydate.c
Normal file
@@ -0,0 +1,109 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define TIMESTRSIZE 1024
|
||||
#define FMTSTRSIZE 1024
|
||||
|
||||
/**
|
||||
* @brief mydate
|
||||
* @details
|
||||
* Usage:
|
||||
* mydate [-H 12|24] [-y 2|4] [-m] [-d] [-M] [-S]
|
||||
* Options:
|
||||
* -y: year 2位,4位
|
||||
* -m: month
|
||||
* -d: day
|
||||
* -H: hour 12小时制,24小时制
|
||||
* -M: minute
|
||||
* -S: second
|
||||
*
|
||||
* @param argc
|
||||
* @param argv
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
time_t stamp;
|
||||
struct tm *tm;
|
||||
char timestr[TIMESTRSIZE];
|
||||
int c;
|
||||
char fmtstr[FMTSTRSIZE];
|
||||
fmtstr[0] = '\0';
|
||||
FILE *fp = stdout;
|
||||
|
||||
time(&stamp);
|
||||
tm = localtime(&stamp);
|
||||
|
||||
while (1)
|
||||
{
|
||||
//* 选项传参
|
||||
// c = getopt(argc, argv, "H:y:MSmd");
|
||||
|
||||
//* 加'-',接收非选项传参
|
||||
c = getopt(argc, argv, "-H:y:MSmd");
|
||||
if (c < 0)
|
||||
break;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
//* 非选项传参,返回1
|
||||
case 1:
|
||||
if (stdout == fp) //! 先入为主
|
||||
{
|
||||
fp = fopen(argv[optind - 1], "w");
|
||||
if (NULL == fp)
|
||||
{
|
||||
perror("fopen()");
|
||||
fp = stdout;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
if (0 == strcmp(optarg, "12"))
|
||||
strncat(fmtstr, "%I(%P) ", FMTSTRSIZE - 1);
|
||||
else if (0 == strcmp(optarg, "24"))
|
||||
strncat(fmtstr, "%H ", FMTSTRSIZE - 1);
|
||||
else
|
||||
fprintf(stderr,
|
||||
"Usage: %s [-H 12|24] [-y 2|4] [-m] [-d] [-M] [-S]\n",
|
||||
argv[0]);
|
||||
break;
|
||||
|
||||
case 'M': strncat(fmtstr, "%M ", FMTSTRSIZE - 1); break;
|
||||
|
||||
case 'S': strncat(fmtstr, "%S ", FMTSTRSIZE - 1); break;
|
||||
|
||||
case 'y':
|
||||
if (0 == strcmp(optarg, "2"))
|
||||
strncat(fmtstr, "%y ", FMTSTRSIZE - 1);
|
||||
else if (0 == strcmp(optarg, "4"))
|
||||
strncat(fmtstr, "%Y ", FMTSTRSIZE - 1);
|
||||
else
|
||||
fprintf(stderr,
|
||||
"Usage: %s [-H 12|24] [-y 2|4] [-m] [-d] [-M] [-S]\n",
|
||||
argv[0]);
|
||||
break;
|
||||
|
||||
case 'm': strncat(fmtstr, "%m ", FMTSTRSIZE - 1); break;
|
||||
|
||||
case 'd': strncat(fmtstr, "%d ", FMTSTRSIZE - 1); break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
strncat(fmtstr, "\n", FMTSTRSIZE - 1);
|
||||
strftime(timestr, TIMESTRSIZE, fmtstr, tm);
|
||||
|
||||
fputs(timestr, fp);
|
||||
|
||||
if (fp != stdout)
|
||||
fclose(fp);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
125
C14-文件系统/mydu.c
Normal file
125
C14-文件系统/mydu.c
Normal file
@@ -0,0 +1,125 @@
|
||||
#include <glob.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define PATHSIZE 1024
|
||||
|
||||
static int path_noloop(const char *path)
|
||||
{
|
||||
char *pos;
|
||||
|
||||
/**
|
||||
* @brief strrchr
|
||||
* @details
|
||||
*
|
||||
* 找到 path 中最后一个 '/' 字符的位置
|
||||
*/
|
||||
pos = strrchr(path, '/');
|
||||
if (NULL == pos)
|
||||
exit(1);
|
||||
|
||||
if ((0 == strcmp(pos + 1, ".") || 0 == strcmp(pos + 1, "..")))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int64_t mydu(const char *path)
|
||||
{
|
||||
// 优化递归
|
||||
// 将部分与递归无关的变量拿出栈,用 static 修饰
|
||||
static struct stat statres;
|
||||
static char nextpath[PATHSIZE];
|
||||
glob_t globres;
|
||||
int64_t sum;
|
||||
int i;
|
||||
|
||||
if (lstat(path, &statres) < 0)
|
||||
{
|
||||
perror("lstat()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!S_ISDIR(statres.st_mode))
|
||||
{
|
||||
/* 非目录 */
|
||||
return statres.st_blocks;
|
||||
/*
|
||||
* st_blocks 代表磁盘块数量,一个磁盘块大小为512字节
|
||||
* 所以除以2才表示多少个1k字节
|
||||
*/
|
||||
}
|
||||
|
||||
/* 目录 */
|
||||
/* 例如:/aaa/bbb/ccc/ddd/eee/fff */
|
||||
|
||||
strncpy(nextpath, path, PATHSIZE);
|
||||
strncat(nextpath, "/*", PATHSIZE); //[W]
|
||||
// if (glob(nextpath, 0, NULL, &globres))
|
||||
// {
|
||||
// perror("glob(), 1");
|
||||
// exit(1);
|
||||
// }
|
||||
glob(nextpath, 0, NULL, &globres);
|
||||
|
||||
// !!! 要考虑 . 和 .. 目录
|
||||
strncpy(nextpath, path, PATHSIZE);
|
||||
strncat(nextpath, "/.*", PATHSIZE); //[W]
|
||||
/*
|
||||
* 这个警告是因为 strncat 函数的第三个参数(即 PATHSIZE)等于目标字符串
|
||||
* nextpath 的大小。这可能会导致 nextpath 缓冲区溢出,因为 strncat
|
||||
* 函数会在目标字符串的末尾添加一个 null 字符('\0')。
|
||||
*/
|
||||
|
||||
// !!! APPEND
|
||||
// if (glob(nextpath, GLOB_APPEND, NULL, &globres))
|
||||
// {
|
||||
// perror("glob(), APPEND");
|
||||
// exit(1);
|
||||
// }
|
||||
glob(nextpath, GLOB_APPEND, NULL, &globres);
|
||||
|
||||
sum = statres.st_blocks;
|
||||
|
||||
for (i = 0; i < globres.gl_pathc; i++)
|
||||
{
|
||||
if (path_noloop(globres.gl_pathv[i]))
|
||||
{
|
||||
sum += mydu(globres.gl_pathv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// !!!
|
||||
globfree(&globres);
|
||||
return sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mydu
|
||||
* @details
|
||||
* Usage: mydu [FILE]...
|
||||
*
|
||||
* 用到了递归的思想
|
||||
*
|
||||
* !!! 未考虑权限问题
|
||||
*
|
||||
* @param argc
|
||||
* @param argv
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "Usage: mydu [FILE]...\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("%lld\n", mydu(argv[1]) / 2);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
13
C14-文件系统/myenv.c
Normal file
13
C14-文件系统/myenv.c
Normal file
@@ -0,0 +1,13 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
extern char **environ;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
for (int i = 0; environ[i] != NULL; i++)
|
||||
puts(environ[i]);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
38
C14-文件系统/readdir.c
Normal file
38
C14-文件系统/readdir.c
Normal file
@@ -0,0 +1,38 @@
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define PAT "/etc"
|
||||
|
||||
/**
|
||||
* @brief 解析PAT下文件个数
|
||||
* @details
|
||||
*
|
||||
* @param argc
|
||||
* @param argv
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
DIR *dp;
|
||||
struct dirent *cur;
|
||||
|
||||
dp = opendir(PAT);
|
||||
if (NULL == dp)
|
||||
{
|
||||
perror("opendir()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// !!! 注意括号
|
||||
while ((cur = readdir(dp)) != NULL)
|
||||
{
|
||||
puts(cur->d_name);
|
||||
}
|
||||
|
||||
closedir(dp);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
4
C14-文件系统/result.csv
Normal file
4
C14-文件系统/result.csv
Normal file
@@ -0,0 +1,4 @@
|
||||
,语文,数学,英语,总分,评价
|
||||
张三,90,91,92,273,A+
|
||||
李四,80,81,82,243,A
|
||||
王五,70,71,72,213,B
|
||||
|
86
C14-文件系统/timelog.c
Normal file
86
C14-文件系统/timelog.c
Normal file
@@ -0,0 +1,86 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define FNAME "time.log"
|
||||
#define BUFSIZE 1024
|
||||
|
||||
/**
|
||||
* @brief 往文件里面输出时间戳
|
||||
* @details
|
||||
* 实例格式:2019-12-12 12:12:12
|
||||
*
|
||||
* @param argc
|
||||
* @param argv
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *fp;
|
||||
time_t stamp;
|
||||
struct tm *tm;
|
||||
char buf[BUFSIZE];
|
||||
int count = 0;
|
||||
|
||||
fp = fopen(FNAME, "a+");
|
||||
if (fp == NULL)
|
||||
{
|
||||
perror("fopen()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while (fgets(buf, BUFSIZE, fp) != NULL)
|
||||
count++;
|
||||
|
||||
while (1)
|
||||
{
|
||||
stamp = time(NULL);
|
||||
|
||||
tm = localtime(&stamp);
|
||||
if (NULL == tm)
|
||||
{
|
||||
perror("localtime()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
strftime(buf, BUFSIZE, "%Y-%m-%d %H:%M:%S", tm);
|
||||
|
||||
fprintf(fp, "%-4d%s\n", ++count, buf);
|
||||
|
||||
/*
|
||||
* 加了sleep(1)之后就没有输出?
|
||||
* 全缓冲
|
||||
* 因为缓冲区没有满,没有刷新到文件里面
|
||||
*/
|
||||
fflush(fp);
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
//! 最终效果
|
||||
// *[main][~/Linux-C-Notes/C13-Linux系统编程/fs]$ ./test
|
||||
// ^C
|
||||
// *[main][~/Linux-C-Notes/C13-Linux系统编程/fs]$ cat time.log
|
||||
// 1 2024-05-11 21:53:26
|
||||
// 2 2024-05-11 21:53:27
|
||||
// 3 2024-05-11 21:53:28
|
||||
// 4 2024-05-11 21:53:29
|
||||
// 5 2024-05-11 21:53:30
|
||||
// *[main][~/Linux-C-Notes/C13-Linux系统编程/fs]$ ./test
|
||||
// ^C
|
||||
// *[main][~/Linux-C-Notes/C13-Linux系统编程/fs]$ cat time.log
|
||||
// 1 2024-05-11 21:53:26
|
||||
// 2 2024-05-11 21:53:27
|
||||
// 3 2024-05-11 21:53:28
|
||||
// 4 2024-05-11 21:53:29
|
||||
// 5 2024-05-11 21:53:30
|
||||
// 6 2024-05-11 21:53:35
|
||||
// 7 2024-05-11 21:53:36
|
||||
// 8 2024-05-11 21:53:37
|
||||
// 9 2024-05-11 21:53:38
|
||||
29
C14-文件系统/username.c
Normal file
29
C14-文件系统/username.c
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* @brief 用user id获取用户名
|
||||
* @details
|
||||
*
|
||||
* @param argc
|
||||
* @param argv
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s <user id>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct passwd *pwdline;
|
||||
|
||||
pwdline = getpwuid(atoi(argv[1]));
|
||||
|
||||
puts(pwdline->pw_name);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
Reference in New Issue
Block a user