00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #define _FILE_OFFSET_BITS 64
00011 #include <errno.h>
00012 #include <stdio.h>
00013 #include <string.h>
00014 #include <sys/types.h>
00015
00016 #if !defined(__solaris__)
00017 #include <sys/xattr.h>
00018 #endif
00019
00020 #ifndef ENOATTR
00021 #define ENOATTR ENODATA
00022 #endif
00023
00024 #include <iostream>
00025 #include <libgen.h>
00026 #include <unistd.h>
00027 #include <stdlib.h>
00028 #include <syslog.h>
00029 #include "XrdFfs/XrdFfsPosix.hh"
00030 #include "XrdPosix/XrdPosixXrootd.hh"
00031 #include "XrdFfs/XrdFfsMisc.hh"
00032 #include "XrdFfs/XrdFfsDent.hh"
00033 #include "XrdFfs/XrdFfsQueue.hh"
00034
00035 #ifdef __cplusplus
00036 extern "C" {
00037 #endif
00038
00039 int XrdFfsPosix_stat(const char *path, struct stat *buf)
00040 {
00041 int rc;
00042 errno = 0;
00043 rc = XrdPosixXrootd::Stat(path, buf);
00044 if (rc == 0 && S_ISBLK(buf->st_mode))
00045 {
00046 buf->st_mode &= 0007777;
00047 if ( buf->st_mode & S_IXUSR )
00048 buf->st_mode |= 0040000;
00049 else
00050 buf->st_mode |= 0100000;
00051 }
00052 return rc;
00053 }
00054
00055 DIR *XrdFfsPosix_opendir(const char *path)
00056 {
00057 return XrdPosixXrootd::Opendir(path);
00058 }
00059
00060 struct dirent *XrdFfsPosix_readdir(DIR *dirp)
00061 {
00062 return XrdPosixXrootd::Readdir(dirp);
00063 }
00064
00065 int XrdFfsPosix_closedir(DIR *dirp)
00066 {
00067 return XrdPosixXrootd::Closedir(dirp);
00068 }
00069
00070 int XrdFfsPosix_mkdir(const char *path, mode_t mode)
00071 {
00072 return XrdPosixXrootd::Mkdir(path, mode);
00073 }
00074
00075 int XrdFfsPosix_rmdir(const char *path)
00076 {
00077
00078 return XrdPosixXrootd::Rmdir(path);
00079 }
00080
00081 int XrdFfsPosix_open(const char *path, int oflags, mode_t mode)
00082 {
00083 return XrdPosixXrootd::Open(path, oflags, mode);
00084 }
00085
00086 int XrdFfsPosix_close(int fildes)
00087 {
00088 return XrdPosixXrootd::Close(fildes);
00089 }
00090
00091 off_t XrdFfsPosix_lseek(int fildes, off_t offset, int whence)
00092 {
00093 return XrdPosixXrootd::Lseek(fildes, (long long)offset, whence);
00094 }
00095
00096 ssize_t XrdFfsPosix_read(int fildes, void *buf, size_t nbyte)
00097 {
00098 return XrdPosixXrootd::Read(fildes, buf, nbyte);
00099 }
00100
00101 ssize_t XrdFfsPosix_pread(int fildes, void *buf, size_t nbyte, off_t offset)
00102 {
00103 return XrdPosixXrootd::Pread(fildes, buf, nbyte, (long long)offset);
00104 }
00105
00106 ssize_t XrdFfsPosix_write(int fildes, const void *buf, size_t nbyte)
00107 {
00108 return XrdPosixXrootd::Write(fildes, buf, nbyte);
00109 }
00110
00111 ssize_t XrdFfsPosix_pwrite(int fildes, const void *buf, size_t nbyte, off_t offset)
00112 {
00113 return XrdPosixXrootd::Pwrite(fildes, buf, nbyte, (long long) offset);
00114 }
00115
00116 int XrdFfsPosix_fsync(int fildes)
00117 {
00118 return XrdPosixXrootd::Fsync(fildes);
00119 }
00120
00121 int XrdFfsPosix_unlink(const char *path)
00122 {
00123 return XrdPosixXrootd::Unlink(path);
00124 }
00125
00126 int XrdFfsPosix_rename(const char *oldpath, const char *newpath)
00127 {
00128 return XrdPosixXrootd::Rename(oldpath, newpath);
00129 }
00130
00131 int XrdFfsPosix_ftruncate(int fildes, off_t offset)
00132 {
00133 return XrdPosixXrootd::Ftruncate(fildes, offset);
00134 }
00135 int XrdFfsPosix_truncate(const char *path, off_t Size)
00136 {
00137 return XrdPosixXrootd::Truncate(path, Size);
00138 }
00139
00140 long long XrdFfsPosix_getxattr(const char *path, const char *name, void *value, unsigned long long size)
00141 {
00142 int bufsize;
00143 char xattrbuf[1024], nameclass[128], *namesubclass;
00144 char *token, *key, *val;
00145 char *lasts_xattr[256], *lasts_tokens[128];
00146
00147
00148
00149
00150
00151 strncpy(nameclass, name, 11);
00152 nameclass[11] = '\0';
00153
00154 if (strcmp(nameclass, "xroot.space") != 0 && strcmp(nameclass, "xroot.xattr") != 0)
00155 {
00156 errno = ENOATTR;
00157 return -1;
00158 }
00159
00160 bufsize = XrdPosixXrootd::Getxattr(path, nameclass, xattrbuf, size);
00161 if (bufsize == -1) return -1;
00162
00163 if (strlen(name) > 11)
00164 {
00165 strcpy(nameclass, name);
00166 namesubclass = &nameclass[12];
00167 }
00168 else
00169 {
00170 strcpy((char*)value, xattrbuf);
00171 return bufsize;
00172 }
00173
00174 token = strtok_r(xattrbuf, "&", lasts_xattr);
00175 while ( token != NULL )
00176 {
00177 key = strtok_r(token, "=", lasts_tokens);
00178 val = strtok_r(NULL, "=", lasts_tokens);
00179 if (! strcmp(key, namesubclass))
00180 {
00181 strcpy((char*)value, val);
00182 return strlen(val);
00183 }
00184 token = strtok_r(NULL, "&", lasts_xattr);
00185 }
00186 errno = ENOATTR;
00187 return -1;
00188 }
00189
00190
00191
00192 struct XrdFfsPosixX_deleteall_args {
00193 char *url;
00194 int *res;
00195 int *err;
00196 mode_t st_mode;
00197 };
00198
00199 void* XrdFfsPosix_x_deleteall(void *x)
00200 {
00201 struct XrdFfsPosixX_deleteall_args* args = (struct XrdFfsPosixX_deleteall_args*) x;
00202
00203 if (S_ISREG(args->st_mode))
00204 *(args->res) = XrdFfsPosix_unlink(args->url);
00205 else if (S_ISDIR(args->st_mode))
00206 *(args->res) = XrdFfsPosix_rmdir(args->url);
00207
00208 *(args->err) = errno;
00209 return NULL;
00210 }
00211
00212 int XrdFfsPosix_deleteall(const char *rdrurl, const char *path, uid_t user_uid, mode_t st_mode)
00213 {
00214 int i, nurls, res, rval;
00215 char *newurls[XrdFfs_MAX_NUM_NODES];
00216 int res_i[XrdFfs_MAX_NUM_NODES];
00217 int errno_i[XrdFfs_MAX_NUM_NODES];
00218 struct XrdFfsPosixX_deleteall_args args[XrdFfs_MAX_NUM_NODES];
00219 struct XrdFfsQueueTasks *jobs[XrdFfs_MAX_NUM_NODES];
00220
00221 nurls = XrdFfsMisc_get_all_urls(rdrurl, newurls, XrdFfs_MAX_NUM_NODES);
00222 if (nurls < 0) rval = -1;
00223
00224 for (i = 0; i < nurls; i++)
00225 {
00226 errno_i[i] = 0;
00227 strcat(newurls[i],path);
00228 XrdFfsMisc_xrd_secsss_editurl(newurls[i], user_uid);
00229 args[i].url = newurls[i];
00230 args[i].err = &errno_i[i];
00231 args[i].res = &res_i[i];
00232 args[i].st_mode = st_mode;
00233 #ifdef NOUSE_QUEUE
00234 XrdFfsPosix_x_deleteall((void*) &args[i]);
00235 }
00236 #else
00237 jobs[i] = XrdFfsQueue_create_task(XrdFfsPosix_x_deleteall, (void**)(&args[i]), 0);
00238 }
00239 for (i = 0; i < nurls; i++)
00240 {
00241 XrdFfsQueue_wait_task(jobs[i]);
00242 XrdFfsQueue_free_task(jobs[i]);
00243 }
00244 #endif
00245 res = -1;
00246 errno = ENOENT;
00247 for (i = 0; i < nurls; i++)
00248 if (res_i[i] == 0)
00249 {
00250 res = 0;
00251 errno = 0;
00252 }
00253 else if (res_i[i] != 0 && errno_i[i] == 125)
00254 {
00255 res = -1;
00256 errno = ETIMEDOUT;
00257 syslog(LOG_WARNING, "WARNING: unlink/rmdir(%s) failed (connection timeout)", newurls[i]);
00258 break;
00259 }
00260 else if (res_i[i] != 0 && errno_i[i] != ENOENT)
00261 {
00262 res = -1;
00263 errno = errno_i[i];
00264 syslog(LOG_WARNING, "WARNING: unlink/rmdir(%s) failed (errno = %d)", newurls[i], errno);
00265 break;
00266 }
00267
00268 for (i = 0; i < nurls; i++)
00269 free(newurls[i]);
00270
00271 return res;
00272 }
00273
00274 int XrdFfsPosix_unlinkall(const char *rdrurl, const char *path, uid_t user_uid)
00275 {
00276 return XrdFfsPosix_deleteall(rdrurl, path, user_uid, S_IFREG);
00277 }
00278
00279 int XrdFfsPosix_rmdirall(const char *rdrurl, const char *path, uid_t user_uid)
00280 {
00281 return XrdFfsPosix_deleteall(rdrurl, path, user_uid, S_IFDIR);
00282 }
00283
00284 int XrdFfsPosix_renameall(const char *rdrurl, const char *from, const char *to, uid_t user_uid)
00285 {
00286 int i, nurls, res, rval = 0;
00287 struct stat stbuf;
00288 char fromurl[1024], tourl[1024], *newurls[XrdFfs_MAX_NUM_NODES];
00289
00290 nurls = XrdFfsMisc_get_all_urls(rdrurl, newurls, XrdFfs_MAX_NUM_NODES);
00291 if (nurls < 0) rval = -1;
00292
00293 for (i = 0; i < nurls; i++)
00294 {
00295 errno = 0;
00296
00297 fromurl[0]='\0';
00298 strcat(fromurl, newurls[i]);
00299 strcat(fromurl, from);
00300 tourl[0]='\0';
00301 strcat(tourl, newurls[i]);
00302 strcat(tourl, to);
00303
00304 XrdFfsMisc_xrd_secsss_editurl(fromurl, user_uid);
00305 XrdFfsMisc_xrd_secsss_editurl(tourl, user_uid);
00306 res = (XrdFfsPosix_stat(fromurl, &stbuf));
00307 if (res == 0)
00308 {
00309
00310
00311
00312
00313
00314
00315
00316
00317 rval = XrdFfsPosix_rename(fromurl, tourl);
00318 if (rval == -1)
00319 {
00320 syslog(LOG_WARNING, "WARNING: rename(%s, %s) failed (errno = %d)", fromurl, tourl, errno);
00321 break;
00322 }
00323
00324 }
00325 }
00326
00327 for (i = 0; i < nurls; i++)
00328 free(newurls[i]);
00329
00330 if (rval != 0 && errno == 0) errno = EIO;
00331 return rval;
00332 }
00333
00334 int XrdFfsPosix_truncateall(const char *rdrurl, const char *path, off_t size, uid_t user_uid)
00335 {
00336 int i, nurls, res, rval = 0;
00337 struct stat stbuf;
00338 char *newurls[XrdFfs_MAX_NUM_NODES];
00339
00340 nurls = XrdFfsMisc_get_all_urls(rdrurl, newurls, XrdFfs_MAX_NUM_NODES);
00341 if (nurls < 0) rval = -1;
00342
00343 for (i = 0; i < nurls; i++)
00344 {
00345 errno = 0;
00346 strcat(newurls[i],path);
00347 XrdFfsMisc_xrd_secsss_editurl(newurls[i], user_uid);
00348 res = (XrdFfsPosix_stat(newurls[i], &stbuf));
00349 if (res == 0)
00350 {
00351 if (S_ISREG(stbuf.st_mode))
00352 rval = XrdFfsPosix_truncate(newurls[i], size);
00353 else
00354 rval = -1;
00355 if (rval == -1)
00356 {
00357 syslog(LOG_WARNING, "WARNING: (f)truncate(%s) failed (errno = %d)", newurls[i], errno);
00358 break;
00359 }
00360
00361 }
00362 else if (errno != ENOENT)
00363 rval = -1;
00364 }
00365
00366 for (i = 0; i < nurls; i++)
00367 free(newurls[i]);
00368
00369 if (rval != 0 && errno == 0) errno = EIO;
00370 return rval;
00371 }
00372
00373 struct XrdFfsPosixX_readdirall_args {
00374 char *url;
00375 int *res;
00376 int *err;
00377 struct XrdFfsDentnames **dents;
00378 };
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389 void* XrdFfsPosix_x_readdirall(void* x)
00390 {
00391 struct XrdFfsPosixX_readdirall_args *args = (struct XrdFfsPosixX_readdirall_args*) x;
00392 DIR *dp;
00393 struct dirent *de;
00394
00395
00396
00397
00398
00399
00400 dp = XrdFfsPosix_opendir(args->url);
00401 if ( dp == NULL && errno != 0)
00402 {
00403 *(args->err) = errno;
00404 *(args->res) = -1;
00405 if (dp != NULL)
00406 XrdFfsPosix_closedir(dp);
00407 }
00408 else
00409 {
00410 *(args->res) = 0;
00411 while ((de = XrdFfsPosix_readdir(dp)) != NULL)
00412 XrdFfsDent_names_add(args->dents, de->d_name);
00413 XrdFfsPosix_closedir(dp);
00414 }
00415 return NULL;
00416 }
00417
00418 int XrdFfsPosix_readdirall(const char *rdrurl, const char *path, char*** direntarray, uid_t user_uid)
00419 {
00420 int i, j, n, nents, nurls;
00421 bool hasDirLock = false;
00422
00423 char *newurls[XrdFfs_MAX_NUM_NODES];
00424 int res_i[XrdFfs_MAX_NUM_NODES];
00425 int errno_i[XrdFfs_MAX_NUM_NODES];
00426 struct XrdFfsDentnames *dir_i[XrdFfs_MAX_NUM_NODES] = {0};
00427 struct XrdFfsPosixX_readdirall_args args[XrdFfs_MAX_NUM_NODES];
00428 struct XrdFfsQueueTasks *jobs[XrdFfs_MAX_NUM_NODES];
00429
00430
00431
00432
00433 nurls = XrdFfsMisc_get_all_urls(rdrurl, newurls, XrdFfs_MAX_NUM_NODES);
00434 if (nurls < 0)
00435 {
00436 errno = EACCES;
00437 return -1;
00438 }
00439
00440 for (i = 0; i < nurls; i++)
00441 {
00442 errno_i[i] = 0;
00443 strcat(newurls[i], path);
00444 XrdFfsMisc_xrd_secsss_editurl(newurls[i], user_uid);
00445 args[i].url = newurls[i];
00446 args[i].err = &errno_i[i];
00447 args[i].res = &res_i[i];
00448 args[i].dents = &dir_i[i];
00449 #ifdef NOUSE_QUEUE
00450 XrdFfsPosix_x_readdirall((void*) &args[i]);
00451 }
00452 #else
00453 jobs[i] = XrdFfsQueue_create_task(XrdFfsPosix_x_readdirall, (void**)(&args[i]), 0);
00454 }
00455 for (i = 0; i < nurls; i++)
00456 {
00457 XrdFfsQueue_wait_task(jobs[i]);
00458 XrdFfsQueue_free_task(jobs[i]);
00459 }
00460 #endif
00461
00462 errno = 0;
00463 for (i = 0; i < nurls; i++)
00464 if (res_i[i] != 0 && errno_i[i] == 125)
00465 {
00466 errno = ETIMEDOUT;
00467 syslog(LOG_WARNING, "WARNING: opendir(%s) failed (connection timeout)", newurls[i]);
00468 break;
00469 }
00470
00471 for (i = 0; i < nurls; i++)
00472 free(newurls[i]);
00473 for (i = 1; i < nurls; i++)
00474 XrdFfsDent_names_join(&dir_i[i], &dir_i[i-1]);
00475
00476 char *last = NULL, **dnarraytmp;
00477
00478 n = XrdFfsDent_names_extract(&dir_i[nurls-1], &dnarraytmp);
00479 *direntarray = (char **) malloc(sizeof(char*) * n);
00480
00481
00482
00483 nents = 0;
00484 for (i = 0; i < n; i++)
00485 {
00486
00487
00488 if (! strcmp(dnarraytmp[i], "DIR_LOCK"))
00489 {
00490 hasDirLock = true;
00491 continue;
00492 }
00493
00494 if (i != 0)
00495 {
00496 char *tmp, *tmp_dot;
00497 tmp = strdup(dnarraytmp[i]);
00498 tmp_dot = tmp + strlen(tmp) - 5;
00499
00500 if (! strcmp(tmp_dot, ".lock") || ! strcmp(tmp_dot, ".fail"))
00501 {
00502 for (j = nents - 1; j >= 0; j--)
00503 {
00504 tmp_dot[0] = '\0';
00505 if (! strcmp(tmp, (*direntarray)[j]))
00506 {
00507 tmp_dot[0] = '.';
00508 free(tmp);
00509 break;
00510 }
00511 }
00512 if (j >= 0) continue;
00513 }
00514 free(tmp);
00515 }
00516
00517 if (last == NULL || strcmp(last, dnarraytmp[i]) != 0)
00518 {
00519 last = dnarraytmp[i];
00520 (*direntarray)[nents++] = strdup(dnarraytmp[i]);
00521 }
00522 }
00523
00524 for (i = 0; i < n; i++) free(dnarraytmp[i]);
00525 free(dnarraytmp);
00526
00527
00528
00529 char *p;
00530 p = strdup(path);
00531 XrdFfsDent_cache_fill(p, direntarray, nents);
00532 free(p);
00533
00534 if (hasDirLock) (*direntarray)[nents++] = strdup("DIR_LOCK");
00535
00536 return nents;
00537 }
00538
00539
00540
00541
00542
00543
00544 struct XrdFfsPosixX_statvfsall_args {
00545 char *url;
00546 int *res;
00547 int *err;
00548 struct statvfs *stbuf;
00549 short osscgroup;
00550 };
00551
00552 void* XrdFfsPosix_x_statvfsall(void *x)
00553 {
00554 struct XrdFfsPosixX_statvfsall_args *args = (struct XrdFfsPosixX_statvfsall_args *)x;
00555 char xattr[256];
00556 off_t oss_size;
00557 long long llVal;
00558
00559 *(args->res) = XrdFfsPosix_getxattr(args->url, "xroot.space.oss.space", xattr, 256);
00560 *(args->err) = errno;
00561 sscanf((const char*)xattr, "%lld", &llVal);
00562 oss_size = static_cast<off_t>(llVal);
00563 args->stbuf->f_blocks = (fsblkcnt_t) (oss_size / args->stbuf->f_bsize);
00564
00565 if (*(args->res) == -1)
00566 {
00567 args->stbuf->f_blocks = 0;
00568 args->stbuf->f_bavail = 0;
00569 args->stbuf->f_bfree = 0;
00570 return NULL;
00571 }
00572 *(args->res) = XrdFfsPosix_getxattr(args->url, "xroot.space.oss.free", xattr, 256);
00573 *(args->err) = errno;
00574 sscanf((const char*)xattr, "%lld", &llVal);
00575 oss_size = static_cast<off_t>(llVal);
00576 args->stbuf->f_bavail = (fsblkcnt_t) (oss_size / args->stbuf->f_bsize);
00577
00578 if (*(args->res) == -1)
00579 {
00580 args->stbuf->f_blocks = 0;
00581 args->stbuf->f_bavail = 0;
00582 args->stbuf->f_bfree = 0;
00583 return NULL;
00584 }
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596 if (args->osscgroup != 1)
00597 args->stbuf->f_bfree = args->stbuf->f_bavail;
00598 else
00599 {
00600 *(args->res) = XrdFfsPosix_getxattr(args->url, "xroot.space.oss.used", xattr, 256);
00601 *(args->err) = errno;
00602 sscanf((const char*)xattr, "%lld", &llVal);
00603 oss_size = static_cast<off_t>(llVal);
00604 args->stbuf->f_bfree = args->stbuf->f_blocks - (fsblkcnt_t) (oss_size / args->stbuf->f_bsize);
00605
00606 }
00607 return NULL;
00608 }
00609
00610 int XrdFfsPosix_statvfsall(const char *rdrurl, const char *path, struct statvfs *stbuf, uid_t user_uid)
00611 {
00612 int i, nurls;
00613 short osscgroup;
00614
00615 char *newurls[XrdFfs_MAX_NUM_NODES];
00616 int res_i[XrdFfs_MAX_NUM_NODES];
00617 int errno_i[XrdFfs_MAX_NUM_NODES];
00618 struct statvfs stbuf_i[XrdFfs_MAX_NUM_NODES];
00619 struct XrdFfsPosixX_statvfsall_args args[XrdFfs_MAX_NUM_NODES];
00620 struct XrdFfsQueueTasks *jobs[XrdFfs_MAX_NUM_NODES];
00621
00622 nurls = XrdFfsMisc_get_all_urls(rdrurl, newurls, XrdFfs_MAX_NUM_NODES);
00623 if (nurls < 0)
00624 {
00625 errno = EACCES;
00626 return -1;
00627 }
00628
00629 if (strstr(path, "oss.cgroup") != NULL)
00630 osscgroup = 1;
00631 else
00632 osscgroup = 0;
00633 for (i = 0; i < nurls; i++)
00634 {
00635 strcat(newurls[i], path);
00636
00637 args[i].url = newurls[i];
00638 args[i].res = &res_i[i];
00639 args[i].err = &errno_i[i];
00640 stbuf_i[i].f_bsize = stbuf->f_bsize;
00641 args[i].stbuf = &(stbuf_i[i]);
00642 args[i].osscgroup = osscgroup;
00643 #ifdef NOUSE_QUEUE
00644 XrdFfsPosix_x_statvfsall((void*) &args[i]);
00645 }
00646 #else
00647 jobs[i] = XrdFfsQueue_create_task(XrdFfsPosix_x_statvfsall, (void**)(&args[i]), 0);
00648 }
00649 for (i = 0; i < nurls; i++)
00650 {
00651 XrdFfsQueue_wait_task(jobs[i]);
00652 XrdFfsQueue_free_task(jobs[i]);
00653 }
00654 #endif
00655
00656
00657
00658 stbuf->f_blocks = 0;
00659 stbuf->f_bfree = 0;
00660 stbuf->f_bavail = 0;
00661 for (i = 0; i < nurls; i++)
00662 {
00663 stbuf->f_blocks += args[i].stbuf->f_blocks;
00664 stbuf->f_bavail += args[i].stbuf->f_bavail;
00665 stbuf->f_bfree += args[i].stbuf->f_bfree;
00666 }
00667
00668 for (i = 0; i < nurls; i++)
00669 free(newurls[i]);
00670
00671 return 0;
00672 }
00673
00674
00675
00676 struct XrdFfsPosixX_statall_args {
00677 char *url;
00678 int *res;
00679 int *err;
00680 struct stat *stbuf;
00681 };
00682
00683 void* XrdFfsPosix_x_statall(void *x)
00684 {
00685 struct XrdFfsPosixX_statall_args *args = (struct XrdFfsPosixX_statall_args *)x;
00686
00687 *(args->res) = XrdFfsPosix_stat(args->url, args->stbuf);
00688 *(args->err) = errno;
00689 return (void *)0;
00690 }
00691
00692 int XrdFfsPosix_statall(const char *rdrurl, const char *path, struct stat *stbuf, uid_t user_uid)
00693 {
00694 int i, res, nurls;
00695
00696 char *newurls[XrdFfs_MAX_NUM_NODES];
00697 int res_i[XrdFfs_MAX_NUM_NODES];
00698 int errno_i[XrdFfs_MAX_NUM_NODES];
00699 struct stat stbuf_i[XrdFfs_MAX_NUM_NODES];
00700 struct XrdFfsPosixX_statall_args args[XrdFfs_MAX_NUM_NODES];
00701 struct XrdFfsQueueTasks *jobs[XrdFfs_MAX_NUM_NODES];
00702
00703 char *p1, *p2, *dir, *file, rootpath[1024];
00704
00705 rootpath[0] = '\0';
00706 strcat(rootpath,rdrurl);
00707 strcat(rootpath,path);
00708 p1 = strdup(path);
00709 p2 = strdup(path);
00710 dir = dirname(p1);
00711 file = basename(p2);
00712
00713 if (XrdFfsDent_cache_search(dir, file))
00714 {
00715 XrdFfsMisc_xrd_secsss_editurl(rootpath, user_uid);
00716 res = XrdFfsPosix_stat(rootpath, stbuf);
00717
00718
00719
00720 if (res == 0)
00721 {
00722 free(p1);
00723 free(p2);
00724 return 0;
00725 }
00726 }
00727 free(p1);
00728 free(p2);
00729
00730 nurls = XrdFfsMisc_get_all_urls(rdrurl, newurls, XrdFfs_MAX_NUM_NODES);
00731
00732 for (i = 0; i < nurls; i++)
00733 {
00734 strcat(newurls[i], path);
00735 XrdFfsMisc_xrd_secsss_editurl(newurls[i], user_uid);
00736 args[i].url = newurls[i];
00737 args[i].res = &res_i[i];
00738 args[i].err = &errno_i[i];
00739 args[i].stbuf = &(stbuf_i[i]);
00740 #ifdef NOUSE_QUEUE
00741 XrdFfsPosix_x_statall((void*) &args[i]);
00742 }
00743 #else
00744 jobs[i] = XrdFfsQueue_create_task(XrdFfsPosix_x_statall, (void**)(&args[i]), 0);
00745 }
00746 for (i = 0; i < nurls; i++)
00747 {
00748 XrdFfsQueue_wait_task(jobs[i]);
00749 XrdFfsQueue_free_task(jobs[i]);
00750 }
00751 #endif
00752 res = -1;
00753 errno = ENOENT;
00754 for (i = 0; i < nurls; i++)
00755 if (res_i[i] == 0)
00756 {
00757 res = 0;
00758 errno = 0;
00759 memcpy((void*)stbuf, (void*)(&stbuf_i[i]), sizeof(struct stat));
00760 break;
00761 }
00762 else if (res_i[i] != 0 && errno_i[i] == 125)
00763 {
00764 res = -1;
00765 errno = ETIMEDOUT;
00766 syslog(LOG_WARNING, "WARNING: stat(%s) failed (connection timeout)", newurls[i]);
00767 }
00768
00769 for (i = 0; i < nurls; i++)
00770 free(newurls[i]);
00771
00772 return res;
00773 }
00774
00775 #ifdef __cplusplus
00776 }
00777 #endif