C语言 - 在其他目录中获取错误的文件权限

时间:2016-10-17 18:30:06

标签: c directory-structure

我是C语言的新手,我很难找到代码中的问题所在。

它似乎在我拥有该程序的当前文件夹中正常工作,但如果我尝试列出父目录的内容,我无法正确获取文件信息。

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>   
#include <sys/stat.h>
#include <limits.h>   
#include <string.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>

char TypeFile (mode_t m)
{
switch (m&S_IFMT) { 
    case S_IFSOCK:  return 's';  /*socket */
    case S_IFLNK:   return 'l';    /*symbolic link*/
    case S_IFREG:   return '-';   /* normal file*/
    case S_IFBLK:   return 'b';   /*block device*/
    case S_IFDIR:   return 'd';   /*directory */
    case S_IFCHR:   return 'c';   /*char  device*/
    case S_IFIFO:   return 'p';   /*pipe*/
    default: return '?';   /*unknown*/
}
}

char * Permissions (mode_t m)
{
static char p[12];
strcpy (p,"---------- ");
p[0]=TypeFile(m);
if (m&S_IRUSR) p[1]='r';  /*owner*/
if (m&S_IWUSR) p[2]='w';
if (m&S_IXUSR) p[3]='x';
if (m&S_IRGRP) p[4]='r';   /*group*/
if (m&S_IWGRP) p[5]='w';
if (m&S_IXGRP) p[6]='x';
if (m&S_IROTH) p[7]='r';   /*other*/
if (m&S_IWOTH) p[8]='w';
if (m&S_IXOTH) p[9]='x';
if (m&S_ISUID) p[3]='s';  /*setuid, setgid, stickybit*/
if (m&S_ISGID) p[6]='s';
if (m&S_ISVTX) p[9]='t';
return (p);
}



char * dateFormat (char *str, time_t val) {
strftime(str, 36, "%b %e %k:%M ", localtime(&val));
return str;
 }


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

/* Variables */
DIR *dirp;
struct dirent *direntp;
struct stat perm;
struct passwd *owner;
struct group *gr;

char path[PATH_MAX + 1];


/* Open dir */
if (argc == 1){ dirp = opendir("."); }  
else { dirp = opendir(argv[1]);      }  

if (dirp == NULL){
printf("Error: Can't open dir \n");
exit(1);
}

/* Read dir content */

char dat[36]; 
while ((direntp = readdir(dirp)) != NULL) {

    realpath(direntp->d_name,path); 
    lstat(path,&perm);           

    if (direntp->d_name[0] == '.') { continue; }    
    printf("%10ld\t%4s\t", direntp->d_ino, Permissions(perm.st_mode)); 
    printf("%4u\t", perm.st_nlink); 

    if ((owner= getpwuid(perm.st_uid)) != NULL) { 
        printf("%4s\t", owner->pw_name);
    }
    else {
        printf("%4d\t", perm.st_uid);
    }

    if ((group = getgrgid(perm.st_gid)) != NULL) {  
        printf("%4s\t", group->gr_name);
    }   
    else {
        printf("%4d\t", perm.st_gid);
    }
    printf("%4ld\t", perm.st_size); 
    printf("%4s\t%4s\n", dateFormat(dat,perm.st_mtime),direntp->d_name); 

  } 

/* Close */
closedir(dirp);

return 0;
}

这将是当前目录中的输出:

165277  -rw-rw-r--     1    me  me  4356    Oct 17 19:48    test.c
147877  -rw-rw-r--     1    me  me  4413    Oct 17 19:48    test.c~
157723  -rw-rw-r--     1    me  me  95981   Sep 15 16:50    Doc.pdf
157722  -rwxrwxr-x     1    me  me  12176   Oct 17 20:20    a.out
157720  -rw-rw-r--     1    me  me   617    Sep 22 19:47    other.c

如果我尝试列出父目录(..):

,这就是输出
163899  ?---------     0    root    root     0      Jan  1  1:00    b
163900  ?---------     0    root    root     0      Jan  1  1:00    ship
297613  drwxrwxr-x     4    me      me       4096   Oct 16 21:38    A.pdf

我怎么能解决这个问题?提前谢谢。

1 个答案:

答案 0 :(得分:1)

问题在于,当您将相对文件名提供给realpath()时,它会将其相对于当前工作目录进行规范化。请注意,direntp->d_name仅包含文件的基本名称,如果您../,则不包含任何opendir("..")。有两种方法可以修复您的程序:

  1. 致电if (argc > 1) chdir(argv[1]);后使用opendir()
  2. 请勿使用realpath(),而是在将其传递给"/"之前自行连接argv [1],direntp->d_namelstat()