/*********************************************************************************
|
* Copyright: (C) 2025 LingYun IoT System Studio
|
* All rights reserved.
|
*
|
* Filename: myls.c
|
* Description: This file is a simple ls command implement.
|
*
|
* Version: 1.0.0(10/15/2025)
|
* Author: Guo Wenxue <guowenxue@gmail.com>
|
* ChangeLog: 1, Release initial version on "10/15/2025 11:08:39 AM"
|
*
|
********************************************************************************/
|
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <sys/stat.h>
|
#include <sys/types.h>
|
#include <unistd.h>
|
#include <dirent.h>
|
#include <string.h>
|
#include <time.h>
|
#include <pwd.h>
|
#include <grp.h>
|
#include <sys/sysmacros.h>
|
|
// 格式化输出文件权限
|
void print_permissions(mode_t mode)
|
{
|
printf("%c", S_ISDIR(mode) ? 'd' : S_ISLNK(mode) ? 'l' : S_ISCHR(mode) ? 'c' :
|
S_ISBLK(mode) ? 'b' : S_ISFIFO(mode) ? 'p' : S_ISSOCK(mode) ? 's' : '-');
|
printf("%c", mode & S_IRUSR ? 'r' : '-');
|
printf("%c", mode & S_IWUSR ? 'w' : '-');
|
printf("%c", mode & S_IXUSR ? 'x' : '-');
|
printf("%c", mode & S_IRGRP ? 'r' : '-');
|
printf("%c", mode & S_IWGRP ? 'w' : '-');
|
printf("%c", mode & S_IXGRP ? 'x' : '-');
|
printf("%c", mode & S_IROTH ? 'r' : '-');
|
printf("%c", mode & S_IWOTH ? 'w' : '-');
|
printf("%c", mode & S_IXOTH ? 'x' : '-');
|
}
|
|
// 格式化输出时间(省略年份)
|
void print_time(time_t t)
|
{
|
char time_str[20];
|
strftime(time_str, sizeof(time_str), "%b %d %H:%M", localtime(&t));
|
printf("%s", time_str);
|
}
|
|
// 输出单个文件的详细信息
|
void print_file_info(const char *path)
|
{
|
struct stat sb;
|
if (lstat(path, &sb) == -1)
|
{
|
perror("lstat");
|
return;
|
}
|
|
// 文件权限
|
print_permissions(sb.st_mode);
|
printf(" ");
|
|
// 硬链接数
|
printf("%ld ", (long)sb.st_nlink);
|
|
// 所有者用户名
|
struct passwd *pw = getpwuid(sb.st_uid);
|
printf("%s ", pw ? pw->pw_name : "?");
|
|
// 组名
|
struct group *gr = getgrgid(sb.st_gid);
|
printf("%s ", gr ? gr->gr_name : "?");
|
|
// 文件大小
|
if (S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode))
|
{
|
printf("%4d,%4d ", major(sb.st_rdev), minor(sb.st_rdev)); // 设备文件
|
}
|
else
|
{
|
printf("%8ld ", (long)sb.st_size); // 普通文件
|
}
|
|
// 修改时间
|
print_time(sb.st_mtime);
|
printf(" ");
|
|
// 文件名
|
printf("%s", path);
|
|
// 如果是符号链接,打印链接目标
|
if (S_ISLNK(sb.st_mode))
|
{
|
char target[1024];
|
ssize_t len = readlink(path, target, sizeof(target) - 1);
|
if (len != -1)
|
{
|
target[len] = '\0';
|
printf(" -> %s", target);
|
}
|
}
|
printf("\n");
|
}
|
|
// 处理目录或文件
|
void process_path(const char *path)
|
{
|
struct stat sb;
|
if (stat(path, &sb) == -1)
|
{
|
perror("stat");
|
return;
|
}
|
|
if (S_ISDIR(sb.st_mode))
|
{
|
// 如果是目录,遍历其内容
|
DIR *dir = opendir(path);
|
if (!dir)
|
{
|
perror("opendir");
|
return;
|
}
|
|
struct dirent *entry;
|
while ((entry = readdir(dir)) != NULL)
|
{
|
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
{
|
continue; // 跳过 . 和 ..
|
}
|
|
char full_path[1024];
|
snprintf(full_path, sizeof(full_path), "%s/%s", path, entry->d_name);
|
print_file_info(full_path);
|
}
|
closedir(dir);
|
}
|
else
|
{
|
// 如果是文件,直接输出信息
|
print_file_info(path);
|
}
|
}
|
|
int main(int argc, char *argv[])
|
{
|
if (argc < 2)
|
{
|
process_path("."); // 默认输出当前目录
|
}
|
else
|
{
|
for (int i = 1; i < argc; i++) // 处理每个参数
|
{
|
process_path(argv[i]);
|
}
|
}
|
return 0;
|
}
|