/** @file my_ls.c
* @brief 实现ls -l []这个功能
* @note 通过这个函数能够获取文件的信息并在终端显示
* @author
* @date
* @version v1.0
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <dirent.h>
#define FILELENGTH 50 // 文件长度
#define N_BITS 3 // 用于打印文件权限时使用
/** @Fn int isDir(const char *name)
* @brief 判断该文件是否是目录
* @param const char *name 文件名
* @return 0 - true -1 - false
*/
int isDir(const char *name)
{
struct stat buf;
if ( stat(name, &buf) != 0 )
{
printf("stat %s error! \n", name);
exit (-1);
}
switch ( buf.st_mode & S_IFMT)
{
case S_IFDIR:
return 0;
break;
default:
return -1;
break;
}
}
/** @Fn void print_perm(mode_t st_mode)
* @brief 打印文件类型和文件的读写权限 rwxrwx...
* @note 由于st_mode是总共由9位组成,先必须循环3次分别对应自己的权限,
本组权限,再之后是其他人权限,因此必须循环三次,每次循环之后
mask右移三位进入下一组的权限打印
通过配对这三位的值,将数组perm[]对应的值打印出来
* @param mode_t st_mode 传入的文件权限值
* @return none
*/
void print_perm(mode_t st_mode)
{
int i, tmp;
unsigned int mask = 0700;
static char *perm[]={"---", "--x", "-w-", "-wx",
"r--", "r-x", "rw-", "rwx"};
if ( (st_mode & S_IFMT) == S_IFSOCK ) // socket文件
{
printf("s");
}
else if ( (st_mode & S_IFMT) == S_IFLNK ) // 链接文件
{
printf("I");
}
else if ( (st_mode & S_IFMT) == S_IFREG ) // 普通文件
{
printf("-");
}
else if ( (st_mode & S_IFMT) == S_IFBLK ) // 块文件
{
printf("b");
}
else if ( (st_mode & S_IFMT) == S_IFCHR ) // 字符文件
{
printf("c");
}
else if ( (st_mode & S_IFMT) == S_IFIFO ) // FIFO
{
printf("p");
}
else
{
printf("d");
}
for ( i=3; i>0 ; --i )
{
tmp = (st_mode & mask) >> (i - 1)*N_BITS;
printf("%3s", perm[tmp]);
mask >>= N_BITS;
}
}
/*
void print_perm(mode_t st_mode)
{
printf("Now here!\n");
char str[11]; strcpy( str, "----------" );
//if ( S_ISDIR(mode) ) str[0] = 'd';
//if ( S_ISCHR(mode) ) str[0] = 'c';
//if ( S_ISBLK(mode) ) str[0] = 'b';
if ( st_mode & S_IRUSR ) str[1] = 'r';
if ( st_mode & S_IWUSR ) str[2] = 'w';
if ( st_mode & S_IXUSR ) str[3] = 'x';
if ( st_mode & S_IRGRP ) str[4] = 'r';
if ( st_mode & S_IWGRP ) str[5] = 'w';
if ( st_mode & S_IXGRP ) str[6] = 'x';
if ( st_mode & S_IROTH ) str[7] = 'r';
if ( st_mode & S_IWOTH ) str[8] = 'w';
if ( st_mode & S_IXOTH ) str[9] = 'x';
printf("%s ",str);
}
*/
/** @Fn void file_info(const char *file)
* @brief 通过stat函数打印file的信息
* @param const char *file 文件名
* @return
*/
void file_info(const char *file)
{
struct stat buf;
if ( stat(file, &buf) != 0 )
{
printf("stat %s error! \n", file);
exit (-1);
}
struct passwd *p_passwd;
struct group *p_group;
int i;
char *p_time;
p_time = ctime(&(buf.st_mtime)); // 获取文件时间
p_passwd = getpwuid(buf.st_uid); // get password file entry
p_group = getgrgid(buf.st_gid); // get grop file entry
print_perm(buf.st_mode);
printf(" %6d %s %s %12d ", buf.st_ino, p_passwd->pw_name, p_group->gr_name, buf.st_size);
for ( i=0; (p_time[i] != 0) && (p_time[i] != '\n'); i++ ) // 打印时间
{
putchar(p_time[i]);
}
printf(" %s\n", file);
}
/** @Fn void dir_info(const char *file)
* @brief 通过dir相关函数打印目录下面的信息
* @param const char *file 文件名
* @return
*/
void dir_info(const char *file)
{
DIR *dirp;
struct dirent *dp;
struct stat buf;
dirp = opendir(file);
if ( NULL == dirp )
{
printf("open dir %s error!\n", file);
exit (-1);
}
chdir(file);
while ( (dp = readdir(dirp)) != NULL )
{
if ( (0 == strcmp(dp->d_name, "."))|| (0 == strcmp(dp->d_name, "..")))
{
continue;
}
file_info(dp->d_name);
}
}
/** @Fn void show_file(const char *file)
* @brief 通过stat函数打印file的信息
* @param const char *file 文件名
* @return
*/
void show_file(const char *file)
{
struct stat buf;
if ( 0 == isDir(file) ) // 如果该文件是目录
{
printf("%s is a dir!\n", file);
dir_info(file); // 调用dir_info()显示信息
}
else
{
file_info(file); // 调用file_info()显示信息
}
}
/** @Fn int main(int argc, char *argv[])
* @brief 函数入口
* @param none
* @return 0 - true 1 - false
*/
int main(int argc, char *argv[])
{
if ( argc != 3 )
{
printf("Input format error!\n");
printf("<Usage> : ls -l file\n");
exit (1);
}
if ( strcmp(argv[1], "-l") != 0 )
{
printf("Input format error!\n");
printf("param is: -l\n");
exit (1);
}
if ( access(argv[2], F_OK) != 0 ) // 判断文件是否存在
{
printf("file not exitst!\n");
exit(-1);
}
show_file(argv[2]);
return 0;
}