• C++遍历目录,并把目录里超过7天的文件删除(跨平台windows&linux)


    C++遍历目录,并把目录里超过7天的文件删除,适用于项目里删除过期的日志,或者视频文件。

    在windows和linux下测试通过。

    windows测试结果:

    linux测试结果:

    源码:

      1 #include <time.h>
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <string.h>
      5 #include "dirent.h"
      6 #include <sys/stat.h>
      7 #include <errno.h>
      8 #ifdef WIN32
      9 
     10 #else
     11     #include <unistd.h>
     12 #endif
     13 
     14 static int find_directory (const char *dirname);
     15 
     16 
     17 int main(int argc, char *argv[])
     18 {
     19     int i;
     20     int result;
     21 
     22     //循环遍历命令行里的每个目录
     23     i = 1;
     24     while (i < argc) {
     25         result = find_directory (argv[i]);
     26         if (result == -1) {
     27             exit (EXIT_FAILURE);
     28         }
     29         i++;
     30     }
     31 
     32     //如果命令行参数为空,则遍历当前工作目录
     33     if (argc == 1) {
     34         find_directory (".");
     35     }
     36     return EXIT_SUCCESS;
     37 }
     38 
     39 //删除7天前的文件
     40 int RemoveFile( char* filename )
     41 {
     42    int result;
     43    //errno_t errno;
     44    //获取文件信息
     45 #ifdef WIN32
     46    struct _stat buf;
     47    result = _stat(filename, &buf);
     48 #else
     49    struct stat buf;
     50    result = stat(filename, &buf);
     51 #endif
     52 
     53    if( result != 0 )
     54    {
     55       perror( "Problem getting information" );
     56       switch (errno)
     57       {
     58          case ENOENT:
     59            printf("File %s not found.
    ", filename);
     60            break;
     61          case EINVAL:
     62            printf("Invalid parameter to _stat.
    ");
     63            break;
     64          default:
     65            /* Should never be reached. */
     66            printf("Unexpected error in _stat.
    ");
     67       }
     68       return -1;
     69    }
     70    else
     71    {
     72       // Output some of the statistics:
     73       printf( "File size     : %ld
    ", buf.st_size );
     74       printf( "Drive         : %c:
    ", buf.st_dev + 'A' );
     75 
     76       time_t t;
     77       tzset(); /*tzset()*/
     78       t = time(NULL);
     79       if((t - buf.st_mtime) > 604800)//604800是7天的秒数,下面是删除超过7天的文件
     80       {
     81         remove(filename);
     82         printf("remove file : %s 
    " ,filename);
     83       }
     84       return 0;
     85    }
     86 
     87 }
     88 
     89 //遍历子目录和目录中的文件
     90 static int find_directory(const char *dirname)
     91 {
     92     DIR *dir;
     93     char buffer[PATH_MAX + 2];
     94     char *p = buffer;
     95     const char *src;
     96     char *end = &buffer[PATH_MAX];
     97     int result; //返回结果
     98 
     99     //copy目录名到buffer
    100     src = dirname;
    101     while (p < end  &&  *src != '') {
    102         *p++ = *src++;
    103     }
    104     *p = '';
    105 
    106     //打开目录
    107     dir = opendir (dirname);
    108     if (dir != NULL) {
    109         struct dirent *ent;
    110 
    111         while ((ent = readdir (dir)) != NULL) {//这里返回的是当前目录.
    112             char *q = p;
    113             char c;
    114 
    115             //获得目录的最后一个字符
    116             if (buffer < q) {
    117                 c = q[-1];
    118             } else {
    119                 c = ':';
    120             }
    121 
    122             //在当前给出的目录下加上/
    123             if (c != ':'  &&  c != '/'  &&  c != '\') {
    124                 *q++ = '/';
    125             }
    126 
    127             //把文件名附加在后面
    128             src = ent->d_name; //src 为根目录.
    129             while (q < end  &&  *src != '') {
    130                 *q++ = *src++;
    131             }
    132             *q = '';
    133 
    134             //根据是否是文件还是目录来选择操作
    135             switch (ent->d_type) {
    136             case DT_LNK:
    137             case DT_REG:
    138                 //如果是文件
    139                 printf ("%s
    ", buffer);
    140                 RemoveFile(buffer);
    141                 break;
    142 
    143             case DT_DIR:
    144                 //如果是目录
    145                 if (strcmp (ent->d_name, ".") != 0
    146                         &&  strcmp (ent->d_name, "..") != 0) {
    147                     find_directory (buffer);
    148                 }
    149                 break;
    150 
    151             default:
    152                 /* Ignore device entries */
    153                 /*NOP*/;
    154             }
    155 
    156         }
    157 
    158         closedir (dir);
    159         result = 0;
    160 
    161     } else {
    162         //目录打不开
    163         printf ("Cannot open directory %s
    ", dirname);
    164         result = -1;
    165     }
    166 
    167     return result;
    168 }

    dirent.h文件代码如下:

      1 /*
      2  * dirent.h - dirent API for Microsoft Visual Studio
      3  *
      4  * Copyright (C) 2006-2012 Toni Ronkko
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining
      7  * a copy of this software and associated documentation files (the
      8  * ``Software''), to deal in the Software without restriction, including
      9  * without limitation the rights to use, copy, modify, merge, publish,
     10  * distribute, sublicense, and/or sell copies of the Software, and to
     11  * permit persons to whom the Software is furnished to do so, subject to
     12  * the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included
     15  * in all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
     18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     20  * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR
     21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     23  * OTHER DEALINGS IN THE SOFTWARE.
     24  *
     25  * $Id: dirent.h,v 1.20 2014/03/19 17:52:23 tronkko Exp $
     26  */
     27 #ifndef DIRENT_H
     28 #define DIRENT_H
     29 
     30 /*
     31  * Define architecture flags so we don't need to include windows.h.
     32  * Avoiding windows.h makes it simpler to use windows sockets in conjunction
     33  * with dirent.h.
     34  */
     35 #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86)
     36 #   define _X86_
     37 #endif
     38 #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_AMD64)
     39 #define _AMD64_
     40 #endif
     41 
     42 #include <stdio.h>
     43 #include <stdarg.h>
     44 #include <windef.h>
     45 #include <winbase.h>
     46 #include <wchar.h>
     47 #include <string.h>
     48 #include <stdlib.h>
     49 #include <malloc.h>
     50 #include <sys/types.h>
     51 #include <sys/stat.h>
     52 #include <errno.h>
     53 
     54 /* Indicates that d_type field is available in dirent structure */
     55 #define _DIRENT_HAVE_D_TYPE
     56 
     57 /* Indicates that d_namlen field is available in dirent structure */
     58 #define _DIRENT_HAVE_D_NAMLEN
     59 
     60 /* Entries missing from MSVC 6.0 */
     61 #if !defined(FILE_ATTRIBUTE_DEVICE)
     62 #   define FILE_ATTRIBUTE_DEVICE 0x40
     63 #endif
     64 
     65 /* File type and permission flags for stat() */
     66 #if !defined(S_IFMT)
     67 #   define S_IFMT   _S_IFMT                     /* File type mask */
     68 #endif
     69 #if !defined(S_IFDIR)
     70 #   define S_IFDIR  _S_IFDIR                    /* Directory */
     71 #endif
     72 #if !defined(S_IFCHR)
     73 #   define S_IFCHR  _S_IFCHR                    /* Character device */
     74 #endif
     75 #if !defined(S_IFFIFO)
     76 #   define S_IFFIFO _S_IFFIFO                   /* Pipe */
     77 #endif
     78 #if !defined(S_IFREG)
     79 #   define S_IFREG  _S_IFREG                    /* Regular file */
     80 #endif
     81 #if !defined(S_IREAD)
     82 #   define S_IREAD  _S_IREAD                    /* Read permission */
     83 #endif
     84 #if !defined(S_IWRITE)
     85 #   define S_IWRITE _S_IWRITE                   /* Write permission */
     86 #endif
     87 #if !defined(S_IEXEC)
     88 #   define S_IEXEC  _S_IEXEC                    /* Execute permission */
     89 #endif
     90 #if !defined(S_IFIFO)
     91 #   define S_IFIFO _S_IFIFO                     /* Pipe */
     92 #endif
     93 #if !defined(S_IFBLK)
     94 #   define S_IFBLK   0                          /* Block device */
     95 #endif
     96 #if !defined(S_IFLNK)
     97 #   define S_IFLNK   0                          /* Link */
     98 #endif
     99 #if !defined(S_IFSOCK)
    100 #   define S_IFSOCK  0                          /* Socket */
    101 #endif
    102 
    103 #if defined(_MSC_VER)
    104 #   define S_IRUSR  S_IREAD                     /* Read user */
    105 #   define S_IWUSR  S_IWRITE                    /* Write user */
    106 #   define S_IXUSR  0                           /* Execute user */
    107 #   define S_IRGRP  0                           /* Read group */
    108 #   define S_IWGRP  0                           /* Write group */
    109 #   define S_IXGRP  0                           /* Execute group */
    110 #   define S_IROTH  0                           /* Read others */
    111 #   define S_IWOTH  0                           /* Write others */
    112 #   define S_IXOTH  0                           /* Execute others */
    113 #endif
    114 
    115 /* Maximum length of file name */
    116 #if !defined(PATH_MAX)
    117 #   define PATH_MAX MAX_PATH
    118 #endif
    119 #if !defined(FILENAME_MAX)
    120 #   define FILENAME_MAX MAX_PATH
    121 #endif
    122 #if !defined(NAME_MAX)
    123 #   define NAME_MAX FILENAME_MAX
    124 #endif
    125 
    126 /* File type flags for d_type */
    127 #define DT_UNKNOWN  0
    128 #define DT_REG      S_IFREG
    129 #define DT_DIR      S_IFDIR
    130 #define DT_FIFO     S_IFIFO
    131 #define DT_SOCK     S_IFSOCK
    132 #define DT_CHR      S_IFCHR
    133 #define DT_BLK      S_IFBLK
    134 #define DT_LNK      S_IFLNK
    135 
    136 /* Macros for converting between st_mode and d_type */
    137 #define IFTODT(mode) ((mode) & S_IFMT)
    138 #define DTTOIF(type) (type)
    139 
    140 /*
    141  * File type macros.  Note that block devices, sockets and links cannot be
    142  * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
    143  * only defined for compatibility.  These macros should always return false
    144  * on Windows.
    145  */
    146 #define    S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
    147 #define    S_ISDIR(mode)  (((mode) & S_IFMT) == S_IFDIR)
    148 #define    S_ISREG(mode)  (((mode) & S_IFMT) == S_IFREG)
    149 #define    S_ISLNK(mode)  (((mode) & S_IFMT) == S_IFLNK)
    150 #define    S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
    151 #define    S_ISCHR(mode)  (((mode) & S_IFMT) == S_IFCHR)
    152 #define    S_ISBLK(mode)  (((mode) & S_IFMT) == S_IFBLK)
    153 
    154 /* Return the exact length of d_namlen without zero terminator */
    155 #define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
    156 
    157 /* Return number of bytes needed to store d_namlen */
    158 #define _D_ALLOC_NAMLEN(p) (PATH_MAX)
    159 
    160 
    161 #ifdef __cplusplus
    162 extern "C" {
    163 #endif
    164 
    165 
    166 /* Wide-character version */
    167 struct _wdirent {
    168     long d_ino;                                 /* Always zero */
    169     unsigned short d_reclen;                    /* Structure size */
    170     size_t d_namlen;                            /* Length of name without  */
    171     int d_type;                                 /* File type */
    172     wchar_t d_name[PATH_MAX];                   /* File name */
    173 };
    174 typedef struct _wdirent _wdirent;
    175 
    176 struct _WDIR {
    177     struct _wdirent ent;                        /* Current directory entry */
    178     WIN32_FIND_DATAW data;                      /* Private file data */
    179     int cached;                                 /* True if data is valid */
    180     HANDLE handle;                              /* Win32 search handle */
    181     wchar_t *patt;                              /* Initial directory name */
    182 };
    183 typedef struct _WDIR _WDIR;
    184 
    185 static _WDIR *_wopendir (const wchar_t *dirname);
    186 static struct _wdirent *_wreaddir (_WDIR *dirp);
    187 static int _wclosedir (_WDIR *dirp);
    188 static void _wrewinddir (_WDIR* dirp);
    189 
    190 
    191 /* For compatibility with Symbian */
    192 #define wdirent _wdirent
    193 #define WDIR _WDIR
    194 #define wopendir _wopendir
    195 #define wreaddir _wreaddir
    196 #define wclosedir _wclosedir
    197 #define wrewinddir _wrewinddir
    198 
    199 
    200 /* Multi-byte character versions */
    201 struct dirent {
    202     long d_ino;                                 /* Always zero */
    203     unsigned short d_reclen;                    /* Structure size */
    204     size_t d_namlen;                            /* Length of name without  */
    205     int d_type;                                 /* File type */
    206     char d_name[PATH_MAX];                      /* File name */
    207 };
    208 typedef struct dirent dirent;
    209 
    210 struct DIR {
    211     struct dirent ent;
    212     struct _WDIR *wdirp;
    213 };
    214 typedef struct DIR DIR;
    215 
    216 static DIR *opendir (const char *dirname);
    217 static struct dirent *readdir (DIR *dirp);
    218 static int closedir (DIR *dirp);
    219 static void rewinddir (DIR* dirp);
    220 
    221 
    222 /* Internal utility functions */
    223 static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp);
    224 static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp);
    225 
    226 static int dirent_mbstowcs_s(
    227     size_t *pReturnValue,
    228     wchar_t *wcstr,
    229     size_t sizeInWords,
    230     const char *mbstr,
    231     size_t count);
    232 
    233 static int dirent_wcstombs_s(
    234     size_t *pReturnValue,
    235     char *mbstr,
    236     size_t sizeInBytes,
    237     const wchar_t *wcstr,
    238     size_t count);
    239 
    240 static void dirent_set_errno (int error);
    241 
    242 /*
    243  * Open directory stream DIRNAME for read and return a pointer to the
    244  * internal working area that is used to retrieve individual directory
    245  * entries.
    246  */
    247 static _WDIR*
    248 _wopendir(
    249     const wchar_t *dirname)
    250 {
    251     _WDIR *dirp = NULL;
    252     int error;
    253 
    254     /* Must have directory name */
    255     if (dirname == NULL  ||  dirname[0] == '') {
    256         dirent_set_errno (ENOENT);
    257         return NULL;
    258     }
    259 
    260     /* Allocate new _WDIR structure */
    261     dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
    262     if (dirp != NULL) {
    263         DWORD n;
    264 
    265         /* Reset _WDIR structure */
    266         dirp->handle = INVALID_HANDLE_VALUE;
    267         dirp->patt = NULL;
    268         dirp->cached = 0;
    269 
    270         /* Compute the length of full path plus zero terminator */
    271         n = GetFullPathNameW (dirname, 0, NULL, NULL);
    272 
    273         /* Allocate room for absolute directory name and search pattern */
    274         dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
    275         if (dirp->patt) {
    276 
    277             /*
    278              * Convert relative directory name to an absolute one.  This
    279              * allows rewinddir() to function correctly even when current
    280              * working directory is changed between opendir() and rewinddir().
    281              */
    282             n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
    283             if (n > 0) {
    284                 wchar_t *p;
    285 
    286                 /* Append search pattern * to the directory name */
    287                 p = dirp->patt + n;
    288                 if (dirp->patt < p) {
    289                     switch (p[-1]) {
    290                     case '\':
    291                     case '/':
    292                     case ':':
    293                         /* Directory ends in path separator, e.g. c:	emp */
    294                         /*NOP*/;
    295                         break;
    296 
    297                     default:
    298                         /* Directory name doesn't end in path separator */
    299                         *p++ = '\';
    300                     }
    301                 }
    302                 *p++ = '*';
    303                 *p = '';
    304 
    305                 /* Open directory stream and retrieve the first entry */
    306                 if (dirent_first (dirp)) {
    307                     /* Directory stream opened successfully */
    308                     error = 0;
    309                 } else {
    310                     /* Cannot retrieve first entry */
    311                     error = 1;
    312                     dirent_set_errno (ENOENT);
    313                 }
    314 
    315             } else {
    316                 /* Cannot retrieve full path name */
    317                 dirent_set_errno (ENOENT);
    318                 error = 1;
    319             }
    320 
    321         } else {
    322             /* Cannot allocate memory for search pattern */
    323             error = 1;
    324         }
    325 
    326     } else {
    327         /* Cannot allocate _WDIR structure */
    328         error = 1;
    329     }
    330 
    331     /* Clean up in case of error */
    332     if (error  &&  dirp) {
    333         _wclosedir (dirp);
    334         dirp = NULL;
    335     }
    336 
    337     return dirp;
    338 }
    339 
    340 /*
    341  * Read next directory entry.  The directory entry is returned in dirent
    342  * structure in the d_name field.  Individual directory entries returned by
    343  * this function include regular files, sub-directories, pseudo-directories
    344  * "." and ".." as well as volume labels, hidden files and system files.
    345  */
    346 static struct _wdirent*
    347 _wreaddir(
    348     _WDIR *dirp)
    349 {
    350     WIN32_FIND_DATAW *datap;
    351     struct _wdirent *entp;
    352 
    353     /* Read next directory entry */
    354     datap = dirent_next (dirp);
    355     if (datap) {
    356         size_t n;
    357         DWORD attr;
    358         
    359         /* Pointer to directory entry to return */
    360         entp = &dirp->ent;
    361 
    362         /* 
    363          * Copy file name as wide-character string.  If the file name is too
    364          * long to fit in to the destination buffer, then truncate file name
    365          * to PATH_MAX characters and zero-terminate the buffer.
    366          */
    367         n = 0;
    368         while (n + 1 < PATH_MAX  &&  datap->cFileName[n] != 0) {
    369             entp->d_name[n] = datap->cFileName[n];
    370             n++;
    371         }
    372         dirp->ent.d_name[n] = 0;
    373 
    374         /* Length of file name excluding zero terminator */
    375         entp->d_namlen = n;
    376 
    377         /* File type */
    378         attr = datap->dwFileAttributes;
    379         if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
    380             entp->d_type = DT_CHR;
    381         } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
    382             entp->d_type = DT_DIR;
    383         } else {
    384             entp->d_type = DT_REG;
    385         }
    386 
    387         /* Reset dummy fields */
    388         entp->d_ino = 0;
    389         entp->d_reclen = sizeof (struct _wdirent);
    390 
    391     } else {
    392 
    393         /* Last directory entry read */
    394         entp = NULL;
    395 
    396     }
    397 
    398     return entp;
    399 }
    400 
    401 /*
    402  * Close directory stream opened by opendir() function.  This invalidates the
    403  * DIR structure as well as any directory entry read previously by
    404  * _wreaddir().
    405  */
    406 static int
    407 _wclosedir(
    408     _WDIR *dirp)
    409 {
    410     int ok;
    411     if (dirp) {
    412 
    413         /* Release search handle */
    414         if (dirp->handle != INVALID_HANDLE_VALUE) {
    415             FindClose (dirp->handle);
    416             dirp->handle = INVALID_HANDLE_VALUE;
    417         }
    418 
    419         /* Release search pattern */
    420         if (dirp->patt) {
    421             free (dirp->patt);
    422             dirp->patt = NULL;
    423         }
    424 
    425         /* Release directory structure */
    426         free (dirp);
    427         ok = /*success*/0;
    428 
    429     } else {
    430         /* Invalid directory stream */
    431         dirent_set_errno (EBADF);
    432         ok = /*failure*/-1;
    433     }
    434     return ok;
    435 }
    436 
    437 /*
    438  * Rewind directory stream such that _wreaddir() returns the very first
    439  * file name again.
    440  */
    441 static void
    442 _wrewinddir(
    443     _WDIR* dirp)
    444 {
    445     if (dirp) {
    446         /* Release existing search handle */
    447         if (dirp->handle != INVALID_HANDLE_VALUE) {
    448             FindClose (dirp->handle);
    449         }
    450 
    451         /* Open new search handle */
    452         dirent_first (dirp);
    453     }
    454 }
    455 
    456 /* Get first directory entry (internal) */
    457 static WIN32_FIND_DATAW*
    458 dirent_first(
    459     _WDIR *dirp)
    460 {
    461     WIN32_FIND_DATAW *datap;
    462 
    463     /* Open directory and retrieve the first entry */
    464     dirp->handle = FindFirstFileW (dirp->patt, &dirp->data);
    465     if (dirp->handle != INVALID_HANDLE_VALUE) {
    466 
    467         /* a directory entry is now waiting in memory */
    468         datap = &dirp->data;
    469         dirp->cached = 1;
    470 
    471     } else {
    472 
    473         /* Failed to re-open directory: no directory entry in memory */
    474         dirp->cached = 0;
    475         datap = NULL;
    476 
    477     }
    478     return datap;
    479 }
    480 
    481 /* Get next directory entry (internal) */
    482 static WIN32_FIND_DATAW*
    483 dirent_next(
    484     _WDIR *dirp)
    485 {
    486     WIN32_FIND_DATAW *p;
    487 
    488     /* Get next directory entry */
    489     if (dirp->cached != 0) {
    490 
    491         /* A valid directory entry already in memory */
    492         p = &dirp->data;
    493         dirp->cached = 0;
    494 
    495     } else if (dirp->handle != INVALID_HANDLE_VALUE) {
    496 
    497         /* Get the next directory entry from stream */
    498         if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) {
    499             /* Got a file */
    500             p = &dirp->data;
    501         } else {
    502             /* The very last entry has been processed or an error occured */
    503             FindClose (dirp->handle);
    504             dirp->handle = INVALID_HANDLE_VALUE;
    505             p = NULL;
    506         }
    507 
    508     } else {
    509 
    510         /* End of directory stream reached */
    511         p = NULL;
    512 
    513     }
    514 
    515     return p;
    516 }
    517 
    518 /* 
    519  * Open directory stream using plain old C-string.
    520  */
    521 static DIR*
    522 opendir(
    523     const char *dirname) 
    524 {
    525     struct DIR *dirp;
    526     int error;
    527 
    528     /* Must have directory name */
    529     if (dirname == NULL  ||  dirname[0] == '') {
    530         dirent_set_errno (ENOENT);
    531         return NULL;
    532     }
    533 
    534     /* Allocate memory for DIR structure */
    535     dirp = (DIR*) malloc (sizeof (struct DIR));
    536     if (dirp) {
    537         wchar_t wname[PATH_MAX];
    538         size_t n;
    539 
    540         /* Convert directory name to wide-character string */
    541         error = dirent_mbstowcs_s (&n, wname, PATH_MAX, dirname, PATH_MAX);
    542         if (!error) {
    543 
    544             /* Open directory stream using wide-character name */
    545             dirp->wdirp = _wopendir (wname);
    546             if (dirp->wdirp) {
    547                 /* Directory stream opened */
    548                 error = 0;
    549             } else {
    550                 /* Failed to open directory stream */
    551                 error = 1;
    552             }
    553 
    554         } else {
    555             /* 
    556              * Cannot convert file name to wide-character string.  This
    557              * occurs if the string contains invalid multi-byte sequences or
    558              * the output buffer is too small to contain the resulting
    559              * string.
    560              */
    561             error = 1;
    562         }
    563 
    564     } else {
    565         /* Cannot allocate DIR structure */
    566         error = 1;
    567     }
    568 
    569     /* Clean up in case of error */
    570     if (error  &&  dirp) {
    571         free (dirp);
    572         dirp = NULL;
    573     }
    574 
    575     return dirp;
    576 }
    577 
    578 /*
    579  * Read next directory entry.
    580  *
    581  * When working with text consoles, please note that file names returned by
    582  * readdir() are represented in the default ANSI code page while any output to
    583  * console is typically formatted on another code page.  Thus, non-ASCII
    584  * characters in file names will not usually display correctly on console.  The
    585  * problem can be fixed in two ways: (1) change the character set of console
    586  * to 1252 using chcp utility and use Lucida Console font, or (2) use
    587  * _cprintf function when writing to console.  The _cprinf() will re-encode
    588  * ANSI strings to the console code page so many non-ASCII characters will
    589  * display correcly.
    590  */
    591 static struct dirent*
    592 readdir(
    593     DIR *dirp) 
    594 {
    595     WIN32_FIND_DATAW *datap;
    596     struct dirent *entp;
    597 
    598     /* Read next directory entry */
    599     datap = dirent_next (dirp->wdirp);
    600     if (datap) {
    601         size_t n;
    602         int error;
    603 
    604         /* Attempt to convert file name to multi-byte string */
    605         error = dirent_wcstombs_s(
    606             &n, dirp->ent.d_name, PATH_MAX, datap->cFileName, PATH_MAX);
    607 
    608         /* 
    609          * If the file name cannot be represented by a multi-byte string,
    610          * then attempt to use old 8+3 file name.  This allows traditional
    611          * Unix-code to access some file names despite of unicode
    612          * characters, although file names may seem unfamiliar to the user.
    613          *
    614          * Be ware that the code below cannot come up with a short file
    615          * name unless the file system provides one.  At least
    616          * VirtualBox shared folders fail to do this.
    617          */
    618         if (error  &&  datap->cAlternateFileName[0] != '') {
    619             error = dirent_wcstombs_s(
    620                 &n, dirp->ent.d_name, PATH_MAX, 
    621                 datap->cAlternateFileName, PATH_MAX);
    622         }
    623 
    624         if (!error) {
    625             DWORD attr;
    626 
    627             /* Initialize directory entry for return */
    628             entp = &dirp->ent;
    629 
    630             /* Length of file name excluding zero terminator */
    631             entp->d_namlen = n - 1;
    632 
    633             /* File attributes */
    634             attr = datap->dwFileAttributes;
    635             if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
    636                 entp->d_type = DT_CHR;
    637             } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
    638                 entp->d_type = DT_DIR;
    639             } else {
    640                 entp->d_type = DT_REG;
    641             }
    642 
    643             /* Reset dummy fields */
    644             entp->d_ino = 0;
    645             entp->d_reclen = sizeof (struct dirent);
    646 
    647         } else {
    648             /* 
    649              * Cannot convert file name to multi-byte string so construct
    650              * an errornous directory entry and return that.  Note that
    651              * we cannot return NULL as that would stop the processing
    652              * of directory entries completely.
    653              */
    654             entp = &dirp->ent;
    655             entp->d_name[0] = '?';
    656             entp->d_name[1] = '';
    657             entp->d_namlen = 1;
    658             entp->d_type = DT_UNKNOWN;
    659             entp->d_ino = 0;
    660             entp->d_reclen = 0;
    661         }
    662 
    663     } else {
    664         /* No more directory entries */
    665         entp = NULL;
    666     }
    667 
    668     return entp;
    669 }
    670 
    671 /*
    672  * Close directory stream.
    673  */
    674 static int
    675 closedir(
    676     DIR *dirp) 
    677 {
    678     int ok;
    679     if (dirp) {
    680 
    681         /* Close wide-character directory stream */
    682         ok = _wclosedir (dirp->wdirp);
    683         dirp->wdirp = NULL;
    684 
    685         /* Release multi-byte character version */
    686         free (dirp);
    687 
    688     } else {
    689 
    690         /* Invalid directory stream */
    691         dirent_set_errno (EBADF);
    692         ok = /*failure*/-1;
    693 
    694     }
    695     return ok;
    696 }
    697 
    698 /*
    699  * Rewind directory stream to beginning.
    700  */
    701 static void
    702 rewinddir(
    703     DIR* dirp) 
    704 {
    705     /* Rewind wide-character string directory stream */
    706     _wrewinddir (dirp->wdirp);
    707 }
    708 
    709 /* Convert multi-byte string to wide character string */
    710 static int
    711 dirent_mbstowcs_s(
    712     size_t *pReturnValue,
    713     wchar_t *wcstr,
    714     size_t sizeInWords,
    715     const char *mbstr,
    716     size_t count)
    717 {
    718     int error;
    719 
    720 #if defined(_MSC_VER)  &&  _MSC_VER >= 1400
    721 
    722     /* Microsoft Visual Studio 2005 or later */
    723     error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);
    724 
    725 #else
    726 
    727     /* Older Visual Studio or non-Microsoft compiler */
    728     size_t n;
    729 
    730     /* Convert to wide-character string (or count characters) */
    731     n = mbstowcs (wcstr, mbstr, sizeInWords);
    732     if (!wcstr  ||  n < count) {
    733 
    734         /* Zero-terminate output buffer */
    735         if (wcstr  &&  sizeInWords) {
    736             if (n >= sizeInWords) {
    737                 n = sizeInWords - 1;
    738             }
    739             wcstr[n] = 0;
    740         }
    741 
    742         /* Length of resuting multi-byte string WITH zero terminator */
    743         if (pReturnValue) {
    744             *pReturnValue = n + 1;
    745         }
    746 
    747         /* Success */
    748         error = 0;
    749 
    750     } else {
    751 
    752         /* Could not convert string */
    753         error = 1;
    754 
    755     }
    756 
    757 #endif
    758 
    759     return error;
    760 }
    761 
    762 /* Convert wide-character string to multi-byte string */
    763 static int
    764 dirent_wcstombs_s(
    765     size_t *pReturnValue,
    766     char *mbstr,
    767     size_t sizeInBytes, /* max size of mbstr */
    768     const wchar_t *wcstr,
    769     size_t count)
    770 {
    771     int error;
    772 
    773 #if defined(_MSC_VER)  &&  _MSC_VER >= 1400
    774 
    775     /* Microsoft Visual Studio 2005 or later */
    776     error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);
    777 
    778 #else
    779 
    780     /* Older Visual Studio or non-Microsoft compiler */
    781     size_t n;
    782 
    783     /* Convert to multi-byte string (or count the number of bytes needed) */
    784     n = wcstombs (mbstr, wcstr, sizeInBytes);
    785     if (!mbstr  ||  n < count) {
    786 
    787         /* Zero-terminate output buffer */
    788         if (mbstr  &&  sizeInBytes) {
    789             if (n >= sizeInBytes) {
    790                 n = sizeInBytes - 1;
    791             }
    792             mbstr[n] = '';
    793         }
    794 
    795         /* Lenght of resulting multi-bytes string WITH zero-terminator */
    796         if (pReturnValue) {
    797             *pReturnValue = n + 1;
    798         }
    799 
    800         /* Success */
    801         error = 0;
    802 
    803     } else {
    804 
    805         /* Cannot convert string */
    806         error = 1;
    807 
    808     }
    809 
    810 #endif
    811 
    812     return error;
    813 }
    814 
    815 /* Set errno variable */
    816 static void
    817 dirent_set_errno(
    818     int error)
    819 {
    820 #if defined(_MSC_VER)  &&  _MSC_VER >= 1400
    821 
    822     /* Microsoft Visual Studio 2005 and later */
    823     _set_errno (error);
    824 
    825 #else
    826 
    827     /* Non-Microsoft compiler or older Microsoft compiler */
    828     errno = error;
    829 
    830 #endif
    831 }
    832 
    833 
    834 #ifdef __cplusplus
    835 }
    836 #endif
    837 #endif /*DIRENT_H*/
    头文件代码

    头文件请参考我的另外一篇博客:

    http://www.cnblogs.com/matthew-2013/p/4676112.html

  • 相关阅读:
    [VirtaulBox]网络连接设置
    LeetCode
    LeetCode
    LeetCode
    LeetCode-37.Sudok Solver
    LeetCode-36.Valid Sudoku
    LeetCode-52.N-Queen II
    LeetCode-51.N-Queens
    LeetCode-22.Generate Parentheses
    LeetCode-111.Mininum Depth of Binary Tree
  • 原文地址:https://www.cnblogs.com/matthew-2013/p/4680188.html
Copyright © 2020-2023  润新知