Linux "ls -al" 喜欢 C 中的程序
Linux "ls -al" like program in C
我有作业要写一个C程序,它的作用类似于Linux "ls -al"命令。我知道互联网上有很多示例程序,它们正在做我需要的事情,但我有一个特定的问题,我找不到解决方案。我还想提一下,我是 C 编程的新手。这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#include <pwd.h>
int list_dir(const char *dirname) {
struct dirent* current_directory;
struct stat my_stat;
struct tm lt;
struct passwd *pwd; // For User-ID
DIR* directory = opendir(dirname);
if(directory == NULL) {
printf("list_dir : %s : %s \n", dirname, strerror(errno));
return 0;
}
printf("Directory : %s\n", dirname);
printf("\n");
while( (current_directory = readdir(directory) ) ) {
stat(current_directory->d_name, &my_stat);
if ( (stat(current_directory->d_name, &my_stat) ) == 0 ) {
pwd = getpwuid(my_stat.st_uid); // Get User-ID
}
// Last Modified
time_t t = my_stat.st_mtime;
localtime_r(&t, <);
char timebuf[80];
strftime(timebuf, sizeof(timebuf), "%c", <);
if (pwd != 0) {
printf("%s \t %ld \t %s \t %s", pwd->pw_name, (long)my_stat.st_size, timebuf, current_directory->d_name);
printf("\n");
} else {
printf("%d \t %ld \t %s \t %s", my_stat.st_uid, (long)my_stat.st_size, timebuf, current_directory->d_name);
printf("\n");
}
}
closedir(directory);
return 0;
}
int main(int argc, char* argv[]) {
if ( argc == 1 ) {
return list_dir ( "." );
} else {
int ret = 0;
for (int i = 1; i < argc; i += 1 ) {
if ( list_dir ( argv[i] ) != 0 ) {
ret = 1;
}
}
return ret;
}
}
该程序必须显示与 "ls -al" 相同的内容(没有权限)。到目前为止一切顺利,如果我用 "gcc -std=gnu99 -o list_dir list_dir.c" 编译它并用“./list_dir” 执行程序,我得到与 "ls -al" 相同的结果,它看起来像这样:
username 1599 Fri May 1 20:43:57 2015 list_dir.c
但是,如果我 运行 程序带有类似的东西:“./list_dir /home/username/Downloads/” 我得到这个:
32727 0 Sun May 8 07:09:04 4461391 selection_sort.c
如您所见,程序无法获取有关用户名、文件大小和年份的正确信息。由于 if(pwd != 0) 语句的 else 情况,此信息也出现了。如果我没有 else 情况,程序将只打印出文件,它可以获得正确的信息。另外,如果我删除此 if 语句以及 if 语句:
if ( (stat(current_directory->d_name, &my_stat) ) == 0 )
我遇到了分段错误。
所以我的问题是:
1.What 我做错了吗?我知道我做错了什么,因为作为家庭作业的提示,我有一个程序示例 运行 以及我可以使用 "stat, lstat, readlink, getpwnam, getpwuid, strftime".
的提示
2.Is 有什么方法可以使用 stat() 和用户 ID 获取用户名,还是只能使用 getpwuid?
这里,
if ( (stat(current_directory->d_name, &my_stat) ) == 0 ) {
pwd = getpwuid(my_stat.st_uid); // Get User-ID
}
如果 stat()
失败会怎样? pwd
将具有未初始化的值或从上一次迭代中设置的不正确的值。
stat
失败的原因是,current_directory->d_name
仅包含文件名,而 stat
需要完整路径。因此,您需要将目录名称添加到文件中并将其传递给 stat()
。您现在只传递文件名。
类似于:
char buf[1024];
errno = 0;
snprintf(buf, sizeof buf, "%s/%s", dirname, current_directory->d_name);
if ( (stat(buf, &my_stat) ) == 0 ) {
...
}
else {
printf("%s: %s\n", buf, strerror(errno));
// exit here or continue to the next entry in the directory
//depending how you wish to handle failure
}
并在 stat()
失败时处理错误。
您在循环中还有另一个 stat()
,它什么都不做。
我有作业要写一个C程序,它的作用类似于Linux "ls -al"命令。我知道互联网上有很多示例程序,它们正在做我需要的事情,但我有一个特定的问题,我找不到解决方案。我还想提一下,我是 C 编程的新手。这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#include <pwd.h>
int list_dir(const char *dirname) {
struct dirent* current_directory;
struct stat my_stat;
struct tm lt;
struct passwd *pwd; // For User-ID
DIR* directory = opendir(dirname);
if(directory == NULL) {
printf("list_dir : %s : %s \n", dirname, strerror(errno));
return 0;
}
printf("Directory : %s\n", dirname);
printf("\n");
while( (current_directory = readdir(directory) ) ) {
stat(current_directory->d_name, &my_stat);
if ( (stat(current_directory->d_name, &my_stat) ) == 0 ) {
pwd = getpwuid(my_stat.st_uid); // Get User-ID
}
// Last Modified
time_t t = my_stat.st_mtime;
localtime_r(&t, <);
char timebuf[80];
strftime(timebuf, sizeof(timebuf), "%c", <);
if (pwd != 0) {
printf("%s \t %ld \t %s \t %s", pwd->pw_name, (long)my_stat.st_size, timebuf, current_directory->d_name);
printf("\n");
} else {
printf("%d \t %ld \t %s \t %s", my_stat.st_uid, (long)my_stat.st_size, timebuf, current_directory->d_name);
printf("\n");
}
}
closedir(directory);
return 0;
}
int main(int argc, char* argv[]) {
if ( argc == 1 ) {
return list_dir ( "." );
} else {
int ret = 0;
for (int i = 1; i < argc; i += 1 ) {
if ( list_dir ( argv[i] ) != 0 ) {
ret = 1;
}
}
return ret;
}
}
该程序必须显示与 "ls -al" 相同的内容(没有权限)。到目前为止一切顺利,如果我用 "gcc -std=gnu99 -o list_dir list_dir.c" 编译它并用“./list_dir” 执行程序,我得到与 "ls -al" 相同的结果,它看起来像这样:
username 1599 Fri May 1 20:43:57 2015 list_dir.c
但是,如果我 运行 程序带有类似的东西:“./list_dir /home/username/Downloads/” 我得到这个:
32727 0 Sun May 8 07:09:04 4461391 selection_sort.c
如您所见,程序无法获取有关用户名、文件大小和年份的正确信息。由于 if(pwd != 0) 语句的 else 情况,此信息也出现了。如果我没有 else 情况,程序将只打印出文件,它可以获得正确的信息。另外,如果我删除此 if 语句以及 if 语句:
if ( (stat(current_directory->d_name, &my_stat) ) == 0 )
我遇到了分段错误。
所以我的问题是: 1.What 我做错了吗?我知道我做错了什么,因为作为家庭作业的提示,我有一个程序示例 运行 以及我可以使用 "stat, lstat, readlink, getpwnam, getpwuid, strftime".
的提示2.Is 有什么方法可以使用 stat() 和用户 ID 获取用户名,还是只能使用 getpwuid?
这里,
if ( (stat(current_directory->d_name, &my_stat) ) == 0 ) {
pwd = getpwuid(my_stat.st_uid); // Get User-ID
}
如果 stat()
失败会怎样? pwd
将具有未初始化的值或从上一次迭代中设置的不正确的值。
stat
失败的原因是,current_directory->d_name
仅包含文件名,而 stat
需要完整路径。因此,您需要将目录名称添加到文件中并将其传递给 stat()
。您现在只传递文件名。
类似于:
char buf[1024];
errno = 0;
snprintf(buf, sizeof buf, "%s/%s", dirname, current_directory->d_name);
if ( (stat(buf, &my_stat) ) == 0 ) {
...
}
else {
printf("%s: %s\n", buf, strerror(errno));
// exit here or continue to the next entry in the directory
//depending how you wish to handle failure
}
并在 stat()
失败时处理错误。
您在循环中还有另一个 stat()
,它什么都不做。