【问题标题】:Scan a directory to find files pointed by soft links扫描目录以查找软链接指向的文件
【发布时间】:2018-11-21 19:30:45
【问题描述】:

我正在尝试为我的操作系统类做这个练习:我应该通过命令行传递一个特定的目录来查找其中软链接指向的任何文件。

这就是我所做的:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>

int main(int argc, char *argv[])
{

 DIR *dir_ptr;
 struct dirent *dir_str;
 struct stat buf;
 struct stat buf2;

 if(argc!=2)
 {
  printf("Error! I need a directory.\n");
  exit(-1);
 }


 if((dir_ptr=opendir(argv[1]))==NULL)       
 {
  printf("Opendir error: %s\n", strerror(errno));
  exit(-1);
 }

 while((dir_str=readdir(dir_ptr))!=NULL)
 {
  lstat(dir_str->d_name, &buf);     
  if(S_ISLNK(buf.st_mode))
  {
   stat(dir_str->d_name, &buf2);
   printf("'%s' points to a file of %ld bytes.\n", dir_str->d_name, buf2.st_size);
  }

 }

 closedir(dir_ptr);
 exit(0);

}

现在我的问题是:这个程序只是将所有指向特定大小文件的软链接写入标准输出。相反,我需要它打印软链接指向的所有文件。其次,奇怪的是,这个程序似乎只有在不需要目录的情况下才能工作,我的意思是,用getcwd()获取当前目录并将返回的路径名传递给opendir()。这个事实上甚至不打印传递目录中的所有软链接。

提前致谢!任何帮助将不胜感激。

编辑:假设我们有一个名为“my_directory”的目录,其中包含以下文件:

justatext.txt
softlink1 (it points to justatext.txt)
justanothertext.txt
softlink2(it points to justanothertext)

当我通过命令行(./a.out my_directory)传递“my_directory”时,我希望程序写入标准输出“justatext.txt”和“justanothertext.txt”,因为目录中的这些文件由软链接。 如果我将此目录传递给我的程序,则不会打印任何输出。

【问题讨论】:

  • 请向我们展示一些示例“输入”(参数)以及预期和实际输出。我也推荐你learn how to debug your programs
  • 使用 readlink() 获取存储在符号链接中的路径名,命名为它的参数(注意——它不会终止字符串)。
  • 您想显示作为软链接目标的文件吗?即使链接位于另一个目录中?
  • @Gerhardh 是的,我愿意。我想显示一个软链接指向的所有文件,最好是在同一个目录下,但这不是必须的。
  • 你想让exit(-1)做什么?在 Linux 中退出代码只能是 0 到 127。通常的做法是使用exit(1)

标签: c directory operating-system posix symlink


【解决方案1】:

好的,我想我已经解决了我的问题。总结了 cmets 中的所有建议,这就是我所做的,并且似乎有效:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <limits.h>     
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>

int main(int argc, char *argv[])
{

 DIR *dir_ptr;
 struct dirent *dir_str;
 struct stat buf;
 struct stat buf2;
 char *buf3;            
 ssize_t nbyte, bufsize;
 int flag=0;

 if(argc!=2)
 {
  printf("Error! I need a directory.\n");
  exit(EXIT_FAILURE);
 }

 if((dir_ptr=opendir(argv[1]))==NULL)
 {
  printf("Opendir error: %s\n", strerror(errno));
  exit(EXIT_FAILURE);
 }

 chdir(argv[1]);    

 while((dir_str=readdir(dir_ptr))!=NULL)    
 {
  lstat(dir_str->d_name, &buf);     
  bufsize=buf.st_size+1;    
  if(buf.st_size==0)        
   bufsize=PATH_MAX;        

  buf3=malloc(bufsize); 
  if(buf3==NULL)
  {
   perror("malloc");
   exit(EXIT_FAILURE);
  }
  nbyte=readlink(dir_str->d_name, buf3, bufsize);   

  if(S_ISLNK(buf.st_mode))  
  {
   stat(dir_str->d_name, &buf2);
   printf("%s is a file of %ld bytes pointed by a symbolic link (%s).\n", buf3, buf2.st_size, dir_str->d_name);
   flag+=1;
  }

 }

 if(flag==0)
  printf("No files pointed by a syslink found in this directory!\n");

 free(buf3);
 closedir(dir_ptr);
 exit(0);

}

首先,我使用chdir() 来通过命令行更改当前目录;然后我实现了readlink() 来获取符号链接中的路径名,命名为它的参数。如果发生错误,我还使用exit(EXIT_FAILURE) 关闭程序。

我不知道这是否完全正确。如果不是这样,请告诉我!

【讨论】: