00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifdef HAVE_CONFIG_H
00030 # include <config.h>
00031 #endif
00032
00033
00034 #include <gwenhywfar/directory.h>
00035 #include <gwenhywfar/debug.h>
00036 #include <gwenhywfar/path.h>
00037 #include <gwenhywfar/buffer.h>
00038 #include <gwenhywfar/text.h>
00039
00040 #ifdef HAVE_UNISTD_H
00041 # include <unistd.h>
00042 #endif
00043 #ifdef HAVE_SYS_STAT_H
00044 # include <sys/stat.h>
00045 #endif
00046 #include <sys/types.h>
00047 #ifdef HAVE_FCNTL_H
00048 # include <fcntl.h>
00049 #endif
00050 #include <string.h>
00051 #include <errno.h>
00052 #include <assert.h>
00053 #include <stdlib.h>
00054 #include <ctype.h>
00055
00056 #ifdef OS_WIN32
00057 # define DIRSEP "\\"
00058 #else
00059 # define DIRSEP "/"
00060 #endif
00061
00062
00063
00064 void *GWEN_Directory_HandlePathElement(const char *entry,
00065 void *data,
00066 unsigned int flags){
00067 char *p;
00068 struct stat st;
00069 int exists;
00070 int withDrive;
00071 GWEN_BUFFER *buf;
00072 GWEN_BUFFER *ebuf = 0;
00073
00074 withDrive=0;
00075
00076 #ifdef OS_WIN32
00077 if (entry && isalpha(*entry)) {
00078 int len;
00079
00080
00081 len=strlen(entry);
00082 if ( (len==2) && (entry[1] == ':') ) {
00083 ebuf=GWEN_Buffer_new(0, len+2, 0, 1);
00084 GWEN_Buffer_AppendString(ebuf, entry);
00085 GWEN_Buffer_AppendByte(ebuf, '\\');
00086 withDrive=1;
00087 entry=GWEN_Buffer_GetStart(ebuf);
00088 }
00089 }
00090 #endif
00091
00092 if (strcasecmp(entry, "..")==0) {
00093 DBG_ERROR(GWEN_LOGDOMAIN, "\"..\" detected");
00094 GWEN_Buffer_free(ebuf);
00095 return 0;
00096 }
00097
00098 buf=(GWEN_BUFFER*)data;
00099 if (GWEN_Buffer_GetUsedBytes(buf) && !withDrive) {
00100 char c;
00101
00102 c=GWEN_Buffer_GetStart(buf)[GWEN_Buffer_GetUsedBytes(buf)-1];
00103 #ifdef OS_WIN32
00104 if (c!='\\')
00105 GWEN_Buffer_AppendByte(buf, '\\');
00106 #else
00107 if (c!='/')
00108 GWEN_Buffer_AppendByte(buf, '/');
00109 #endif
00110 }
00111 GWEN_Buffer_AppendString(buf, entry);
00112
00113
00114 p=GWEN_Buffer_GetStart(buf);
00115 DBG_DEBUG(GWEN_LOGDOMAIN, "Checking path \"%s\"", p);
00116 if (stat(p, &st)) {
00117 exists=0;
00118 DBG_DEBUG(GWEN_LOGDOMAIN, "stat: %s (%s)", strerror(errno), p);
00119 if ((flags & GWEN_PATH_FLAGS_PATHMUSTEXIST) ||
00120 ((flags & GWEN_PATH_FLAGS_LAST) &&
00121 (flags & GWEN_PATH_FLAGS_NAMEMUSTEXIST))) {
00122 DBG_INFO(GWEN_LOGDOMAIN, "Path \"%s\" does not exist (it should)", p);
00123 GWEN_Buffer_free(ebuf);
00124 return 0;
00125 }
00126 }
00127 else {
00128 DBG_DEBUG(GWEN_LOGDOMAIN, "Checking for type");
00129 exists=1;
00130 if (flags & GWEN_PATH_FLAGS_VARIABLE) {
00131 if (!S_ISREG(st.st_mode)) {
00132 DBG_INFO(GWEN_LOGDOMAIN, "%s not a regular file", p);
00133 GWEN_Buffer_free(ebuf);
00134 return 0;
00135 }
00136 }
00137 else {
00138 if (!S_ISDIR(st.st_mode)) {
00139 DBG_INFO(GWEN_LOGDOMAIN, "%s not a direcory", p);
00140 GWEN_Buffer_free(ebuf);
00141 return 0;
00142 }
00143 }
00144 if ((flags & GWEN_PATH_FLAGS_PATHMUSTNOTEXIST) ||
00145 ((flags & GWEN_PATH_FLAGS_LAST) &&
00146 (flags & GWEN_PATH_FLAGS_NAMEMUSTNOTEXIST))) {
00147 DBG_INFO(GWEN_LOGDOMAIN, "Path \"%s\" exists (it should not)", p);
00148 GWEN_Buffer_free(ebuf);
00149 return 0;
00150 }
00151 }
00152
00153 if (!exists) {
00154 int isPublic;
00155
00156 DBG_DEBUG(GWEN_LOGDOMAIN, "Entry \"%s\" does not exist", p);
00157
00158 isPublic=(
00159 ((flags & GWEN_PATH_FLAGS_LAST) &&
00160 (flags & GWEN_DIR_FLAGS_PUBLIC_NAME)) ||
00161 (!(flags & GWEN_PATH_FLAGS_LAST) &&
00162 (flags & GWEN_DIR_FLAGS_PUBLIC_PATH))
00163 );
00164
00165 if (flags & GWEN_PATH_FLAGS_VARIABLE) {
00166
00167 int fd;
00168
00169 DBG_DEBUG(GWEN_LOGDOMAIN, "Creating file \"%s\"", p);
00170 if (isPublic)
00171 fd=open(p, O_RDWR | O_CREAT | O_TRUNC,
00172 S_IRUSR | S_IWUSR
00173 #ifdef S_IRGRP
00174 | S_IRGRP
00175 #endif
00176 #ifdef S_IROTH
00177 | S_IROTH
00178 #endif
00179 );
00180 else
00181 fd=open(p, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
00182 if (fd==-1) {
00183 DBG_ERROR(GWEN_LOGDOMAIN, "open: %s (%s)", strerror(errno), p);
00184 GWEN_Buffer_free(ebuf);
00185 return 0;
00186 }
00187 close(fd);
00188 DBG_DEBUG(GWEN_LOGDOMAIN, "Sucessfully created");
00189 }
00190 else {
00191
00192 DBG_DEBUG(GWEN_LOGDOMAIN, "Creating folder \"%s\"", p);
00193
00194 if (isPublic) {
00195 if (GWEN_Directory_CreatePublic(p)) {
00196 DBG_ERROR(GWEN_LOGDOMAIN, "Could not create directory \"%s\"", p);
00197 GWEN_Buffer_free(ebuf);
00198 return 0;
00199 }
00200 }
00201 else {
00202 if (GWEN_Directory_Create(p)) {
00203 DBG_ERROR(GWEN_LOGDOMAIN, "Could not create directory \"%s\"", p);
00204 GWEN_Buffer_free(ebuf);
00205 return 0;
00206 }
00207 }
00208 }
00209 }
00210 else {
00211 DBG_DEBUG(GWEN_LOGDOMAIN, "Entry \"%s\" exists", p);
00212 }
00213 DBG_DEBUG(GWEN_LOGDOMAIN, "Returning this: %s", p);
00214 GWEN_Buffer_free(ebuf);
00215 return buf;
00216 }
00217
00218
00219
00220 int GWEN_Directory_GetPath(const char *path,
00221 unsigned int flags) {
00222 GWEN_BUFFER *buf;
00223 void *p;
00224
00225 assert(path);
00226 buf=GWEN_Buffer_new(0, strlen(path)+10, 0, 1);
00227 p=GWEN_Path_Handle(path, buf,
00228 flags | GWEN_PATH_FLAGS_CHECKROOT,
00229 GWEN_Directory_HandlePathElement);
00230 if (!p) {
00231 DBG_INFO(GWEN_LOGDOMAIN, "Path so far: \"%s\"", GWEN_Buffer_GetStart(buf));
00232 GWEN_Buffer_free(buf);
00233 return -1;
00234 }
00235 GWEN_Buffer_free(buf);
00236 return 0;
00237 }
00238
00239
00240
00241 int GWEN_Directory_OsifyPath(const char *path, GWEN_BUFFER *pbuf,
00242 int transformDriveElement){
00243 const char *p;
00244
00245 p=path;
00246
00247
00248 #ifdef OS_WIN32
00249 if (transformDriveElement) {
00250 if (*p=='/')
00251 if (isalpha(p[1]))
00252 if (p[2]=='/' || p[2]==0) {
00253 GWEN_Buffer_AppendByte(pbuf, p[0]);
00254 GWEN_Buffer_AppendByte(pbuf, ':');
00255 p+=2;
00256 }
00257 }
00258 #endif
00259
00260 while(*p) {
00261 if (*p=='/' || *p=='\\') {
00262 while (*p=='/' || *p=='\\')
00263 p++;
00264 #ifdef OS_WIN32
00265 GWEN_Buffer_AppendByte(pbuf, '\\');
00266 #else
00267 GWEN_Buffer_AppendByte(pbuf, '/');
00268 #endif
00269 }
00270 else {
00271 GWEN_Buffer_AppendByte(pbuf, *p);
00272 p++;
00273 }
00274 }
00275
00276 return 0;
00277 }
00278
00279
00280
00281 int GWEN_Directory_FindFileInPaths(const GWEN_STRINGLIST *paths,
00282 const char *filePath,
00283 GWEN_BUFFER *fbuf) {
00284 GWEN_STRINGLISTENTRY *se;
00285
00286 se=GWEN_StringList_FirstEntry(paths);
00287 while(se) {
00288 GWEN_BUFFER *tbuf;
00289 FILE *f;
00290
00291 tbuf=GWEN_Buffer_new(0, 256, 0, 1);
00292 GWEN_Buffer_AppendString(tbuf, GWEN_StringListEntry_Data(se));
00293 GWEN_Buffer_AppendString(tbuf, DIRSEP);
00294 GWEN_Buffer_AppendString(tbuf, filePath);
00295 DBG_DEBUG(GWEN_LOGDOMAIN, "Trying \"%s\"",
00296 GWEN_Buffer_GetStart(tbuf));
00297 f=fopen(GWEN_Buffer_GetStart(tbuf), "r");
00298 if (f) {
00299 fclose(f);
00300 DBG_DEBUG(GWEN_LOGDOMAIN,
00301 "File \"%s\" found in folder \"%s\"",
00302 filePath,
00303 GWEN_StringListEntry_Data(se));
00304 GWEN_Buffer_AppendBuffer(fbuf, tbuf);
00305 GWEN_Buffer_free(tbuf);
00306 return 0;
00307 }
00308 GWEN_Buffer_free(tbuf);
00309
00310 se=GWEN_StringListEntry_Next(se);
00311 }
00312
00313 DBG_INFO(GWEN_LOGDOMAIN, "File \"%s\" not found", filePath);
00314 return GWEN_ERROR_NOT_FOUND;
00315 }
00316
00317
00318
00319 int GWEN_Directory_FindPathForFile(const GWEN_STRINGLIST *paths,
00320 const char *filePath,
00321 GWEN_BUFFER *fbuf) {
00322 GWEN_STRINGLISTENTRY *se;
00323
00324 se=GWEN_StringList_FirstEntry(paths);
00325 while(se) {
00326 GWEN_BUFFER *tbuf;
00327 FILE *f;
00328
00329 tbuf=GWEN_Buffer_new(0, 256, 0, 1);
00330 GWEN_Buffer_AppendString(tbuf, GWEN_StringListEntry_Data(se));
00331 GWEN_Buffer_AppendString(tbuf, DIRSEP);
00332 GWEN_Buffer_AppendString(tbuf, filePath);
00333 DBG_DEBUG(GWEN_LOGDOMAIN, "Trying \"%s\"",
00334 GWEN_Buffer_GetStart(tbuf));
00335 f=fopen(GWEN_Buffer_GetStart(tbuf), "r");
00336 if (f) {
00337 fclose(f);
00338 DBG_INFO(GWEN_LOGDOMAIN,
00339 "File \"%s\" found in folder \"%s\"",
00340 filePath,
00341 GWEN_StringListEntry_Data(se));
00342 GWEN_Buffer_AppendString(fbuf, GWEN_StringListEntry_Data(se));
00343 GWEN_Buffer_free(tbuf);
00344 return 0;
00345 }
00346 GWEN_Buffer_free(tbuf);
00347
00348 se=GWEN_StringListEntry_Next(se);
00349 }
00350
00351 DBG_INFO(GWEN_LOGDOMAIN, "File \"%s\" not found", filePath);
00352 return GWEN_ERROR_NOT_FOUND;
00353 }
00354
00355
00356
00357 int GWEN_Directory_GetTmpDirectory(char *buffer, unsigned int size)
00358 {
00359 const char *tmp_dir;
00360 assert(buffer);
00361
00362
00363 tmp_dir = getenv ("TMPDIR");
00364 if (!tmp_dir)
00365 tmp_dir = getenv ("TMP");
00366 if (!tmp_dir)
00367 tmp_dir = getenv ("TEMP");
00368
00369 if (!tmp_dir)
00370 {
00371 #ifdef OS_WIN32
00372 tmp_dir = "C:\\";
00373 #else
00374 tmp_dir = "/tmp";
00375 #endif
00376 }
00377
00378 strncpy (buffer, tmp_dir, size);
00379 return 0;
00380 }
00381
00382
00383
00384 int GWEN_Directory_GetAllEntries(const char *folder,
00385 GWEN_STRINGLIST *sl,
00386 const char *mask) {
00387 GWEN_DIRECTORY *d;
00388 int rv;
00389 char buffer[256];
00390
00391 d=GWEN_Directory_new();
00392 rv=GWEN_Directory_Open(d, folder);
00393 if (rv<0) {
00394 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00395 GWEN_Directory_free(d);
00396 return rv;
00397 }
00398
00399 while(0==GWEN_Directory_Read(d, buffer, sizeof(buffer))) {
00400 if (strcmp(buffer, ".")!=0 &&
00401 strcmp(buffer, "..")!=0 &&
00402 (mask==NULL ||
00403 GWEN_Text_ComparePattern(buffer+1, mask, 0)!=-1))
00404 GWEN_StringList_AppendString(sl, buffer, 0, 1);
00405 }
00406
00407 GWEN_Directory_Close(d);
00408 GWEN_Directory_free(d);
00409 return 0;
00410 }
00411
00412
00413
00414 int GWEN_Directory_GetFileEntriesWithType(const char *folder,
00415 GWEN_STRINGLIST *sl,
00416 const char *mask) {
00417 GWEN_DIRECTORY *d;
00418 int rv;
00419 char buffer[256];
00420 GWEN_BUFFER *pbuf;
00421 uint32_t pos;
00422
00423 d=GWEN_Directory_new();
00424 rv=GWEN_Directory_Open(d, folder);
00425 if (rv<0) {
00426 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00427 GWEN_Directory_free(d);
00428 return rv;
00429 }
00430
00431 pbuf=GWEN_Buffer_new(0, 256, 0, 1);
00432 GWEN_Buffer_AppendString(pbuf, folder);
00433 GWEN_Buffer_AppendString(pbuf, GWEN_DIR_SEPARATOR_S);
00434 pos=GWEN_Buffer_GetPos(pbuf);
00435
00436 while(0==GWEN_Directory_Read(d, buffer+1, sizeof(buffer)-2)) {
00437 if (strcmp(buffer, ".")!=0 &&
00438 strcmp(buffer, "..")!=0 &&
00439 (mask==NULL ||
00440 GWEN_Text_ComparePattern(buffer+1, mask, 0)!=-1)) {
00441 struct stat st;
00442
00443 GWEN_Buffer_AppendString(pbuf, buffer+1);
00444 if (stat(GWEN_Buffer_GetStart(pbuf), &st)==0) {
00445 if (S_ISREG(st.st_mode))
00446 buffer[0]='f';
00447 else if (S_ISDIR(st.st_mode))
00448 buffer[0]='d';
00449 else
00450 buffer[0]='?';
00451 GWEN_StringList_AppendString(sl, buffer, 0, 1);
00452 }
00453 GWEN_Buffer_Crop(pbuf, 0, pos);
00454 }
00455 }
00456
00457 GWEN_Directory_Close(d);
00458 GWEN_Directory_free(d);
00459 return 0;
00460 }
00461
00462
00463
00464
00465 int GWEN_Directory_GetFileEntries(const char *folder, GWEN_STRINGLIST *sl,
00466 const char *mask) {
00467 GWEN_DIRECTORY *d;
00468 int rv;
00469 char buffer[256];
00470 GWEN_BUFFER *pbuf;
00471 uint32_t pos;
00472
00473 d=GWEN_Directory_new();
00474 rv=GWEN_Directory_Open(d, folder);
00475 if (rv<0) {
00476 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00477 GWEN_Directory_free(d);
00478 return rv;
00479 }
00480
00481 pbuf=GWEN_Buffer_new(0, 256, 0, 1);
00482 GWEN_Buffer_AppendString(pbuf, folder);
00483 GWEN_Buffer_AppendString(pbuf, GWEN_DIR_SEPARATOR_S);
00484 pos=GWEN_Buffer_GetPos(pbuf);
00485
00486 while(0==GWEN_Directory_Read(d, buffer, sizeof(buffer))) {
00487 if (strcmp(buffer, ".")!=0 &&
00488 strcmp(buffer, "..")!=0 &&
00489 (mask==NULL ||
00490 GWEN_Text_ComparePattern(buffer+1, mask, 0)!=-1)) {
00491 struct stat st;
00492
00493 GWEN_Buffer_AppendString(pbuf, buffer);
00494 if (stat(GWEN_Buffer_GetStart(pbuf), &st)==0) {
00495 if (S_ISREG(st.st_mode))
00496 GWEN_StringList_AppendString(sl, buffer, 0, 1);
00497 }
00498 GWEN_Buffer_Crop(pbuf, 0, pos);
00499 }
00500 }
00501
00502 GWEN_Buffer_free(pbuf);
00503 GWEN_Directory_Close(d);
00504 GWEN_Directory_free(d);
00505 return 0;
00506 }
00507
00508
00509
00510 int GWEN_Directory_GetDirEntries(const char *folder, GWEN_STRINGLIST *sl,
00511 const char *mask) {
00512 GWEN_DIRECTORY *d;
00513 int rv;
00514 char buffer[256];
00515 GWEN_BUFFER *pbuf;
00516 uint32_t pos;
00517
00518 d=GWEN_Directory_new();
00519 rv=GWEN_Directory_Open(d, folder);
00520 if (rv<0) {
00521 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00522 GWEN_Directory_free(d);
00523 return rv;
00524 }
00525
00526 pbuf=GWEN_Buffer_new(0, 256, 0, 1);
00527 GWEN_Buffer_AppendString(pbuf, folder);
00528 GWEN_Buffer_AppendString(pbuf, GWEN_DIR_SEPARATOR_S);
00529 pos=GWEN_Buffer_GetPos(pbuf);
00530
00531 while(0==GWEN_Directory_Read(d, buffer, sizeof(buffer))) {
00532 if (strcmp(buffer, ".")!=0 &&
00533 strcmp(buffer, "..")!=0 &&
00534 (mask==NULL ||
00535 GWEN_Text_ComparePattern(buffer+1, mask, 0)!=-1)) {
00536 struct stat st;
00537
00538 GWEN_Buffer_AppendString(pbuf, buffer);
00539 if (stat(GWEN_Buffer_GetStart(pbuf), &st)==0) {
00540 if (S_ISDIR(st.st_mode))
00541 GWEN_StringList_AppendString(sl, buffer, 0, 1);
00542 }
00543 GWEN_Buffer_Crop(pbuf, 0, pos);
00544 }
00545 }
00546
00547 GWEN_Directory_Close(d);
00548 GWEN_Directory_free(d);
00549 return 0;
00550 }
00551
00552
00553
00554 int GWEN_Directory_GetMatchingFilesRecursively(const char *folder,
00555 GWEN_STRINGLIST *sl,
00556 const char *mask) {
00557 GWEN_DIRECTORY *d;
00558 int rv;
00559 char buffer[256];
00560 GWEN_BUFFER *pbuf;
00561 uint32_t pos;
00562 GWEN_STRINGLIST *folderList;
00563
00564 folderList=GWEN_StringList_new();
00565
00566 d=GWEN_Directory_new();
00567 rv=GWEN_Directory_Open(d, folder);
00568 if (rv<0) {
00569 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00570 GWEN_Directory_free(d);
00571 GWEN_StringList_free(folderList);
00572 return rv;
00573 }
00574
00575 pbuf=GWEN_Buffer_new(0, 256, 0, 1);
00576 GWEN_Buffer_AppendString(pbuf, folder);
00577 GWEN_Buffer_AppendString(pbuf, GWEN_DIR_SEPARATOR_S);
00578 pos=GWEN_Buffer_GetPos(pbuf);
00579
00580 while(0==GWEN_Directory_Read(d, buffer, sizeof(buffer)-2)) {
00581 if (strcmp(buffer, ".")!=0 &&
00582 strcmp(buffer, "..")!=0) {
00583 struct stat st;
00584
00585 GWEN_Buffer_AppendString(pbuf, buffer);
00586 if (stat(GWEN_Buffer_GetStart(pbuf), &st)==0) {
00587 if (S_ISDIR(st.st_mode))
00588
00589 GWEN_StringList_AppendString(folderList, GWEN_Buffer_GetStart(pbuf), 0, 1);
00590 else {
00591 if (mask==NULL || GWEN_Text_ComparePattern(buffer, mask, 0)!=-1)
00592 GWEN_StringList_AppendString(sl, GWEN_Buffer_GetStart(pbuf), 0, 1);
00593 }
00594 }
00595 GWEN_Buffer_Crop(pbuf, 0, pos);
00596 }
00597 }
00598
00599 GWEN_Directory_Close(d);
00600 GWEN_Directory_free(d);
00601
00602 if (GWEN_StringList_Count(folderList)) {
00603 GWEN_STRINGLISTENTRY *se;
00604
00605 se=GWEN_StringList_FirstEntry(folderList);
00606 while(se) {
00607 const char *s;
00608
00609 s=GWEN_StringListEntry_Data(se);
00610 if (s && *s)
00611 GWEN_Directory_GetMatchingFilesRecursively(s, sl, mask);
00612 se=GWEN_StringListEntry_Next(se);
00613 }
00614 }
00615 GWEN_StringList_free(folderList);
00616 GWEN_Buffer_free(pbuf);
00617
00618 return 0;
00619 }
00620
00621
00622
00623 int GWEN_Directory_GetAbsoluteFolderPath(const char *folder, GWEN_BUFFER *tbuf) {
00624 char savedPwd[300];
00625 char dataPwd[300];
00626
00627
00628 if (getcwd(savedPwd, sizeof(savedPwd)-1)==NULL) {
00629 DBG_ERROR(GWEN_LOGDOMAIN, "getcwd(): %s", strerror(errno));
00630 return GWEN_ERROR_IO;
00631 }
00632
00633 if (chdir(folder)) {
00634 DBG_ERROR(GWEN_LOGDOMAIN, "chdir(%s): %s", folder, strerror(errno));
00635 return GWEN_ERROR_IO;
00636 }
00637
00638
00639 if (getcwd(dataPwd, sizeof(dataPwd)-1)==NULL) {
00640 DBG_ERROR(GWEN_LOGDOMAIN, "getcwd(): %s", strerror(errno));
00641 return GWEN_ERROR_IO;
00642 }
00643 dataPwd[sizeof(dataPwd)-1]=0;
00644
00645
00646 if (chdir(savedPwd)) {
00647 DBG_ERROR(GWEN_LOGDOMAIN, "chdir(%s): %s", folder, strerror(errno));
00648 return GWEN_ERROR_IO;
00649 }
00650
00651 GWEN_Buffer_AppendString(tbuf, dataPwd);
00652 return 0;
00653 }
00654
00655
00656
00657
00658
00659