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

原文地址:https://www.cnblogs.com/matthew-2013/p/4680188.html