zoukankan      html  css  js  c++  java
  • linux关于 文件/文件夹的操作 中

    说一个关于stat函数

    stat函数

    表头文件:    #include <sys/stat.h> 
    函数定义:    int stat(const char *file_name, struct stat *buf); 
    函数说明:    通过文件名filename获取文件信息,并保存在buf所指的结构体stat中 
    返回值:     执行成功则返回0,失败返回-1,错误代码存于errno(需要include <errno.h>)

    errno错误代码: 
        ENOENT         参数file_name指定的文件不存在 
        ENOTDIR        路径中的目录存在但却非真正的目录 
        ELOOP          欲打开的文件有过多符号连接问题,上限为16符号连接 
        EFAULT         参数buf为无效指针,指向无法存在的内存空间 
        EACCESS        存取文件时被拒绝 
        ENOMEM         核心内存不足 
        ENAMETOOLONG   参数file_name的路径名称太长

    stat结构体定义:

    struct stat { 
        dev_t         st_dev;       //文件的设备编号 
        ino_t         st_ino;         //节点 
        mode_t        st_mode;   //文件的类型和存取的权限 
        nlink_t       st_nlink;      //连到该文件的硬连接数目,刚建立的文件值为1 
        uid_t         st_uid;        //用户ID 
        gid_t         st_gid;        //组ID 
        dev_t         st_rdev;     //(设备类型)若此文件为设备文件,则为其设备编号 
        off_t         st_size;       //文件字节数(文件大小) 
        unsigned long st_blksize;   //块大小(文件系统的I/O 缓冲区大小) 
        unsigned long st_blocks;   //块数 
        time_t        st_atime;      //最后一次访问时间 
        time_t        st_mtime;     //最后一次修改时间 
        time_t        st_ctime;     //最后一次改变时间(指属性) 
    };

    示例代码:

    #include <sys/stat.h>
    #include <stdio.h>
    #include <errno.h>
    
    int main()
    {
        struct stat buf;
        int res = stat("test.txt", &buf);
        if(res != 0)
        {
            printf("stat file fail!
    ");
    
            printf("%d
    ", errno);
        }
        return 0;
    }



    /************************************************************************************华丽的分割线********************************************************************************************/
    下面有些地方是属于转来的,有些是自己补充的,转来的原出处已经不可访问

    最近在看Linux下文件操作相关章节,遇到了这么几个结构体,被搞的晕乎乎的,今日有空,仔细研究了一下,受益匪浅。

    首先说说DIR这一结构体,以下为DIR结构体的定义:

     1 struct __dirstream
     2    {
     3     void *__fd;
     4     char *__data;
     5     int __entry_data;
     6     char *__ptr;
     7     int __entry_ptr;
     8     size_t __allocation;
     9     size_t __size;
    10     __libc_lock_define (, __lock)
    11    };
    12 typedef struct __dirstream DIR;

    DIR结构体类似于FILE,是一个内部结构,以下几个函数用这个内部结构保存当前正在被读取的目录的有关信息(摘自《UNIX环境高级编程(第二版)》)。函数 DIR *opendir(const char *pathname),即打开文件目录,返回的就是指向DIR结构体的指针,而该指针由以下几个函数使用:

    1 struct dirent *readdir(DIR *dp);
    2 void rewinddir(DIR *dp);
    3 int closedir(DIR *dp);
    4 long telldir(DIR *dp);
    5 void seekdir(DIR *dp,long loc);

    关于DIR结构,我们知道这么多就可以了,没必要去再去研究他的结构成员。

    接着是dirent结构体,首先我们要弄清楚目录文件(directory file)的概念:这种文件包含了其他文件的名字以及指向与这些文件有关的信息的指针(摘自《UNIX环境高级编程(第二版)》)。从定义能够看出,dirent不仅仅指向目录,还指向目录中的具体文件,readdir函数同样也读取目录下的文件,这就是证据。以下为dirent结构体的定义:

    1 struct dirent
    2 {
    3   long d_ino; /* inode number 索引节点号 */
    4     off_t d_off; /* offset to this dirent 在目录文件中的偏移 */
    5     unsigned short d_reclen; /* length of this d_name 文件名长 */
    6     unsigned char d_type; /* the type of d_name 文件类型 */
    7     char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */
    8 }

     补充

    28 以下内容转自http://blog.csdn.NET/angle_birds/article/details/8503039
    29 
    30 unsigned char d_type
    31 d_type表示档案类型:
    32 enum
    33 { 
    34     DT_UNKNOWN = 0,       //The type is unknown. Only some filesystems have full support to return the type of the file, others might always return this value.类型未知。少数文件系统会出现此函数不支持的文件类型,另一些则总是返回这个值。总之这个值是为了应对不兼容的文件系统而设置的。
    35  # define DT_UNKNOWN DT_UNKNOWN  
    36      DT_FIFO = 1,         //A named pipe, or FIFO. See FIFO Special Files.一个命名管道,或FIFO。
    37  # define DT_FIFO DT_FIFO 
    38      DT_CHR = 2,         //A character device.字符设备
    39  # define DT_CHR DT_CHR 
    40      DT_DIR = 4,          //A directory.目录
    41  # define DT_DIR DT_DIR 
    42      DT_BLK = 6,         //A block device.块设备
    43  # define DT_BLK DT_BLK 
    44      DT_REG = 8,         //A regular file.常规文件
    45  # define DT_REG DT_REG 
    46      DT_LNK = 10,        //A symbolic link. 符号链接
    47  # define DT_LNK DT_LNK 
    48      DT_SOCK = 12,           //A local-domain socket.套接字
    49  # define DT_SOCK DT_SOCK 
    50      DT_WHT = 14 
    51  # define DT_WHT DT_WHT 
    52 }; 

    从上述定义也能够看出来,dirent结构体存储的关于文件的信息很少,所以dirent同样也是起着一个索引的作用,如果想获得类似ls -l那种效果的文件信息,必须要靠stat函数了。

    通过readdir函数读取到的文件名存储在结构体dirent的d_name成员中,而函数

    int stat(const char *file_name, struct stat *buf);

    的作用就是获取文件名为d_name的文件的详细信息,存储在stat结构体中。以下为stat结构体的定义:

     1 struct stat {
     2         mode_t     st_mode;       //文件访问权限
     3         ino_t      st_ino;       //索引节点号
     4         dev_t      st_dev;        //文件使用的设备号
     5         dev_t      st_rdev;       //设备文件的设备号
     6         nlink_t    st_nlink;      //文件的硬连接数
     7         uid_t      st_uid;        //所有者用户识别号
     8         gid_t      st_gid;        //组识别号
     9         off_t      st_size;       //以字节为单位的文件容量
    10         time_t     st_atime;      //最后一次访问该文件的时间
    11         time_t     st_mtime;      //最后一次修改该文件的时间
    12         time_t     st_ctime;      //最后一次改变该文件状态的时间
    13         blksize_t st_blksize;    //包含该文件的磁盘块的大小
    14         blkcnt_t   st_blocks;     //该文件所占的磁盘块
    15       };

    补充:

    int stat(const char *path, struct stat *buf);
    
    int lstat(const char *path, struct stat *buf);
    
    int fstat(int filedes, struct stat *buf);

    聪明人一眼就能看出来fstat的第一个参数是和另外两个不一样的,对!fstat区别于另外两个系统调用的地方在于,fstat系统调用接受的是 一个“文件描述符”,而另外两个则直接接受“文件全路径”。文件描述符是需要我们用open系统调用后才能得到的,而文件全路经直接写就可以了。

    stat和lstat的区别:当文件是一个符号链接时,lstat返回的是该符号链接本身的信息;而stat返回的是该链接指向的文件的信息。(似乎有些晕吧,这样记,lstat比stat多了一个l,因此它是有本事处理符号链接文件的,因此当遇到符号链接文件时,lstat当然不会放过。而 stat系统调用没有这个本事,它只能对符号链接文件睁一只眼闭一只眼,直接去处理链接所指文件喽)

    最后,总结一下,想要获取某目录下(比如a目下)b文件的详细信息,我们应该怎样做?

    首先,我们使用opendir函数打开目录a,返回指向目录a的DIR结构体c。

    接着,我们调用readdir( c)函数读取目录a下所有文件(包括目录),返回指向目录a下所有文件的dirent结构体d。

    然后,我们遍历d,调用stat(d->name,stat *e)来获取每个文件的详细信息,存储在stat结构体e中。

    总体就是这样一种逐步细化的过程,在这一过程中,三种结构体扮演着不同的角色。

    /************************************************************************************华丽的分割线********************************************************************************************/
    补充
    从测代码里面摘出了实现这个功能部分的代码:
    可以实现从指定目录下遍历所有的文件,然后读取所需的信息。
    But一般文件信息通过readdir也够用了,不一定要stat,stat函数如果文件不存在不会创建,但是fopen如果文件不存在,会创建一个
     1 #include <unistd.h>  
     2 #include <stdio.h>  
     3 #include <stdlib.h>  
     4 #include <stddef.h>  
     5 #include <string.h>  
     6 #include <errno.h>  
     7 #include <getopt.h>  
     8 #include <fcntl.h>  
     9 #include <errno.h>  
    10 #include <signal.h>  
    11 #include <getopt.h>  
    12 #include <sys/time.h>  
    13 #include <sys/socket.h>  
    14 #include <sys/un.h>  
    15 #include <sys/select.h>  
    16 #include <linux/types.h>  
    17 #include <linux/netlink.h>  
    18 #include <sys/types.h>
    19 #include <libudev.h>
    20 #include <iostream>
    21 #include <pthread.h>
    22 #include <sys/mount.h>
    23 #include <sys/stat.h>
    24 #include <dirent.h>
    25 #include <time.h>
    26 #include <sys/stat.h>
    27 using namespace std;
    28 
    29 //Specify the path and then loop check the folder/file under the path/subpath
    30 void LoopFolder_FindFile(const string BasicPath)
    31 {
    32     DIR *pDir=NULL;
    33     struct dirent *pDirent=NULL;
    34     pDir=opendir(BasicPath.c_str());
    35 
    36 
    37     if(pDir==NULL)
    38     {
    39         printf("error type %d
    ", errno);
    40     }
    41     else
    42     {
    43         //loop read the dir,
    44         /*The  readdir()  function returns a pointer to a dirent structure representing the next directory entry in the directory stream pointed to by dirp.  It returns NULL on reaching the end of the directory
    45         stream or if an error occurred.*/
    46         while((pDirent=readdir(pDir))!=NULL)
    47         {            
    48             if(strcmp(pDirent->d_name,".")==0 || strcmp(pDirent->d_name,"..")==0)    ///current dir OR parrent dir
    49             {                            
    50                 continue;
    51             }
    52 
    53             if(pDirent->d_type==4) //means it is a dir
    54             {                            
    55                 string basepath(BasicPath);
    56                 basepath.append("/");
    57                 basepath.append(pDirent->d_name);
    58                 LoopFolder_FindFile(basepath);
    59             }
    60             else if (pDirent->d_type==8) //regular file
    61             {                
    62                 string filepath(BasicPath);
    63                 filepath.append("/");
    64                 filepath.append(pDirent->d_name);
    65 
    66                 if(strcmp(pDirent->d_name,"Record_FILE")==0)
    67                 {                
    68                     printf(" path=%s 
      ", filepath.c_str());
    69                     struct stat buf;    
    70                     int retv=stat(filepath.c_str(),&buf);
    71                     if(retv==-1)
    72                     {
    73                         printf("File error with error code=%d
    ",errno);
    74                     }
    75                     else
    76                     {
    77                         printf("st_uid=%d
     LastModified Time is:
     %s
    ", buf.st_uid,ctime(&(buf.st_mtime)));
    78                     }
    79                                     
    80                 }    
    81 
    82             }
    83         }    
    84         if(pDir!=NULL)
    85            {
    86                closedir(pDir);
    87            }
    88     }
    89 }
    90 int main()  
    91 {      
    92     LoopFolder_FindFile("/mnt/hgfs/0_SharedFolder/0_Local_Test_Folder/01_TestFolder/");
    93 }

     

    /************************************************************************************华丽的分割线********************************************************************************************/


    以下主要来自2.6.32的内核代码中的/usr/include/asm-generic/errno.h及errno-base.h,输出错误原因定义归纳整理如下:
      1   #define EPERM 1 /* Operation not permitted */
      2   #define ENOENT 2 /* No such file or directory */
      3   #define ESRCH 3 /* No such process */
      4   #define EINTR 4 /* Interrupted system call */
      5   #define EIO 5 /* I/O error */
      6   #define ENXIO 6 /* No such device or address */
      7   #define E2BIG 7 /* Argument list too long */
      8   #define ENOEXEC 8 /* Exec format error */
      9   #define EBADF 9 /* Bad file number */
     10   #define ECHILD 10 /* No child processes */
     11   #define EAGAIN 11 /* Try again */
     12   #define ENOMEM 12 /* Out of memory */
     13   #define EACCES 13 /* Permission denied */
     14   #define EFAULT 14 /* Bad address */
     15   #define ENOTBLK 15 /* Block device required */
     16   #define EBUSY 16 /* Device or resource busy */
     17   #define EEXIST 17 /* File exists */
     18   #define EXDEV 18 /* Cross-device link */
     19   #define ENODEV 19 /* No such device */
     20   #define ENOTDIR 20 /* Not a directory */
     21   #define EISDIR 21 /* Is a directory */
     22   #define EINVAL 22 /* Invalid argument */
     23   #define ENFILE 23 /* File table overflow */
     24   #define EMFILE 24 /* Too many open files */
     25   #define ENOTTY 25 /* Not a typewriter */
     26   #define ETXTBSY 26 /* Text file busy */
     27   #define EFBIG 27 /* File too large */
     28   #define ENOSPC 28 /* No space left on device */
     29   #define ESPIPE 29 /* Illegal seek */
     30   #define EROFS 30 /* Read-only file system */
     31   #define EMLINK 31 /* Too many links */
     32   #define EPIPE 32 /* Broken pipe */
     33   #define EDOM 33 /* Math argument out of domain of func */
     34   #define ERANGE 34 /* Math result not representable */
     35   #define EDEADLK 35 /* Resource deadlock would occur */
     36   #define ENAMETOOLONG 36 /* File name too long */
     37   #define ENOLCK 37 /* No record locks available */
     38   #define ENOSYS 38 /* Function not implemented */
     39   #define ENOTEMPTY 39 /* Directory not empty */
     40   #define ELOOP 40 /* Too many symbolic links encountered */
     41   #define EWOULDBLOCK EAGAIN /* Operation would block */
     42   #define ENOMSG 42 /* No message of desired type */
     43   #define EIDRM 43 /* Identifier removed */
     44   #define ECHRNG 44 /* Channel number out of range */
     45   #define EL2NSYNC 45 /* Level 2 not synchronized */
     46   #define EL3HLT 46 /* Level 3 halted */
     47   #define EL3RST 47 /* Level 3 reset */
     48   #define ELNRNG 48 /* Link number out of range */
     49   #define EUNATCH 49 /* Protocol driver not attached */
     50   #define ENOCSI 50 /* No CSI structure available */
     51   #define EL2HLT 51 /* Level 2 halted */
     52   #define EBADE 52 /* Invalid exchange */
     53   #define EBADR 53 /* Invalid request descriptor */
     54   #define EXFULL 54 /* Exchange full */
     55   #define ENOANO 55 /* No anode */
     56   #define EBADRQC 56 /* Invalid request code */
     57   #define EBADSLT 57 /* Invalid slot */
     58   #define EDEADLOCK EDEADLK
     59   #define EBFONT 59 /* Bad font file format */
     60   #define ENOSTR 60 /* Device not a stream */
     61   #define ENODATA 61 /* No data available */
     62   #define ETIME 62 /* Timer expired */
     63   #define ENOSR 63 /* Out of streams resources */
     64   #define ENONET 64 /* Machine is not on the network */
     65   #define ENOPKG 65 /* Package not installed */
     66   #define EREMOTE 66 /* Object is remote */
     67   #define ENOLINK 67 /* Link has been severed */
     68   #define EADV 68 /* Advertise error */
     69   #define ESRMNT 69 /* Srmount error */
     70   #define ECOMM 70 /* Communication error on send */
     71   #define EPROTO 71 /* Protocol error */
     72   #define EMULTIHOP 72 /* Multihop attempted */
     73   #define EDOTDOT 73 /* RFS specific error */
     74   #define EBADMSG 74 /* Not a data message */
     75   #define EOVERFLOW 75 /* Value too large for defined data type */
     76   #define ENOTUNIQ 76 /* Name not unique on network */
     77   #define EBADFD 77 /* File descriptor in bad state */
     78   #define EREMCHG 78 /* Remote address changed */
     79   #define ELIBACC 79 /* Can not access a needed shared library */
     80   #define ELIBBAD 80 /* Accessing a corrupted shared library */
     81   #define ELIBSCN 81 /* .lib section in a.out corrupted */
     82   #define ELIBMAX 82 /* Attempting to link in too many shared libraries */
     83   #define ELIBEXEC 83 /* Cannot exec a shared library directly */
     84   #define EILSEQ 84 /* Illegal byte sequence */
     85   #define ERESTART 85 /* Interrupted system call should be restarted */
     86   #define ESTRPIPE 86 /* Streams pipe error */
     87   #define EUSERS 87 /* Too many users */
     88   #define ENOTSOCK 88 /* Socket operation on non-socket */
     89   #define EDESTADDRREQ 89 /* Destination address required */
     90   #define EMSGSIZE 90 /* Message too long */
     91   #define EPROTOTYPE 91 /* Protocol wrong type for socket */
     92   #define ENOPROTOOPT 92 /* Protocol not available */
     93   #define EPROTONOSUPPORT 93 /* Protocol not supported */
     94   #define ESOCKTNOSUPPORT 94 /* Socket type not supported */
     95   #define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
     96   #define EPFNOSUPPORT 96 /* Protocol family not supported */
     97   #define EAFNOSUPPORT 97 /* Address family not supported by protocol */
     98   #define EADDRINUSE 98 /* Address already in use */
     99   #define EADDRNOTAVAIL 99 /* Cannot assign requested address */
    100   #define ENETDOWN 100 /* Network is down */
    101   #define ENETUNREACH 101 /* Network is unreachable */
    102   #define ENETRESET 102 /* Network dropped connection because of reset */
    103   #define ECONNABORTED 103 /* Software caused connection abort */
    104   #define ECONNRESET 104 /* Connection reset by peer */
    105   #define ENOBUFS 105 /* No buffer space available */
    106   #define EISCONN 106 /* Transport endpoint is already connected */
    107   #define ENOTCONN 107 /* Transport endpoint is not connected */
    108   #define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
    109   #define ETOOMANYREFS 109 /* Too many references: cannot splice */
    110   #define ETIMEDOUT 110 /* Connection timed out */
    111   #define ECONNREFUSED 111 /* Connection refused */
    112   #define EHOSTDOWN 112 /* Host is down */
    113   #define EHOSTUNREACH 113 /* No route to host */
    114   #define EALREADY 114 /* Operation already in progress */
    115   #define EINPROGRESS 115 /* Operation now in progress */
    116   #define ESTALE 116 /* Stale NFS file handle */
    117   #define EUCLEAN 117 /* Structure needs cleaning */
    118   #define ENOTNAM 118 /* Not a XENIX named type file */
    119   #define ENAVAIL 119 /* No XENIX semaphores available */
    120   #define EISNAM 120 /* Is a named type file */
    121   #define ENOKEY 126 /* Required key not available */
    122   #define EKEYEXPIRED 127 /* Key has expired */
    123   #define EKEYREVOKED 128 /* Key has been revoked */
    124   #define EKEYREJECTED 129 /* Key was rejected by service */
    125   #define EOWNERDEAD 130 /* Owner died */
    126   #define ENOTRECOVERABLE 131 /* State not recoverable */
    127   #define ERFKILL 132 /* Operation not possible due to RF-kill */
    128   #define EHWPOISON 133 /* Memory page has hardware error */
  • 相关阅读:
    用GDB调试程序(一)
    vim添加删除多行注释
    python binary lib on win/各种python库的二进制包
    python使用libssh2连接linux
    python xpath
    splinter python浏览器自动化操作,模拟浏览器的行为
    pytesser图片文本识别
    python验证码识别
    Python 之 使用 PIL 库做图像处理
    Connection reset by peer问题分析
  • 原文地址:https://www.cnblogs.com/jlmgary/p/6742557.html
Copyright © 2011-2022 走看看