1 /***************************************************************************
2     begin       : Sun Nov 23 2003
3     copyright   : (C) 2019 by Martin Preuss
4     email       : martin@libchipcard.de
5 
6  ***************************************************************************
7  *                                                                         *
8  *   This library is free software; you can redistribute it and/or         *
9  *   modify it under the terms of the GNU Lesser General Public            *
10  *   License as published by the Free Software Foundation; either          *
11  *   version 2.1 of the License, or (at your option) any later version.    *
12  *                                                                         *
13  *   This library is distributed in the hope that it will be useful,       *
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
16  *   Lesser General Public License for more details.                       *
17  *                                                                         *
18  *   You should have received a copy of the GNU Lesser General Public      *
19  *   License along with this library; if not, write to the Free Software   *
20  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
21  *   MA  02111-1307  USA                                                   *
22  *                                                                         *
23  ***************************************************************************/
24 
25 
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29 
30 
31 #include <gwenhywfar/directory.h>
32 #include <gwenhywfar/debug.h>
33 #include <gwenhywfar/path.h>
34 #include <gwenhywfar/buffer.h>
35 #include <gwenhywfar/text.h>
36 
37 #ifdef HAVE_UNISTD_H
38 # include <unistd.h>
39 #endif
40 #ifdef HAVE_SYS_STAT_H
41 # include <sys/stat.h>
42 #endif
43 #include <sys/types.h>
44 #ifdef HAVE_FCNTL_H
45 # include <fcntl.h>
46 #endif
47 #include <string.h>
48 #include <errno.h>
49 #include <assert.h>
50 #include <stdlib.h>
51 #include <ctype.h>
52 
53 #ifdef OS_WIN32
54 # define DIRSEP "\\"
55 #else
56 # define DIRSEP "/"
57 #endif
58 
59 #define DISABLE_DEBUGLOG
60 
61 
62 
63 /* ------------------------------------------------------------------------------------------------
64  * forward declarations
65  * ------------------------------------------------------------------------------------------------
66  */
67 
68 
69 static void *GWEN_Directory_HandlePathElement(const char *entry, void *data, unsigned int flags);
70 
71 
72 
73 /* ------------------------------------------------------------------------------------------------
74  * implementations
75  * ------------------------------------------------------------------------------------------------
76  */
77 
78 
79 
GWEN_Directory_HandlePathElement(const char * entry,void * data,unsigned int flags)80 void *GWEN_Directory_HandlePathElement(const char *entry,
81                                        void *data,
82                                        unsigned int flags)
83 {
84   char *p;
85   struct stat st;
86   int exists;
87   int withDrive;
88   GWEN_BUFFER *buf;
89   GWEN_BUFFER *ebuf = 0;
90 
91   withDrive=0;
92 
93 #ifdef OS_WIN32
94   if (entry && isalpha(*entry)) {
95     int len;
96 
97     /* append backslash if entry only consists of a drive specification */
98     len=strlen(entry);
99     if ((len==2) && (entry[1] == ':')) {
100       ebuf=GWEN_Buffer_new(0, len+2, 0, 1);
101       GWEN_Buffer_AppendString(ebuf, entry);
102       GWEN_Buffer_AppendByte(ebuf, '\\');
103       withDrive=1;
104       entry=GWEN_Buffer_GetStart(ebuf);
105     }
106   }
107 #endif /* OS_WIN32 */
108 
109   if (strcasecmp(entry, "..")==0) {
110     DBG_ERROR(GWEN_LOGDOMAIN, "\"..\" detected");
111     GWEN_Buffer_free(ebuf);
112     return 0;
113   }
114 
115   buf=(GWEN_BUFFER *)data;
116   if (GWEN_Buffer_GetUsedBytes(buf) && !withDrive) {
117     char c;
118 
119     c=GWEN_Buffer_GetStart(buf)[GWEN_Buffer_GetUsedBytes(buf)-1];
120 #ifdef OS_WIN32
121     if (c!='\\')
122       GWEN_Buffer_AppendByte(buf, '\\');
123 #else
124     if (c!='/')
125       GWEN_Buffer_AppendByte(buf, '/');
126 #endif /* OS_WIN32 */
127   }
128   GWEN_Buffer_AppendString(buf, entry);
129 
130   /* check for existence of the file/folder */
131   p=GWEN_Buffer_GetStart(buf);
132   DBG_VERBOUS(GWEN_LOGDOMAIN, "Checking path \"%s\"", p);
133   if (stat(p, &st)) {
134     exists=0;
135     DBG_DEBUG(GWEN_LOGDOMAIN, "stat: %s (%s)", strerror(errno), p);
136     if ((flags & GWEN_PATH_FLAGS_PATHMUSTEXIST) ||
137         ((flags & GWEN_PATH_FLAGS_LAST) &&
138          (flags & GWEN_PATH_FLAGS_NAMEMUSTEXIST))) {
139       DBG_INFO(GWEN_LOGDOMAIN, "Path \"%s\" does not exist (it should)", p);
140       GWEN_Buffer_free(ebuf);
141       return 0;
142     }
143   }
144   else {
145     DBG_VERBOUS(GWEN_LOGDOMAIN, "Checking for type");
146     exists=1;
147     if (flags & GWEN_PATH_FLAGS_VARIABLE) {
148       if (!S_ISREG(st.st_mode)) {
149         DBG_INFO(GWEN_LOGDOMAIN, "%s not a regular file", p);
150         GWEN_Buffer_free(ebuf);
151         return 0;
152       }
153     }
154     else {
155       if (!S_ISDIR(st.st_mode)) {
156         DBG_INFO(GWEN_LOGDOMAIN, "%s not a direcory", p);
157         GWEN_Buffer_free(ebuf);
158         return 0;
159       }
160     }
161     if ((flags & GWEN_PATH_FLAGS_PATHMUSTNOTEXIST) ||
162         ((flags & GWEN_PATH_FLAGS_LAST) &&
163          (flags & GWEN_PATH_FLAGS_NAMEMUSTNOTEXIST))) {
164       DBG_INFO(GWEN_LOGDOMAIN, "Path \"%s\" exists (it should not)", p);
165       GWEN_Buffer_free(ebuf);
166       return 0;
167     }
168   } /* if stat is ok */
169 
170   if (!exists) {
171     int isPublic;
172 
173     DBG_DEBUG(GWEN_LOGDOMAIN, "Entry \"%s\" does not exist", p);
174 
175     isPublic=(
176                ((flags & GWEN_PATH_FLAGS_LAST) &&
177                 (flags & GWEN_DIR_FLAGS_PUBLIC_NAME)) ||
178                (!(flags & GWEN_PATH_FLAGS_LAST) &&
179                 (flags & GWEN_DIR_FLAGS_PUBLIC_PATH))
180              );
181 
182     if (flags & GWEN_PATH_FLAGS_VARIABLE) {
183       /* create file */
184       int fd;
185 
186       DBG_DEBUG(GWEN_LOGDOMAIN, "Creating file \"%s\"", p);
187       if (isPublic)
188         fd=open(p, O_RDWR | O_CREAT | O_TRUNC,
189                 S_IRUSR | S_IWUSR
190 #ifdef S_IRGRP
191                 | S_IRGRP
192 #endif
193 #ifdef S_IROTH
194                 | S_IROTH
195 #endif
196                );
197       else
198         fd=open(p, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
199       if (fd==-1) {
200         DBG_ERROR(GWEN_LOGDOMAIN, "open: %s (%s)", strerror(errno), p);
201         GWEN_Buffer_free(ebuf);
202         return 0;
203       }
204       close(fd);
205       DBG_VERBOUS(GWEN_LOGDOMAIN, "Successfully created");
206     }
207     else {
208       /* create dir */
209       DBG_VERBOUS(GWEN_LOGDOMAIN, "Creating folder \"%s\"", p);
210 
211       if (isPublic) {
212         if (GWEN_Directory_CreatePublic(p)) {
213           DBG_ERROR(GWEN_LOGDOMAIN, "Could not create directory \"%s\"", p);
214           GWEN_Buffer_free(ebuf);
215           return 0;
216         }
217       }
218       else {
219         if (GWEN_Directory_Create(p)) {
220           DBG_ERROR(GWEN_LOGDOMAIN, "Could not create directory \"%s\"", p);
221           GWEN_Buffer_free(ebuf);
222           return 0;
223         }
224       }
225     }
226   } /* if exists */
227   else {
228     DBG_VERBOUS(GWEN_LOGDOMAIN, "Entry \"%s\" exists", p);
229   }
230   DBG_VERBOUS(GWEN_LOGDOMAIN, "Returning this: %s", p);
231   GWEN_Buffer_free(ebuf);
232   return buf;
233 }
234 
235 
236 
GWEN_Directory_GetPath(const char * path,unsigned int flags)237 int GWEN_Directory_GetPath(const char *path,
238                            unsigned int flags)
239 {
240   GWEN_BUFFER *buf;
241   void *p;
242 
243   assert(path);
244   buf=GWEN_Buffer_new(0, strlen(path)+10, 0, 1);
245   p=GWEN_Path_Handle(path, buf,
246                      flags | GWEN_PATH_FLAGS_CHECKROOT,
247                      GWEN_Directory_HandlePathElement);
248   if (!p) {
249     DBG_INFO(GWEN_LOGDOMAIN, "Path so far: \"%s\"", GWEN_Buffer_GetStart(buf));
250     GWEN_Buffer_free(buf);
251     return -1;
252   }
253   GWEN_Buffer_free(buf);
254   return 0;
255 }
256 
257 
258 
GWEN_Directory_OsifyPath(const char * path,GWEN_BUFFER * pbuf,GWEN_UNUSED int transformDriveElement)259 int GWEN_Directory_OsifyPath(const char *path, GWEN_BUFFER *pbuf,
260 #ifndef OS_WIN32
261                              GWEN_UNUSED
262 #endif
263                              int transformDriveElement)
264 {
265   const char *p;
266 
267   p=path;
268 
269   /* handle drive letters (only check for normal slashes here) */
270 #ifdef OS_WIN32
271   if (transformDriveElement) {
272     if (*p=='/')
273       if (isalpha(p[1]))
274         if (p[2]=='/' || p[2]==0) {
275           GWEN_Buffer_AppendByte(pbuf, p[0]);
276           GWEN_Buffer_AppendByte(pbuf, ':');
277           p+=2;
278         }
279   }
280 #endif
281 
282   while (*p) {
283     if (*p=='/' || *p=='\\') {
284       while (*p=='/' || *p=='\\')
285         p++;
286 #ifdef OS_WIN32
287       GWEN_Buffer_AppendByte(pbuf, '\\');
288 #else
289       GWEN_Buffer_AppendByte(pbuf, '/');
290 #endif
291     }
292     else {
293       GWEN_Buffer_AppendByte(pbuf, *p);
294       p++;
295     }
296   }
297 
298   return 0;
299 }
300 
301 
302 
GWEN_Directory_FindFileInPaths(const GWEN_STRINGLIST * paths,const char * filePath,GWEN_BUFFER * fbuf)303 int GWEN_Directory_FindFileInPaths(const GWEN_STRINGLIST *paths,
304                                    const char *filePath,
305                                    GWEN_BUFFER *fbuf)
306 {
307   GWEN_STRINGLISTENTRY *se;
308 
309   se=GWEN_StringList_FirstEntry(paths);
310   while (se) {
311     GWEN_BUFFER *tbuf;
312     FILE *f;
313 
314     tbuf=GWEN_Buffer_new(0, 256, 0, 1);
315     GWEN_Buffer_AppendString(tbuf, GWEN_StringListEntry_Data(se));
316     GWEN_Buffer_AppendString(tbuf, DIRSEP);
317     GWEN_Buffer_AppendString(tbuf, filePath);
318     DBG_VERBOUS(GWEN_LOGDOMAIN, "Trying \"%s\"",
319                 GWEN_Buffer_GetStart(tbuf));
320     f=fopen(GWEN_Buffer_GetStart(tbuf), "r");
321     if (f) {
322       fclose(f);
323       DBG_DEBUG(GWEN_LOGDOMAIN,
324                 "File \"%s\" found in folder \"%s\"",
325                 filePath,
326                 GWEN_StringListEntry_Data(se));
327       GWEN_Buffer_AppendBuffer(fbuf, tbuf);
328       GWEN_Buffer_free(tbuf);
329       return 0;
330     }
331     GWEN_Buffer_free(tbuf);
332 
333     se=GWEN_StringListEntry_Next(se);
334   }
335 
336   DBG_INFO(GWEN_LOGDOMAIN, "File \"%s\" not found", filePath);
337   return GWEN_ERROR_NOT_FOUND;
338 }
339 
340 
341 
GWEN_Directory_FindPathForFile(const GWEN_STRINGLIST * paths,const char * filePath,GWEN_BUFFER * fbuf)342 int GWEN_Directory_FindPathForFile(const GWEN_STRINGLIST *paths,
343                                    const char *filePath,
344                                    GWEN_BUFFER *fbuf)
345 {
346   GWEN_STRINGLISTENTRY *se;
347 
348   se=GWEN_StringList_FirstEntry(paths);
349   while (se) {
350     GWEN_BUFFER *tbuf;
351     FILE *f;
352 
353     tbuf=GWEN_Buffer_new(0, 256, 0, 1);
354     GWEN_Buffer_AppendString(tbuf, GWEN_StringListEntry_Data(se));
355     GWEN_Buffer_AppendString(tbuf, DIRSEP);
356     GWEN_Buffer_AppendString(tbuf, filePath);
357     DBG_VERBOUS(GWEN_LOGDOMAIN, "Trying \"%s\"",
358                 GWEN_Buffer_GetStart(tbuf));
359     f=fopen(GWEN_Buffer_GetStart(tbuf), "r");
360     if (f) {
361       fclose(f);
362       DBG_INFO(GWEN_LOGDOMAIN,
363                "File \"%s\" found in folder \"%s\"",
364                filePath,
365                GWEN_StringListEntry_Data(se));
366       GWEN_Buffer_AppendString(fbuf, GWEN_StringListEntry_Data(se));
367       GWEN_Buffer_free(tbuf);
368       return 0;
369     }
370     GWEN_Buffer_free(tbuf);
371 
372     se=GWEN_StringListEntry_Next(se);
373   }
374 
375   DBG_INFO(GWEN_LOGDOMAIN, "File \"%s\" not found", filePath);
376   return GWEN_ERROR_NOT_FOUND;
377 }
378 
379 
380 
GWEN_Directory_GetTmpDirectory(char * buffer,unsigned int size)381 int GWEN_Directory_GetTmpDirectory(char *buffer, unsigned int size)
382 {
383   const char *tmp_dir;
384   assert(buffer);
385 
386   /* Copied from http://svn.gnome.org/viewcvs/glib/trunk/glib/gutils.c */
387   tmp_dir = getenv("TMPDIR");
388   if (!tmp_dir)
389     tmp_dir = getenv("TMP");
390   if (!tmp_dir)
391     tmp_dir = getenv("TEMP");
392 
393   if (!tmp_dir) {
394 #ifdef OS_WIN32
395     tmp_dir = "C:\\";
396 #else
397     tmp_dir = "/tmp";
398 #endif  /* !OS_WIN32 */
399   }
400 
401   strncpy(buffer, tmp_dir, size);
402   return 0;
403 }
404 
405 
406 
GWEN_Directory_GetAllEntries(const char * folder,GWEN_STRINGLIST * sl,const char * mask)407 int GWEN_Directory_GetAllEntries(const char *folder,
408                                  GWEN_STRINGLIST *sl,
409                                  const char *mask)
410 {
411   GWEN_DIRECTORY *d;
412   int rv;
413   char buffer[256];
414 
415   d=GWEN_Directory_new();
416   rv=GWEN_Directory_Open(d, folder);
417   if (rv<0) {
418     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
419     GWEN_Directory_free(d);
420     return rv;
421   }
422 
423   while (0==GWEN_Directory_Read(d, buffer, sizeof(buffer))) {
424     if (strcmp(buffer, ".")!=0 &&
425         strcmp(buffer, "..")!=0 &&
426         (mask==NULL ||
427          GWEN_Text_ComparePattern(buffer+1, mask, 0)!=-1))
428       GWEN_StringList_AppendString(sl, buffer, 0, 1);
429   }
430 
431   GWEN_Directory_Close(d);
432   GWEN_Directory_free(d);
433   return 0;
434 }
435 
436 
437 
GWEN_Directory_GetFileEntriesWithType(const char * folder,GWEN_STRINGLIST * sl,const char * mask)438 int GWEN_Directory_GetFileEntriesWithType(const char *folder,
439                                           GWEN_STRINGLIST *sl,
440                                           const char *mask)
441 {
442   GWEN_DIRECTORY *d;
443   int rv;
444   char buffer[256];
445   GWEN_BUFFER *pbuf;
446   uint32_t pos;
447 
448   d=GWEN_Directory_new();
449   rv=GWEN_Directory_Open(d, folder);
450   if (rv<0) {
451     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
452     GWEN_Directory_free(d);
453     return rv;
454   }
455 
456   pbuf=GWEN_Buffer_new(0, 256, 0, 1);
457   GWEN_Buffer_AppendString(pbuf, folder);
458   GWEN_Buffer_AppendString(pbuf, GWEN_DIR_SEPARATOR_S);
459   pos=GWEN_Buffer_GetPos(pbuf);
460 
461   while (0==GWEN_Directory_Read(d, buffer+1, sizeof(buffer)-2)) {
462     if (strcmp(buffer, ".")!=0 &&
463         strcmp(buffer, "..")!=0 &&
464         (mask==NULL ||
465          GWEN_Text_ComparePattern(buffer+1, mask, 0)!=-1)) {
466       struct stat st;
467 
468       GWEN_Buffer_AppendString(pbuf, buffer+1);
469       if (stat(GWEN_Buffer_GetStart(pbuf), &st)==0) {
470         if (S_ISREG(st.st_mode))
471           buffer[0]='f';
472         else if (S_ISDIR(st.st_mode))
473           buffer[0]='d';
474         else
475           buffer[0]='?';
476         GWEN_StringList_AppendString(sl, buffer, 0, 1);
477       }
478       GWEN_Buffer_Crop(pbuf, 0, pos);
479     }
480   }
481 
482   GWEN_Directory_Close(d);
483   GWEN_Directory_free(d);
484   return 0;
485 }
486 
487 
488 
489 
GWEN_Directory_GetFileEntries(const char * folder,GWEN_STRINGLIST * sl,const char * mask)490 int GWEN_Directory_GetFileEntries(const char *folder, GWEN_STRINGLIST *sl,
491                                   const char *mask)
492 {
493   GWEN_DIRECTORY *d;
494   int rv;
495   char buffer[256];
496   GWEN_BUFFER *pbuf;
497   uint32_t pos;
498 
499   d=GWEN_Directory_new();
500   rv=GWEN_Directory_Open(d, folder);
501   if (rv<0) {
502     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
503     GWEN_Directory_free(d);
504     return rv;
505   }
506 
507   pbuf=GWEN_Buffer_new(0, 256, 0, 1);
508   GWEN_Buffer_AppendString(pbuf, folder);
509   GWEN_Buffer_AppendString(pbuf, GWEN_DIR_SEPARATOR_S);
510   pos=GWEN_Buffer_GetPos(pbuf);
511 
512   while (0==GWEN_Directory_Read(d, buffer, sizeof(buffer))) {
513     if (strcmp(buffer, ".")!=0 &&
514         strcmp(buffer, "..")!=0 &&
515         (mask==NULL ||
516          GWEN_Text_ComparePattern(buffer+1, mask, 0)!=-1)) {
517       struct stat st;
518 
519       GWEN_Buffer_AppendString(pbuf, buffer);
520       if (stat(GWEN_Buffer_GetStart(pbuf), &st)==0) {
521         if (S_ISREG(st.st_mode))
522           GWEN_StringList_AppendString(sl, buffer, 0, 1);
523       }
524       GWEN_Buffer_Crop(pbuf, 0, pos);
525     }
526   }
527 
528   GWEN_Buffer_free(pbuf);
529   GWEN_Directory_Close(d);
530   GWEN_Directory_free(d);
531   return 0;
532 }
533 
534 
535 
GWEN_Directory_GetDirEntries(const char * folder,GWEN_STRINGLIST * sl,const char * mask)536 int GWEN_Directory_GetDirEntries(const char *folder, GWEN_STRINGLIST *sl,
537                                  const char *mask)
538 {
539   GWEN_DIRECTORY *d;
540   int rv;
541   char buffer[256];
542   GWEN_BUFFER *pbuf;
543   uint32_t pos;
544 
545   d=GWEN_Directory_new();
546   rv=GWEN_Directory_Open(d, folder);
547   if (rv<0) {
548     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
549     GWEN_Directory_free(d);
550     return rv;
551   }
552 
553   pbuf=GWEN_Buffer_new(0, 256, 0, 1);
554   GWEN_Buffer_AppendString(pbuf, folder);
555   GWEN_Buffer_AppendString(pbuf, GWEN_DIR_SEPARATOR_S);
556   pos=GWEN_Buffer_GetPos(pbuf);
557 
558   while (0==GWEN_Directory_Read(d, buffer, sizeof(buffer))) {
559     if (strcmp(buffer, ".")!=0 &&
560         strcmp(buffer, "..")!=0 &&
561         (mask==NULL ||
562          GWEN_Text_ComparePattern(buffer+1, mask, 0)!=-1)) {
563       struct stat st;
564 
565       GWEN_Buffer_AppendString(pbuf, buffer);
566       if (stat(GWEN_Buffer_GetStart(pbuf), &st)==0) {
567         if (S_ISDIR(st.st_mode))
568           GWEN_StringList_AppendString(sl, buffer, 0, 1);
569       }
570       GWEN_Buffer_Crop(pbuf, 0, pos);
571     }
572   }
573 
574   GWEN_Directory_Close(d);
575   GWEN_Directory_free(d);
576   return 0;
577 }
578 
579 
580 
GWEN_Directory_GetMatchingFilesRecursively(const char * folder,GWEN_STRINGLIST * sl,const char * mask)581 int GWEN_Directory_GetMatchingFilesRecursively(const char *folder,
582                                                GWEN_STRINGLIST *sl,
583                                                const char *mask)
584 {
585   GWEN_DIRECTORY *d;
586   int rv;
587   char buffer[256];
588   GWEN_BUFFER *pbuf;
589   uint32_t pos;
590   GWEN_STRINGLIST *folderList;
591 
592   folderList=GWEN_StringList_new();
593 
594   d=GWEN_Directory_new();
595   rv=GWEN_Directory_Open(d, folder);
596   if (rv<0) {
597     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
598     GWEN_Directory_free(d);
599     GWEN_StringList_free(folderList);
600     return rv;
601   }
602 
603   pbuf=GWEN_Buffer_new(0, 256, 0, 1);
604   GWEN_Buffer_AppendString(pbuf, folder);
605   GWEN_Buffer_AppendString(pbuf, GWEN_DIR_SEPARATOR_S);
606   pos=GWEN_Buffer_GetPos(pbuf);
607 
608   while (0==GWEN_Directory_Read(d, buffer, sizeof(buffer)-2)) {
609     if (strcmp(buffer, ".")!=0 &&
610         strcmp(buffer, "..")!=0) {
611       struct stat st;
612 
613       GWEN_Buffer_AppendString(pbuf, buffer);
614       if (stat(GWEN_Buffer_GetStart(pbuf), &st)==0) {
615         if (S_ISDIR(st.st_mode))
616           /* add folders to the folder list */
617           GWEN_StringList_AppendString(folderList, GWEN_Buffer_GetStart(pbuf), 0, 0);
618         else {
619           if (mask==NULL || GWEN_Text_ComparePattern(buffer, mask, 0)!=-1)
620             /* don't check for duplicates here (i.e. last param =0) */
621             GWEN_StringList_AppendString(sl, GWEN_Buffer_GetStart(pbuf), 0, 0);
622         }
623       }
624       GWEN_Buffer_Crop(pbuf, 0, pos);
625     }
626   }
627 
628   GWEN_Directory_Close(d);
629   GWEN_Directory_free(d);
630 
631   if (GWEN_StringList_Count(folderList)) {
632     GWEN_STRINGLISTENTRY *se;
633 
634     se=GWEN_StringList_FirstEntry(folderList);
635     while (se) {
636       const char *s;
637 
638       s=GWEN_StringListEntry_Data(se);
639       if (s && *s)
640         GWEN_Directory_GetMatchingFilesRecursively(s, sl, mask);
641       se=GWEN_StringListEntry_Next(se);
642     }
643   }
644   GWEN_StringList_free(folderList);
645   GWEN_Buffer_free(pbuf);
646 
647   return 0;
648 }
649 
650 
651 
GWEN_Directory_GetAbsoluteFolderPath(const char * folder,GWEN_BUFFER * tbuf)652 int GWEN_Directory_GetAbsoluteFolderPath(const char *folder, GWEN_BUFFER *tbuf)
653 {
654   char savedPwd[300];
655   char dataPwd[300];
656 
657   /* get current working dir */
658   if (getcwd(savedPwd, sizeof(savedPwd)-1)==NULL) {
659     DBG_ERROR(GWEN_LOGDOMAIN, "getcwd(): %s", strerror(errno));
660     return GWEN_ERROR_IO;
661   }
662 
663   if (chdir(folder)) {
664     DBG_ERROR(GWEN_LOGDOMAIN, "chdir(%s): %s", folder, strerror(errno));
665     return GWEN_ERROR_IO;
666   }
667 
668   /* get new current working dir */
669   if (getcwd(dataPwd, sizeof(dataPwd)-1)==NULL) {
670     DBG_ERROR(GWEN_LOGDOMAIN, "getcwd(): %s", strerror(errno));
671     return GWEN_ERROR_IO;
672   }
673   dataPwd[sizeof(dataPwd)-1]=0;
674 
675   /* change back to previous pwd */
676   if (chdir(savedPwd)) {
677     DBG_ERROR(GWEN_LOGDOMAIN, "chdir(%s): %s", folder, strerror(errno));
678     return GWEN_ERROR_IO;
679   }
680 
681   GWEN_Buffer_AppendString(tbuf, dataPwd);
682   return 0;
683 }
684 
685 
686 
687 
688 
689 
690