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
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 #include "RConfigure.h"
00210 #include "RConfig.h"
00211
00212 #include <ctype.h>
00213 #include <fcntl.h>
00214 #include <pwd.h>
00215 #include <stdio.h>
00216 #include <string.h>
00217 #include <string>
00218 #include <stdlib.h>
00219 #include <unistd.h>
00220 #include <time.h>
00221 #include <sys/time.h>
00222 #include <sys/stat.h>
00223 #include <netinet/in.h>
00224 #include <errno.h>
00225 #include <netdb.h>
00226 #include "snprintf.h"
00227
00228 #include <sys/types.h>
00229 #include <dirent.h>
00230
00231 #if defined(__CYGWIN__) && defined(__GNUC__)
00232 # define cygwingcc
00233 #endif
00234 #if defined(__alpha) && !defined(linux)
00235 # ifdef _XOPEN_SOURCE
00236 # if _XOPEN_SOURCE+0 > 0
00237 # define R__TRUE64
00238 # endif
00239 # endif
00240 #include <sys/mount.h>
00241 #ifndef R__TRUE64
00242 extern "C" int fstatfs(int file_descriptor, struct statfs *buffer);
00243 #endif
00244 #elif defined(__APPLE__)
00245 #include <sys/mount.h>
00246 extern "C" int fstatfs(int file_descriptor, struct statfs *buffer);
00247 #elif defined(linux) || defined(__hpux) || defined(cygwingcc)
00248 #include <sys/vfs.h>
00249 #elif defined(__FreeBSD__) || defined(__OpenBSD__)
00250 #include <sys/param.h>
00251 #include <sys/mount.h>
00252 #else
00253 #include <sys/statfs.h>
00254 #endif
00255
00256 #if defined(linux) || defined(__hpux) || defined(_AIX) || defined(__alpha) || \
00257 defined(__sun) || defined(__sgi) || defined(__FreeBSD__) || \
00258 defined(__APPLE__) || defined(cygwingcc) || defined(__OpenBSD__)
00259 #define HAVE_MMAP
00260 #endif
00261
00262 #ifdef HAVE_MMAP
00263 # include <sys/mman.h>
00264 #ifndef MAP_FILE
00265 #define MAP_FILE 0
00266 #endif
00267 #endif
00268
00269 #if (defined(__FreeBSD__) && (__FreeBSD__ < 4)) || defined(__OpenBSD__) || \
00270 (defined(__APPLE__) && (!defined(MAC_OS_X_VERSION_10_3) || \
00271 (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_3)))
00272 #include <sys/file.h>
00273 #define lockf(fd, op, sz) flock((fd), (op))
00274 #ifndef F_LOCK
00275 #define F_LOCK (LOCK_EX | LOCK_NB)
00276 #endif
00277 #ifndef F_ULOCK
00278 #define F_ULOCK LOCK_UN
00279 #endif
00280 #endif
00281
00282 #if defined(cygwingcc)
00283 #define F_LOCK F_WRLCK
00284 #define F_ULOCK F_UNLCK
00285 static int fcntl_lockf(int fd, int op, off_t off)
00286 {
00287 flock fl;
00288 fl.l_whence = SEEK_SET;
00289 fl.l_start = off;
00290 fl.l_len = 0;
00291 fl.l_pid = getpid();
00292 fl.l_type = op;
00293 return fcntl(fd, F_SETLK, &fl);
00294 }
00295 #define lockf fcntl_lockf
00296 #endif
00297
00298 #if defined(linux) || defined(__sun) || defined(__sgi) || \
00299 defined(_AIX) || defined(__FreeBSD__) || defined(__APPLE__) || \
00300 defined(__MACH__) || defined(cygwingcc) || defined(__OpenBSD__)
00301 #include <grp.h>
00302 #include <sys/types.h>
00303 #include <signal.h>
00304 #define ROOT_SIGNAL_INCLUDED
00305 #endif
00306
00307 #if defined(__alpha) && !defined(linux) && !defined(__FreeBSD__) && \
00308 !defined(__OpenBSD__)
00309 extern "C" int initgroups(const char *name, int basegid);
00310 #ifndef ROOT_SIGNAL_INCLUDED
00311 #include <signal.h>
00312 #endif
00313 #endif
00314
00315 #if defined(__sgi) && !defined(__GNUG__) && (SGI_REL<62)
00316 extern "C" {
00317 int seteuid(int euid);
00318 int setegid(int egid);
00319 }
00320 #endif
00321
00322 #if defined(_AIX)
00323 extern "C" {
00324
00325 int seteuid(uid_t euid);
00326 int setegid(gid_t egid);
00327 }
00328 #endif
00329
00330 #include "rootdp.h"
00331
00332 extern "C" {
00333 #include "rsadef.h"
00334 #include "rsalib.h"
00335 }
00336
00337
00338 int gDebug = 0;
00339
00340
00341
00342 enum EFileMode{ kBinary, kAscii };
00343
00344 static std::string gRootdTab;
00345 static std::string gRpdAuthTab;
00346 static EService gService = kROOTD;
00347 static int gProtocol = 18;
00348 static int gClientProtocol = -1;
00349 static int gAnon = 0;
00350 static double gBytesRead = 0;
00351 static double gBytesWritten = 0;
00352 static DIR *gRDDirectory = 0;
00353 static int gDownloaded = 0;
00354 static int gFd = -1;
00355 static int gFtp = 0;
00356 static int gInetdFlag = 0;
00357 static char gOption[32] = { 0 };
00358 static char gFile[kMAXPATHLEN] = { 0 };
00359 static int gUploaded = 0;
00360 static int gWritable = 0;
00361 static int gReadOnly = 0;
00362 static std::string gUser;
00363 static std::string gPasswd;
00364
00365
00366 static int gCastorFlag = 0;
00367 static std::string gCastorFile;
00368 static std::string gCastorReqId;
00369
00370 using namespace ROOT;
00371
00372
00373
00374
00375 void Err(int level,const char *msg, int size)
00376 {
00377 Perror((char *)msg,size);
00378 if (level > -1) NetSendError((ERootdErrors)level);
00379 }
00380
00381 void ErrFatal(int level,const char *msg, int size)
00382 {
00383 Perror((char *)msg,size);
00384 if (level > -1) NetSendError((ERootdErrors)level);
00385 RootdClose();
00386 exit(1);
00387 }
00388
00389 void ErrSys(int level,const char *msg, int size)
00390 {
00391 Perror((char *)msg,size);
00392 ErrFatal(level,msg,size);
00393 }
00394
00395
00396
00397 const char *shellMeta = "~*[]{}?$";
00398 const char *shellStuff = "(){}<>\"'";
00399 const char shellEscape = '\\';
00400
00401
00402 static int EscChar(const char *src, char *dst, int dstlen, const char *specchars, char escchar)
00403 {
00404
00405
00406 const char *p;
00407 char *q, *end = dst+dstlen-1;
00408
00409 for (p = src, q = dst; *p && q < end; ) {
00410 if (strchr(specchars, *p)) {
00411 *q++ = escchar;
00412 if (q < end)
00413 *q++ = *p++;
00414 } else
00415 *q++ = *p++;
00416 }
00417 *q = '\0';
00418
00419 if (*p != 0)
00420 return -1;
00421 return q-dst;
00422 }
00423
00424
00425 void SigPipe(int)
00426 {
00427
00428
00429 ErrorInfo("SigPipe: rootd.cxx: got a SIGPIPE");
00430
00431
00432 RpdAuthCleanup(0, 0);
00433 RootdClose();
00434 exit(1);
00435 }
00436
00437
00438 static const char *HomeDirectory(const char *name)
00439 {
00440
00441
00442 static char path[kMAXPATHLEN], mydir[kMAXPATHLEN];
00443 struct passwd *pw;
00444
00445 if (name) {
00446 pw = getpwnam(name);
00447 if (pw) {
00448 strncpy(path, pw->pw_dir, kMAXPATHLEN-1);
00449 path[sizeof(path)-1] = '\0';
00450 return path;
00451 }
00452 } else {
00453 if (mydir[0])
00454 return mydir;
00455 pw = getpwuid(getuid());
00456 if (pw) {
00457 strncpy(mydir, pw->pw_dir, kMAXPATHLEN-1);
00458 mydir[sizeof(mydir)-1] = '\0';
00459 return mydir;
00460 }
00461 }
00462 return 0;
00463 }
00464
00465
00466 char *RootdExpandPathName(const char *name)
00467 {
00468
00469
00470
00471 const char *patbuf = name;
00472
00473
00474 while (*patbuf == ' ')
00475 patbuf++;
00476
00477
00478 for (const char *p = patbuf; *p; p++)
00479 if (strchr(shellMeta, *p))
00480 goto needshell;
00481
00482 return strdup(name);
00483
00484 needshell:
00485
00486 char escPatbuf[kMAXPATHLEN];
00487 EscChar(patbuf, escPatbuf, sizeof(escPatbuf), shellStuff, shellEscape);
00488
00489 char cmd[kMAXPATHLEN];
00490 #ifdef __hpux
00491 strlcpy(cmd, "/bin/echo ", sizeof(cmd));
00492 #else
00493 strlcpy(cmd, "echo ", sizeof(cmd));
00494 #endif
00495
00496
00497 if (escPatbuf[0] == '~') {
00498 const char *hd;
00499 if (escPatbuf[1] != '\0' && escPatbuf[1] != '/') {
00500
00501 char uname[70], *p, *q;
00502 for (p = &escPatbuf[1], q = uname; *p && *p !='/';)
00503 *q++ = *p++;
00504 *q = '\0';
00505 hd = HomeDirectory(uname);
00506 if (hd == 0)
00507 strcat(cmd, escPatbuf);
00508 else {
00509 strcat(cmd, hd);
00510 strcat(cmd, p);
00511 }
00512
00513 } else {
00514 hd = HomeDirectory(0);
00515 if (hd == 0) {
00516 Error(ErrSys, kErrFatal, "RootdExpandPathName: no home directory");
00517 return 0;
00518 }
00519 strcat(cmd, hd);
00520 strcat(cmd, &escPatbuf[1]);
00521 }
00522 } else
00523 strcat(cmd, escPatbuf);
00524
00525 FILE *pf;
00526 if ((pf = ::popen(&cmd[0], "r")) == 0) {
00527 Error(ErrSys, kErrFatal, "RootdExpandPathName: error in popen(%s)", cmd);
00528 return 0;
00529 }
00530
00531
00532 char expPatbuf[kMAXPATHLEN];
00533 int ch, i, cnt = 0;
00534 again:
00535 for (i = 0, ch = fgetc(pf); ch != EOF && ch != ' ' && ch != '\n'; i++, ch = fgetc(pf)) {
00536 expPatbuf[i] = ch;
00537 cnt++;
00538 }
00539
00540 if (cnt == 0 && ch == EOF) goto again;
00541 expPatbuf[cnt] = '\0';
00542
00543
00544 while (ch != EOF) {
00545 ch = fgetc(pf);
00546 if (ch == ' ' || ch == '\t') {
00547 ::pclose(pf);
00548 Error(ErrFatal, kErrFatal, "RootdExpandPathName: expression ambigous");
00549 return 0;
00550 }
00551 }
00552
00553 ::pclose(pf);
00554
00555 return strdup(expPatbuf);
00556 }
00557
00558
00559 int RootdCheckTab(int mode)
00560 {
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580 const char *sfile = gRootdTab.c_str();
00581 int fid, create = 0;
00582
00583 int noupdate = 0;
00584 if (mode < 0) {
00585 mode = 1;
00586 noupdate = 1;
00587 }
00588
00589 again:
00590 if (access(sfile, F_OK) == -1) {
00591 fid = open(sfile, O_CREAT|O_RDWR, 0644);
00592 if (fid != -1) fchmod(fid, 0666);
00593 create = 1;
00594 } else
00595 fid = open(sfile, O_RDWR);
00596
00597 if (fid == -1) {
00598 if (sfile[1] == 'u') {
00599 sfile = gRootdTab.c_str()+4;
00600 goto again;
00601 }
00602 Error(ErrSys, kErrFatal, "RootdCheckTab: error opening %s", sfile);
00603 }
00604
00605
00606 if (lockf(fid, F_LOCK, (off_t)1) == -1) {
00607 if (sfile[1] == 'u' && create) {
00608 close(fid);
00609 remove(sfile);
00610 sfile = gRootdTab.c_str()+4;
00611 goto again;
00612 }
00613 Error(ErrSys, kErrFatal, "RootdCheckTab: error locking %s", sfile);
00614 }
00615 if (gDebug > 2)
00616 ErrorInfo("RootdCheckTab: file %s locked", sfile);
00617
00618 struct stat sbuf;
00619 fstat(fid, &sbuf);
00620 size_t siz = sbuf.st_size;
00621
00622 dev_t device;
00623 ino_t inode;
00624 if (stat(gFile, &sbuf) == -1) {
00625 device = 0;
00626 inode = 0;
00627 } else {
00628 device = sbuf.st_dev;
00629 inode = sbuf.st_ino;
00630 }
00631
00632 char msg[kMAXPATHLEN];
00633 const char *smode = (mode == 1) ? "write" : "read";
00634 int result = 1;
00635
00636 if (siz > 0) {
00637 int changed = 0;
00638 char *fbuf = new char[siz+1];
00639 char *flast = fbuf + siz;
00640
00641 while (read(fid, fbuf, siz) < 0 && GetErrno() == EINTR)
00642 ResetErrno();
00643 fbuf[siz] = 0;
00644
00645 char *n, *s = fbuf;
00646 while ((n = strchr(s, '\n')) && siz > 0) {
00647 n++;
00648 char user[64], gmode[32];
00649 int pid;
00650 unsigned long dev, ino;
00651 sscanf(s, "%s %lu %lu %s %s %d", msg, &dev, &ino, gmode, user, &pid);
00652 if (kill(pid, 0) == -1 && GetErrno() == ESRCH) {
00653 ErrorInfo("RootdCheckTab: remove stale lock (%s %lu %lu %s %s %d)\n",
00654 msg, dev, ino, gmode, user, pid);
00655 if (n >= flast) {
00656 siz = int(s - fbuf);
00657 changed = 1;
00658 break;
00659 } else {
00660 int l = int(flast - n) + 1;
00661 memmove(s, n, l);
00662 siz -= int(n - s);
00663 n = s;
00664 }
00665 flast = fbuf + siz;
00666 changed = 1;
00667 } else if ((dev_t)dev == device && (ino_t)ino == inode) {
00668 if (mode == 1)
00669 result = 0;
00670 else if (!strcmp(gmode, "write"))
00671 result = 0;
00672 }
00673 s = n;
00674 }
00675 if (changed) {
00676 if (ftruncate(fid, 0) == -1)
00677 ErrorInfo("RootdCheckTab: ftruncate failed");
00678 lseek(fid, 0, SEEK_SET);
00679 if (siz > 0) {
00680 while (write(fid, fbuf, siz) < 0 && GetErrno() == EINTR)
00681 ResetErrno();
00682 }
00683 }
00684 delete [] fbuf;
00685 }
00686
00687 if (result && !noupdate) {
00688 unsigned long dev = device;
00689 unsigned long ino = inode;
00690 char *tmsg = msg;
00691 int lmsg = strlen(gFile) + gUser.length() + strlen(smode) + 40;
00692 if (lmsg > kMAXPATHLEN)
00693 tmsg = new char[lmsg];
00694 sprintf(tmsg, "%s %lu %lu %s %s %d\n",
00695 gFile, dev, ino, smode, gUser.c_str(), (int) getpid());
00696 if (write(fid, tmsg, strlen(tmsg)) == -1)
00697 Error(ErrSys, kErrFatal, "RootdCheckTab: error writing %s", sfile);
00698 if (tmsg != msg)
00699 delete[] tmsg;
00700 }
00701
00702
00703 lseek(fid, 0, SEEK_SET);
00704 if (lockf(fid, F_ULOCK, (off_t)1) == -1)
00705 Error(ErrSys, kErrFatal, "RootdCheckTab: error unlocking %s", sfile);
00706 if (gDebug > 2)
00707 ErrorInfo("RootdCheckTab: file %s unlocked", sfile);
00708
00709 close(fid);
00710
00711 return result;
00712 }
00713
00714
00715 void RootdCloseTab(int force = 0)
00716 {
00717
00718
00719
00720
00721
00722
00723 const char *sfile = gRootdTab.c_str();
00724 int fid;
00725
00726 again:
00727 if (access(sfile, F_OK) == -1) {
00728 if (sfile[1] == 'u') {
00729 sfile = gRootdTab.c_str()+4;
00730 goto again;
00731 }
00732 ErrorInfo("RootdCloseTab: file %s does not exist", sfile);
00733 return;
00734 }
00735
00736 fid = open(sfile, O_RDWR);
00737
00738 if (fid == -1) {
00739 ErrorInfo("RootdCloseTab: error opening %s", sfile);
00740 return;
00741 }
00742
00743
00744 if (lockf(fid, F_LOCK, (off_t)1) == -1) {
00745 ErrorInfo("RootdCloseTab: error locking %s", sfile);
00746 return;
00747 }
00748 if (gDebug > 2)
00749 ErrorInfo("RootdCloseTab: file %s locked", sfile);
00750
00751 struct stat sbuf;
00752 fstat(fid, &sbuf);
00753 size_t siz = sbuf.st_size;
00754
00755 stat(gFile, &sbuf);
00756 dev_t device = sbuf.st_dev;
00757 ino_t inode = sbuf.st_ino;
00758
00759 if (siz > 0) {
00760 int changed = 0;
00761 int mypid = getpid();
00762 char *fbuf = new char[siz+1];
00763 char *flast = fbuf + siz;
00764
00765 while (read(fid, fbuf, siz) < 0 && GetErrno() == EINTR)
00766 ResetErrno();
00767 fbuf[siz] = 0;
00768
00769 char *n, *s = fbuf;
00770 while ((n = strchr(s, '\n')) && siz > 0) {
00771 n++;
00772 char msg[kMAXPATHLEN], user[64], gmode[32];
00773 int pid, stale = 0;
00774 unsigned long dev, ino;
00775 sscanf(s, "%s %lu %lu %s %s %d", msg, &dev, &ino, gmode, user, &pid);
00776 if (kill(pid, 0) == -1 && GetErrno() == ESRCH) {
00777 stale = 1;
00778 ErrorInfo("Remove Stale Lock (%s %lu %lu %s %s %d)\n",
00779 msg, dev, ino, gmode, user, pid);
00780 }
00781 if (stale || (!force && mypid == pid) ||
00782 (force && device == (dev_t)dev && inode == (ino_t)ino &&
00783 !strcmp(gUser.c_str(), user))) {
00784 if (n >= flast) {
00785 siz = int(s - fbuf);
00786 changed = 1;
00787 break;
00788 } else {
00789 int l = int(flast - n) + 1;
00790 memmove(s, n, l);
00791 siz -= int(n - s);
00792 n = s;
00793 }
00794 flast = fbuf + siz;
00795 changed = 1;
00796 }
00797 s = n;
00798 }
00799 if (changed) {
00800 if (ftruncate(fid, 0) == -1)
00801 ErrorInfo("RootdCheckTab: ftruncate failed");
00802 lseek(fid, 0, SEEK_SET);
00803 if (siz > 0) {
00804 while (write(fid, fbuf, siz) < 0 && GetErrno() == EINTR)
00805 ResetErrno();
00806 }
00807 }
00808 delete [] fbuf;
00809 }
00810
00811
00812 lseek(fid, 0, SEEK_SET);
00813 if (lockf(fid, F_ULOCK, (off_t)1) == -1) {
00814 ErrorInfo("RootdCloseTab: error unlocking %s", sfile);
00815 return;
00816 }
00817 if (gDebug > 2)
00818 ErrorInfo("RootdCloseTab: file %s unlocked", sfile);
00819
00820 close(fid);
00821 }
00822
00823
00824 int RootdIsOpen()
00825 {
00826 if (gFd == -1) return 0;
00827 return 1;
00828 }
00829
00830
00831 void RootdCloseFtp()
00832 {
00833 if (gDebug > 0)
00834 ErrorInfo("RootdCloseFtp: %d files uploaded, %d files downloaded,"
00835 " rd=%g, wr=%g, rx=%g, tx=%g",
00836 gUploaded, gDownloaded, gBytesRead, gBytesWritten,
00837 NetGetBytesRecv(), NetGetBytesSent());
00838 else
00839 ErrorInfo("Rootd: %d files uploaded, %d files downloaded, rd=%g,"
00840 " wr=%g, rx=%g, tx=%g",
00841 gUploaded, gDownloaded, gBytesRead, gBytesWritten,
00842 NetGetBytesRecv(), NetGetBytesSent());
00843 }
00844
00845
00846 void RootdClose()
00847 {
00848 if (gFtp) {
00849 RootdCloseFtp();
00850 return;
00851 }
00852
00853 if (RootdIsOpen()) {
00854 close(gFd);
00855 gFd = -1;
00856 }
00857
00858 RootdCloseTab();
00859
00860 if (gDebug > 0)
00861 ErrorInfo("RootdClose: file %s closed, rd=%g, wr=%g, rx=%g, tx=%g",
00862 gFile, gBytesRead, gBytesWritten,
00863 NetGetBytesRecv(), NetGetBytesSent());
00864 else
00865 ErrorInfo("Rootd: file %s closed, rd=%g, wr=%g, rx=%g, tx=%g", gFile,
00866 gBytesRead, gBytesWritten,
00867 NetGetBytesRecv(), NetGetBytesSent());
00868 }
00869
00870
00871 void RootdFlush()
00872 {
00873 if (RootdIsOpen() && gWritable) {
00874 #ifndef WIN32
00875 if (fsync(gFd) < 0)
00876 Error(ErrSys, kErrFatal, "RootdFlush: error flushing file %s", gFile);
00877 #endif
00878 }
00879
00880 if (gDebug > 0)
00881 ErrorInfo("RootdFlush: file %s flushed", gFile);
00882 }
00883
00884
00885 void RootdStat()
00886 {
00887
00888 }
00889
00890
00891 void RootdFstat(const char *buf)
00892 {
00893
00894
00895 char msg[256];
00896 int islink = 0;
00897
00898 #if defined(R__SEEK64)
00899 struct stat64 statbuf;
00900 #elif defined(WIN32)
00901 struct _stati64 statbuf;
00902 #else
00903 struct stat statbuf;
00904 #endif
00905
00906 int rc = -1;
00907 if (!buf || !strlen(buf)) {
00908
00909 if (RootdIsOpen()) {
00910 #if defined(R__SEEK64)
00911 rc = fstat64(gFd, &statbuf);
00912 #elif defined(WIN32)
00913 rc = _fstati64(gFd, &statbuf);
00914 #else
00915 rc = fstat(gFd, &statbuf);
00916 #endif
00917 }
00918 } else {
00919
00920 char *epath = (char *)buf;
00921 if (buf[0] == '/' && buf[1] == '/')
00922 epath++;
00923 #if defined(R__SEEK64)
00924 rc = lstat64(epath, &statbuf);
00925 #elif defined(WIN32)
00926 rc = _stati64(epath, &statbuf);
00927 #else
00928 rc = lstat(epath, &statbuf);
00929 #endif
00930 if (rc >= 0) {
00931 islink = S_ISLNK(statbuf.st_mode);
00932 if (islink) {
00933 #if defined(R__SEEK64)
00934 rc = stat64(epath, &statbuf);
00935 #elif defined(WIN32)
00936 rc = _stati64(epath, &statbuf);
00937 #else
00938 rc = stat(epath, &statbuf);
00939 #endif
00940 }
00941 }
00942 }
00943
00944
00945 if (gClientProtocol > 11) {
00946 if (rc >= 0)
00947 sprintf(msg, "%ld %ld %d %d %d %lld %ld %d", (long)statbuf.st_dev,
00948 (long)statbuf.st_ino, statbuf.st_mode, (int)(statbuf.st_uid),
00949 (int)(statbuf.st_gid), (Long64_t)statbuf.st_size, statbuf.st_mtime,
00950 islink);
00951 else
00952 sprintf(msg, "-1 -1 -1 -1 -1 -1 -1 -1");
00953 } else {
00954
00955 if (rc >= 0) {
00956 long id = (statbuf.st_dev << 24) + statbuf.st_ino;
00957 Long64_t size = statbuf.st_size;
00958 long modtime = statbuf.st_mtime;
00959 long flags = 0;
00960 if (statbuf.st_mode & ((S_IEXEC)|(S_IEXEC>>3)|(S_IEXEC>>6)))
00961 flags |= 1;
00962 if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
00963 flags |= 2;
00964 if ((statbuf.st_mode & S_IFMT) != S_IFREG &&
00965 (statbuf.st_mode & S_IFMT) != S_IFDIR)
00966 flags |= 4;
00967 sprintf(msg, "%ld %lld %ld %ld", id, size, flags, modtime);
00968 } else
00969 sprintf(msg, "-1 -1 -1 -1");
00970 }
00971
00972 NetSend(msg, kROOTD_FSTAT);
00973 }
00974
00975
00976 void RootdParallel()
00977 {
00978
00979
00980
00981 int buf[3];
00982 if (NetRecvRaw(buf, sizeof(buf)) < 0)
00983 Error(ErrFatal, kErrFatal, "RootdParallel: error receiving message");
00984
00985 int size = ntohl(buf[1]);
00986 int port = ntohl(buf[2]);
00987
00988 if (gDebug > 0)
00989 ErrorInfo("RootdParallel: port = %d, size = %d", port, size);
00990
00991 if (size > 1)
00992 NetParOpen(port, size);
00993 }
00994
00995
00996 static int SysOpen(const char *pathname, int flags, unsigned int mode)
00997 {
00998
00999
01000 #if defined(R__WINGCC)
01001
01002
01003 return ::open(pathname, flags | O_BINARY, mode);
01004 #elif defined(R__SEEK64)
01005 return ::open64(pathname, flags, mode);
01006 #else
01007 return ::open(pathname, flags, mode);
01008 #endif
01009 }
01010
01011
01012 void RootdOpen(const char *msg)
01013 {
01014
01015
01016
01017 char file[kMAXPATHLEN], option[32];
01018
01019 gBytesRead = gBytesWritten = 0;
01020 NetResetByteCount();
01021
01022 sscanf(msg, "%s %s", file, option);
01023
01024 if (gCastorFlag) {
01025
01026
01027 if (gCastorReqId.length() > 0) {
01028 if (strstr(file, gCastorReqId.c_str()) == 0) {
01029 Error(ErrFatal, kErrNoAccess,
01030 "RootdOpen: Bad CASTOR Request ID: %s rather than %s",
01031 file, gCastorReqId.c_str());
01032 }
01033 }
01034
01035 ErrorInfo("RootdOpen: CASTOR Flag on, file: %s", gCastorFile.c_str());
01036 strncpy(gFile, gCastorFile.c_str(), kMAXPATHLEN-1);
01037 gFile[kMAXPATHLEN-1] = '\0';
01038
01039 } else {
01040
01041 if (gClientProtocol > 14) {
01042 strlcpy(gFile, file, sizeof(gFile));
01043 } else {
01044
01045 if (file[0] == '/')
01046 strlcpy(gFile, &file[1], sizeof(gFile));
01047 else
01048 strlcpy(gFile, file, sizeof(gFile));
01049 }
01050
01051 gFile[strlen(file)] = '\0';
01052 }
01053
01054 strlcpy(gOption, option, sizeof(gOption));
01055
01056 int forceOpen = 0;
01057 if (option[0] == 'f') {
01058 forceOpen = 1;
01059 strlcpy(gOption, &option[1], sizeof(gOption));
01060 }
01061
01062 int forceRead = 0;
01063 if (!strcmp(option, "+read")) {
01064 forceRead = 1;
01065 strlcpy(gOption, &option[1], sizeof(gOption));
01066 }
01067
01068 int create = 0;
01069 if (!strcmp(gOption, "new") || !strcmp(gOption, "create"))
01070 create = 1;
01071 int recreate = strcmp(gOption, "recreate") ? 0 : 1;
01072 int update = strcmp(gOption, "update") ? 0 : 1;
01073 int read = strcmp(gOption, "read") ? 0 : 1;
01074 if (!create && !recreate && !update && !read) {
01075 read = 1;
01076 strlcpy(gOption, "read", sizeof(gOption));
01077 }
01078
01079 if (!read && gReadOnly)
01080 Error(ErrFatal, kErrNoAccess,
01081 "RootdOpen: file %s can only be opened in \"READ\" mode", gFile);
01082
01083 if (!gAnon) {
01084 char *fname;
01085 if ((fname = RootdExpandPathName(gFile))) {
01086 strlcpy(gFile, fname, sizeof(gFile));
01087 free(fname);
01088 } else
01089 Error(ErrFatal, kErrBadFile, "RootdOpen: bad file name %s", gFile);
01090 }
01091
01092 if (forceOpen)
01093 RootdCloseTab(1);
01094
01095 int trunc = 0;
01096 if (recreate) {
01097 if (!RootdCheckTab(-1))
01098 Error(ErrFatal, kErrFileWriteOpen,
01099 "RootdOpen: file %s already opened in read or write mode", gFile);
01100 if (!access(gFile, F_OK))
01101 trunc = O_TRUNC;
01102 else {
01103 recreate = 0;
01104 create = 1;
01105 strlcpy(gOption, "create", sizeof(gOption));
01106 }
01107 }
01108
01109 if (create && !access(gFile, F_OK))
01110 Error(ErrFatal, kErrFileExists, "RootdOpen: file %s already exists", gFile);
01111
01112 int wasupdt = 0;
01113 if (update) {
01114 if (access(gFile, F_OK)) {
01115 update = 0;
01116 create = 1;
01117 wasupdt = 1;
01118 strlcpy(gOption, "create", sizeof(gOption));
01119 }
01120 if (update && access(gFile, W_OK))
01121 Error(ErrFatal, kErrNoAccess,
01122 "RootdOpen: no write permission for file %s", gFile);
01123 }
01124
01125 if (read) {
01126 if (access(gFile, F_OK))
01127 Error(ErrFatal, kErrNoFile,
01128 "RootdOpen: file %s does not exist (errno: 0x%x)", gFile, errno);
01129 if (access(gFile, R_OK))
01130 Error(ErrFatal, kErrNoAccess,
01131 "RootdOpen: no read permission for file %s (errno: 0x%x)", gFile, errno);
01132 }
01133
01134 if (create || recreate || update) {
01135 if (create || recreate) {
01136
01137 #ifndef WIN32
01138 gFd = SysOpen(gFile, O_RDWR | O_CREAT | trunc, 0644);
01139 #else
01140 gFd = SysOpen(gFile, O_RDWR | O_CREAT | O_BINARY | trunc, S_IREAD | S_IWRITE);
01141 #endif
01142 if (gFd != -1)
01143 close(gFd);
01144 gFd = -1;
01145 }
01146 #ifndef WIN32
01147 gFd = SysOpen(gFile, O_RDWR, 0644);
01148 #else
01149 gFd = SysOpen(gFile, O_RDWR | O_BINARY, S_IREAD | S_IWRITE);
01150 #endif
01151 if (gFd == -1)
01152 Error(ErrSys, kErrFileOpen, "RootdOpen: error opening file %s in write mode", gFile);
01153
01154 if (!RootdCheckTab(1)) {
01155 close(gFd);
01156 Error(ErrFatal, kErrFileWriteOpen, "RootdOpen: file %s already opened in read or write mode", gFile);
01157 }
01158
01159 gWritable = wasupdt ? 2 : 1;
01160
01161 } else {
01162 #ifndef WIN32
01163 gFd = SysOpen(gFile, O_RDONLY, 0644);
01164 #else
01165 gFd = SysOpen(gFile, O_RDONLY | O_BINARY, S_IREAD | S_IWRITE);
01166 #endif
01167 if (gFd == -1)
01168 Error(ErrSys, kErrFileOpen, "RootdOpen: error opening file %s in read mode", gFile);
01169
01170 if (!RootdCheckTab(0)) {
01171 if (!forceRead) {
01172 close(gFd);
01173 Error(ErrFatal, kErrFileReadOpen, "RootdOpen: file %s already opened in write mode", gFile);
01174 }
01175 }
01176
01177 gWritable = 0;
01178
01179 }
01180
01181 NetSend(gWritable, kROOTD_OPEN);
01182
01183 struct stat sbuf;
01184 fstat(gFd, &sbuf);
01185 unsigned long dev = sbuf.st_dev;
01186 unsigned long ino = sbuf.st_ino;
01187
01188 if (gDebug > 0)
01189 ErrorInfo("RootdOpen: file %s opened in mode %s", gFile, gOption);
01190 else {
01191 if (gAnon)
01192 ErrorInfo("RootdOpen: file %s (dev=%lu,inode=%lu,%s) opened by %s/%s",
01193 gFile, dev, ino, gOption, gUser.c_str(), gPasswd.c_str());
01194 else
01195 ErrorInfo("RootdOpen: file %s (dev=%lu,inode=%lu,%s) opened by %s",
01196 gFile, dev, ino, gOption, gUser.c_str());
01197 }
01198 }
01199
01200
01201 void RootdPut(const char *msg)
01202 {
01203
01204
01205
01206 Long64_t offset;
01207 int len;
01208
01209 sscanf(msg, "%lld %d", &offset, &len);
01210
01211 char *buf = new char[len];
01212 NetRecvRaw(buf, len);
01213
01214 if (!RootdIsOpen() || !gWritable)
01215 Error(ErrFatal, kErrNoAccess, "RootdPut: file %s not opened in write mode", gFile);
01216
01217 #if defined (R__SEEK64)
01218 if (lseek64(gFd, offset, SEEK_SET) < 0)
01219 #elif defined(WIN32)
01220 if (_lseeki64(gFd, offset, SEEK_SET) < 0)
01221 #else
01222 if (lseek(gFd, offset, SEEK_SET) < 0)
01223 #endif
01224 Error(ErrSys, kErrFilePut, "RootdPut: cannot seek to position %lld in file %s", offset, gFile);
01225
01226 ssize_t siz;
01227 while ((siz = write(gFd, buf, len)) < 0 && GetErrno() == EINTR)
01228 ResetErrno();
01229
01230 if (siz < 0)
01231 Error(ErrSys, kErrFilePut, "RootdPut: error writing to file %s", gFile);
01232
01233 if (siz != len)
01234 Error(ErrFatal, kErrFilePut, "RootdPut: error writing all requested bytes to file %s, wrote %d of %d",
01235 gFile, siz, len);
01236
01237 NetSend(0, kROOTD_PUT);
01238
01239 delete [] buf;
01240
01241 gBytesWritten += len;
01242
01243 if (gDebug > 0)
01244 ErrorInfo("RootdPut: written %d bytes starting at %lld to file %s",
01245 len, offset, gFile);
01246 }
01247
01248
01249 void RootdGet(const char *msg)
01250 {
01251
01252
01253
01254 Long64_t offset;
01255 int len;
01256
01257 sscanf(msg, "%lld %d", &offset, &len);
01258
01259 char *buf = new char[len];
01260
01261 if (!RootdIsOpen())
01262 Error(ErrFatal, kErrNoAccess, "RootdGet: file %s not open", gFile);
01263
01264 #if defined (R__SEEK64)
01265 if (lseek64(gFd, offset, SEEK_SET) < 0)
01266 #elif defined(WIN32)
01267 if (_lseeki64(gFd, offset, SEEK_SET) < 0)
01268 #else
01269 if (lseek(gFd, offset, SEEK_SET) < 0)
01270 #endif
01271 Error(ErrSys, kErrFileGet, "RootdGet: cannot seek to position %lld in"
01272 " file %s", offset, gFile);
01273
01274 ssize_t siz;
01275 while ((siz = read(gFd, buf, len)) < 0 && GetErrno() == EINTR)
01276 ResetErrno();
01277
01278 if (siz < 0)
01279 Error(ErrSys, kErrFileGet, "RootdGet: error reading from file %s", gFile);
01280
01281 if (siz != len)
01282 Error(ErrFatal, kErrFileGet, "RootdGet: error reading all requested bytes"
01283 " from file %s, got %d of %d",gFile, siz, len);
01284
01285 NetSend(0, kROOTD_GET);
01286
01287 NetSendRaw(buf, len);
01288
01289 delete [] buf;
01290
01291 gBytesRead += len;
01292
01293 if (gDebug > 0)
01294 ErrorInfo("RootdGet: read %d bytes starting at %lld from file %s",
01295 len, offset, gFile);
01296 }
01297
01298
01299 void RootdGets(const char *msg)
01300 {
01301
01302
01303
01304
01305
01306 if (!RootdIsOpen())
01307 Error(ErrFatal, kErrNoAccess, "RootdGets: file %s not open", gFile);
01308
01309 Int_t nbuf;
01310 Int_t len;
01311 Int_t npar;
01312 Int_t size;
01313 Int_t maxTransz;
01314
01315 npar = sscanf(msg, "%d %d %d", &nbuf, &len, &maxTransz);
01316
01317 Long64_t *offsets = new Long64_t[nbuf];
01318 Int_t *lens = new Int_t[nbuf];
01319 char *buf_in = new char[len+1];
01320
01321 NetRecvRaw(buf_in, len);
01322 buf_in[len] = '\0';
01323
01324 char *ptr = buf_in;
01325 size = 0;
01326 for(Int_t i = 0 ; i < nbuf ; i++) {
01327 sscanf(ptr, "%llu-%d/", &offsets[i], &lens[i]);
01328 ptr = strchr(ptr, '/') + 1;
01329 size += lens[i];
01330 }
01331
01332
01333
01334 if( npar == 2 )
01335 maxTransz = size;
01336
01337
01338 NetSend(0, kROOTD_GETS);
01339
01340 char *buf_out = new char[maxTransz];
01341 char *buf_send = new char[maxTransz];
01342 Int_t actual_pos = 0;
01343 Int_t buf_pos = 0;
01344 ssize_t siz = 0;
01345
01346 for (Int_t i = 0; i < nbuf; i++) {
01347 Long64_t left = size - actual_pos;
01348 if (left > maxTransz)
01349 left = maxTransz;
01350
01351 Int_t pos = 0;
01352 while ( pos < lens[i] ) {
01353 #if defined (R__SEEK64)
01354 if (lseek64(gFd, offsets[i] + pos, SEEK_SET) < 0)
01355 #elif defined(WIN32)
01356 if (_lseeki64(gFd, offsets[i] + pos, SEEK_SET) < 0)
01357 #else
01358 if (lseek(gFd, offsets[i] + pos, SEEK_SET) < 0)
01359 #endif
01360 Error(ErrSys, kErrFileGet, "RootdGets: cannot seek to position %lld in"
01361 " file %s", offsets[i], gFile);
01362
01363 Int_t readsz = lens[i] - pos;
01364 if( readsz > ( left - buf_pos) )
01365 readsz = left - buf_pos;
01366
01367 while ((siz = read(gFd, buf_out + buf_pos, readsz)) < 0 && GetErrno() == EINTR)
01368 ResetErrno();
01369
01370 if (siz != readsz)
01371 goto end;
01372
01373 pos += readsz;
01374 buf_pos += readsz;
01375 if ( buf_pos == left ) {
01376 if (gDebug > 0 )
01377 ErrorInfo("RootdGets: Sending %d bytes", left);
01378
01379
01380 char *buf_tmp = buf_out;
01381 buf_out = buf_send;
01382 buf_send = buf_tmp;
01383
01384 NetSendRaw(buf_send, left);
01385 actual_pos += left;
01386 buf_pos = 0;
01387
01388 if ( left > (size - actual_pos) )
01389 left = size - actual_pos;
01390 }
01391 }
01392 }
01393
01394 end:
01395 if (siz < 0)
01396 Error(ErrSys, kErrFileGet, "RootdGets: error reading from file %s", gFile);
01397
01398 if (actual_pos != size)
01399 Error(ErrFatal, kErrFileGet, "RootdGets: error reading all requested bytes"
01400 " from file %s, got %d of %d",gFile, actual_pos, size);
01401
01402 delete [] buf_in;
01403 delete [] buf_out;
01404 delete [] buf_send;
01405 delete [] lens;
01406 delete [] offsets;
01407
01408 gBytesRead += actual_pos;
01409
01410 if (gDebug > 0)
01411 ErrorInfo("RootdGets: read %d bytes from file %s",
01412 actual_pos, gFile);
01413 }
01414
01415
01416 void RootdPutFile(const char *msg)
01417 {
01418
01419
01420 char file[kMAXPATHLEN];
01421 Long64_t size, restartat;
01422 int blocksize, mode, forceopen = 0;
01423
01424 gFtp = 1;
01425
01426 sscanf(msg, "%s %d %d %lld %lld", file, &blocksize, &mode, &size, &restartat);
01427
01428 if (file[0] == '-') {
01429 forceopen = 1;
01430 strlcpy(gFile, file+1, sizeof(gFile));
01431 } else
01432 strlcpy(gFile, file, sizeof(gFile));
01433
01434
01435 struct stat st;
01436 if (!stat(gFile, &st)) {
01437 if (gAnon) {
01438 Error(Err, kErrFileExists, "RootdPutFile: anonymous users may not overwrite existing file %s", gFile);
01439 return;
01440 }
01441 } else if (GetErrno() != ENOENT) {
01442 Error(Err, kErrFatal, "RootdPutFile: can't check for file presence");
01443 return;
01444 }
01445
01446
01447 if (restartat || forceopen)
01448 RootdCloseTab(1);
01449
01450
01451 int fd;
01452 if (!restartat) {
01453
01454
01455 #ifndef WIN32
01456 fd = SysOpen(gFile, O_RDWR | O_CREAT, 0600);
01457 #else
01458 fd = SysOpen(gFile, O_RDWR | O_CREAT | O_BINARY, S_IREAD | S_IWRITE);
01459 #endif
01460 if (fd < 0) {
01461 Error(Err, kErrFileOpen, "RootdPutFile: cannot open file %s", gFile);
01462 return;
01463 }
01464
01465 close(fd);
01466
01467
01468
01469 if (!RootdCheckTab(1)) {
01470 Error(Err, kErrFileWriteOpen, "RootdPutFile: file %s already opened in read or write mode", gFile);
01471 return;
01472 }
01473
01474 #ifndef WIN32
01475 fd = SysOpen(gFile, O_CREAT | O_TRUNC | O_WRONLY, 0600);
01476 #else
01477 if (mode == kBinary)
01478 fd = SysOpen(gFile, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY,
01479 S_IREAD | S_IWRITE);
01480 else
01481 fd = SysOpen(gFile, O_CREAT | O_TRUNC | O_WRONLY,
01482 S_IREAD | S_IWRITE);
01483 #endif
01484 } else {
01485 #ifndef WIN32
01486 fd = SysOpen(gFile, O_WRONLY, 0600);
01487 #else
01488 if (mode == kBinary)
01489 fd = SysOpen(gFile, O_WRONLY | O_BINARY, S_IREAD | S_IWRITE);
01490 else
01491 fd = SysOpen(gFile, O_WRONLY, S_IREAD | S_IWRITE);
01492 #endif
01493 if (fd < 0) {
01494 Error(Err, kErrFileOpen, "RootdPutFile: cannot open file %s", gFile);
01495 return;
01496 }
01497 if (!RootdCheckTab(1)) {
01498 close(fd);
01499 Error(Err, kErrFileWriteOpen, "RootdPutFile: file %s already opened in read or write mode", gFile);
01500 return;
01501 }
01502 }
01503
01504
01505 if (strcmp(gFile, "/dev/null")) {
01506 struct statfs statfsbuf;
01507 #if defined(__sgi) || (defined(__sun) && !defined(linux))
01508 if (fstatfs(fd, &statfsbuf, sizeof(struct statfs), 0) == 0) {
01509 Long64_t space = (Long64_t)statfsbuf.f_bsize * (Long64_t)statfsbuf.f_bfree;
01510 #else
01511 if (fstatfs(fd, &statfsbuf) == 0) {
01512 Long64_t space = (Long64_t)statfsbuf.f_bsize * (Long64_t)statfsbuf.f_bavail;
01513 #endif
01514 if (space < size - restartat) {
01515 Error(Err, kErrNoSpace, "RootdPutFile: not enough space to store file %s", gFile);
01516 close(fd);
01517 return;
01518 }
01519 }
01520 }
01521
01522
01523 if (restartat) {
01524 #if defined(R__SEEK64)
01525 if (lseek64(fd, restartat, SEEK_SET) < 0) {
01526 #elif defined(WIN32)
01527 if (_lseeki64(fd, restartat, SEEK_SET) < 0) {
01528 #else
01529 if (lseek(fd, restartat, SEEK_SET) < 0) {
01530 #endif
01531 Error(Err, kErrRestartSeek, "RootdPutFile: cannot seek to position %lld in file %s",
01532 restartat, gFile);
01533 close(fd);
01534 return;
01535 }
01536 }
01537
01538
01539 NetSend(0, kROOTD_PUTFILE);
01540
01541 struct timeval started, ended;
01542 gettimeofday(&started, 0);
01543
01544 char *buf = new char[blocksize];
01545 char *buf2 = 0;
01546 if (mode == 1)
01547 buf2 = new char[blocksize];
01548
01549 Long64_t pos = restartat & ~(blocksize-1);
01550 int skip = restartat - pos;
01551
01552 while (pos < size) {
01553 Long64_t left = Long64_t(size - pos);
01554 if (left > blocksize)
01555 left = blocksize;
01556
01557 NetRecvRaw(buf, int(left-skip));
01558
01559 int n = int(left-skip);
01560
01561
01562 ssize_t siz;
01563 if (mode == kAscii) {
01564 int i = 0, j = 0;
01565 while (i < n) {
01566 if (buf[i] == '\r')
01567 i++;
01568 else
01569 buf2[j++] = buf[i++];
01570 }
01571 n = j;
01572 while ((siz = write(fd, buf2, n)) < 0 && GetErrno() == EINTR)
01573 ResetErrno();
01574 } else {
01575 while ((siz = write(fd, buf, n)) < 0 && GetErrno() == EINTR)
01576 ResetErrno();
01577 }
01578
01579 if (siz < 0)
01580 Error(ErrSys, kErrFilePut, "RootdPutFile: error writing to file %s", gFile);
01581
01582 if (siz != n)
01583 Error(ErrFatal, kErrFilePut, "RootdPutFile: error writing all requested bytes to file %s, wrote %d of %d",
01584 gFile, siz, int(left-skip));
01585
01586 gBytesWritten += n;
01587
01588 pos += left;
01589 skip = 0;
01590 }
01591
01592 gettimeofday(&ended, 0);
01593
01594
01595 NetSend(0, kROOTD_PUTFILE);
01596
01597 delete [] buf; delete [] buf2;
01598
01599 fchmod(fd, 0644);
01600
01601 close(fd);
01602
01603 RootdCloseTab();
01604
01605 gUploaded++;
01606
01607 double speed, t;
01608 t = (ended.tv_sec + ended.tv_usec / 1000000.0) -
01609 (started.tv_sec + started.tv_usec / 1000000.0);
01610 if (t > 0)
01611 speed = double(size - restartat) / t;
01612 else
01613 speed = 0.0;
01614 if (speed > 524288)
01615 ErrorInfo("RootdPutFile: uploaded file %s (%lld bytes, %.3f seconds, "
01616 "%.2f Mbytes/s)", gFile, size, t, speed / 1048576);
01617 else if (speed > 512)
01618 ErrorInfo("RootdPutFile: uploaded file %s (%lld bytes, %.3f seconds, "
01619 "%.2f Kbytes/s)", gFile, size, t, speed / 1024);
01620 else
01621 ErrorInfo("RootdPutFile: uploaded file %s (%lld bytes, %.3f seconds, "
01622 "%.2f bytes/s)", gFile, size, t, speed);
01623 }
01624
01625
01626 void RootdGetFile(const char *msg)
01627 {
01628
01629
01630 char file[kMAXPATHLEN];
01631 Long64_t restartat;
01632 int blocksize, mode, forceopen = 0;
01633
01634 gFtp = 1;
01635
01636 sscanf(msg, "%s %d %d %lld", file, &blocksize, &mode, &restartat);
01637
01638 if (file[0] == '-') {
01639 forceopen = 1;
01640 strlcpy(gFile, file+1, sizeof(gFile));
01641 } else
01642 strlcpy(gFile, file, sizeof(gFile));
01643
01644
01645 if (forceopen)
01646 RootdCloseTab(1);
01647
01648
01649 #if defined(WIN32) || defined(R__WINGCC)
01650 int fd = SysOpen(gFile, O_RDONLY | O_BINARY, S_IREAD | S_IWRITE);
01651 #else
01652 int fd = SysOpen(gFile, O_RDONLY, 0600);
01653 #endif
01654 if (fd < 0) {
01655 Error(Err, kErrFileOpen, "RootdGetFile: cannot open file %s", gFile);
01656 return;
01657 }
01658
01659
01660
01661 if (!RootdCheckTab(0)) {
01662 close(fd);
01663 Error(Err, kErrFileOpen, "RootdGetFile: file %s is already open in write mode", gFile);
01664 return;
01665 }
01666
01667 #if defined(R__SEEK64)
01668 struct stat64 st;
01669 if (fstat64(fd, &st)) {
01670 #elif defined(WIN32)
01671 struct _stati64 st;
01672 if (_fstati64(fd, &st)) {
01673 #else
01674 struct stat st;
01675 if (fstat(fd, &st)) {
01676 #endif
01677 Error(Err, kErrFatal, "RootdGetFile: cannot get size of file %s", gFile);
01678 close(fd);
01679 return;
01680 }
01681 Long64_t size = st.st_size;
01682
01683 if (!S_ISREG(st.st_mode)) {
01684 Error(Err, kErrBadFile, "RoodGetFile: not a regular file %s", gFile);
01685 close(fd);
01686 return;
01687 }
01688
01689
01690 if (restartat && (restartat >= size))
01691 restartat = 0;
01692
01693
01694 NetSend(0, kROOTD_GETFILE);
01695
01696 char mess[128];
01697 SPrintf(mess, 128, "%lld", size);
01698 NetSend(mess, kROOTD_GETFILE);
01699
01700 struct timeval started, ended;
01701 gettimeofday(&started, 0);
01702
01703 Long64_t pos = restartat & ~(blocksize-1);
01704 int skip = int(restartat - pos);
01705
01706 #ifndef HAVE_MMAP
01707 char *buf = new char[blocksize];
01708 #if defined(R__SEEK64)
01709 lseek64(fd, pos, SEEK_SET);
01710 #elif defined(WIN32)
01711 _lseeki64(fd, pos, SEEK_SET);
01712 #else
01713 lseek(fd, pos, SEEK_SET);
01714 #endif
01715 #endif
01716
01717 while (pos < size) {
01718 Long64_t left = size - pos;
01719 if (left > blocksize)
01720 left = blocksize;
01721 #ifdef HAVE_MMAP
01722 #if defined(R__SEEK64)
01723 char *buf = (char*) mmap64(0, left, PROT_READ, MAP_FILE | MAP_SHARED, fd, pos);
01724 #else
01725 char *buf = (char*) mmap(0, left, PROT_READ, MAP_FILE | MAP_SHARED, fd, pos);
01726 #endif
01727 if (buf == (char *) -1)
01728 Error(ErrFatal, kErrFileGet, "RootdGetFile: mmap of file %s failed", gFile);
01729 #else
01730 int siz;
01731 while ((siz = read(fd, buf, (int)left)) < 0 && GetErrno() == EINTR)
01732 ResetErrno();
01733 if (siz < 0 || siz != left)
01734 Error(ErrFatal, kErrFileGet, "RootdGetFile: error reading from file %s", gFile);
01735 #endif
01736
01737 NetSendRaw(buf+skip, int(left-skip));
01738
01739 gBytesRead += left-skip;
01740
01741 pos += left;
01742 skip = 0;
01743
01744 #ifdef HAVE_MMAP
01745 munmap(buf, left);
01746 #endif
01747 }
01748
01749 gettimeofday(&ended, 0);
01750
01751 #ifndef HAVE_MMAP
01752 delete [] buf;
01753 #endif
01754
01755 close(fd);
01756
01757 RootdCloseTab();
01758
01759 gDownloaded++;
01760
01761 double speed, t;
01762 t = (ended.tv_sec + ended.tv_usec / 1000000.0) -
01763 (started.tv_sec + started.tv_usec / 1000000.0);
01764 if (t > 0)
01765 speed = double(size - restartat) / t;
01766 else
01767 speed = 0.0;
01768 if (speed > 524288)
01769 ErrorInfo("RootdGetFile: downloaded file %s (%lld bytes, %.3f seconds, "
01770 "%.2f Mbytes/s)", gFile, size, t, speed / 1048576);
01771 else if (speed > 512)
01772 ErrorInfo("RootdGetFile: downloaded file %s (%lld bytes, %.3f seconds, "
01773 "%.2f Kbytes/s)", gFile, size, t, speed / 1024);
01774 else
01775 ErrorInfo("RootdGetFile: downloaded file %s (%lld bytes, %.3f seconds, "
01776 "%.2f bytes/s)", gFile, size, t, speed);
01777 }
01778
01779
01780 void RootdChdir(const char *dir)
01781 {
01782
01783
01784 const int kMAXBUFLEN = kMAXPATHLEN + 256;
01785 char buffer[kMAXBUFLEN];
01786
01787 if (dir && *dir == '~') {
01788 struct passwd *pw;
01789 int i = 0;
01790 const char *p = dir;
01791
01792 p++;
01793 while (*p && *p != '/')
01794 buffer[i++] = *p++;
01795 buffer[i] = 0;
01796
01797 if ((pw = getpwnam(i ? buffer : gUser.c_str())))
01798 SPrintf(buffer, kMAXBUFLEN, "%s%s", pw->pw_dir, p);
01799 else
01800 *buffer = 0;
01801 } else
01802 *buffer = 0;
01803
01804 if (chdir(*buffer ? buffer : (dir && *dir ? dir : "/")) == -1) {
01805 SPrintf(buffer,kMAXBUFLEN,"cannot change directory to %s",dir);
01806 Perror(buffer,kMAXBUFLEN);
01807 NetSend(buffer, kROOTD_CHDIR);
01808 return;
01809 } else {
01810 FILE *msg;
01811
01812 if ((msg = fopen(".message", "r"))) {
01813 int len = fread(buffer, 1, kMAXPATHLEN, msg);
01814 fclose(msg);
01815 if (len > 0 && len < 1024) {
01816 buffer[len] = 0;
01817 NetSend(buffer, kMESS_STRING);
01818 }
01819 }
01820
01821 if (!getcwd(buffer, kMAXPATHLEN)) {
01822 if (dir && *dir == '/')
01823 SPrintf(buffer, kMAXBUFLEN, "%s", dir);
01824 }
01825 NetSend(buffer, kROOTD_CHDIR);
01826 }
01827 }
01828
01829
01830 void RootdAccess(const char *buf)
01831 {
01832
01833
01834 char buffer[kMAXPATHLEN];
01835 char path[kMAXPATHLEN];
01836 int mode;
01837
01838 int nw = 0;
01839 if (buf)
01840 nw = sscanf(buf,"%s %d",path,&mode);
01841
01842 if (nw >= 2) {
01843
01844 char *epath = &path[0];
01845 if (path[0] == '/' && path[1] == '/')
01846 epath = &path[1];
01847
01848 if (access(epath, mode) == -1) {
01849 SPrintf(buffer,kMAXPATHLEN,"cannot stat %s",epath);
01850 Perror(buffer);
01851 ErrorInfo("RootdAccess: %s", buffer);
01852 } else
01853 SPrintf(buffer,kMAXPATHLEN,"OK");
01854
01855 } else {
01856 SPrintf(buffer,kMAXPATHLEN,"bad input format %s",buf);
01857 ErrorInfo("RootdAccess: %s", buffer);
01858 }
01859
01860 NetSend(buffer, kROOTD_ACCESS);
01861 }
01862
01863
01864
01865 void RootdFreeDir()
01866 {
01867
01868
01869 char buffer[kMAXPATHLEN];
01870
01871 if (!gRDDirectory) {
01872 SPrintf(buffer,kMAXPATHLEN,"no directory open");
01873 ErrorInfo("RootdFreeDir: %s", buffer);
01874 } else if (closedir(gRDDirectory) == -1) {
01875 SPrintf(buffer,kMAXPATHLEN,"cannot free open directory");
01876 Perror(buffer);
01877 ErrorInfo("RootdFreeDir: %s", buffer);
01878 } else
01879 SPrintf(buffer,kMAXPATHLEN,"open directory freed");
01880
01881 NetSend(buffer, kROOTD_FREEDIR);
01882 }
01883
01884
01885 void RootdGetDirEntry()
01886 {
01887
01888
01889 char buffer[kMAXPATHLEN];
01890 struct dirent *dp = 0;
01891
01892 if (!gRDDirectory) {
01893 SPrintf(buffer,kMAXPATHLEN,"no directory open");
01894 ErrorInfo("RootdGetDirEntry: %s", buffer);
01895 } else if ((dp = readdir(gRDDirectory)) == 0) {
01896 if (GetErrno() == EBADF) {
01897 SPrintf(buffer,kMAXPATHLEN,"cannot read open directory");
01898 Perror(buffer);
01899 ErrorInfo("RootdGetDirEntry: %s", buffer);
01900 } else
01901 SPrintf(buffer,kMAXPATHLEN,"no more entries");
01902 } else {
01903 SPrintf(buffer,kMAXPATHLEN,"OK:%s",dp->d_name);
01904 }
01905
01906 NetSend(buffer, kROOTD_DIRENTRY);
01907 }
01908
01909
01910 void RootdOpenDir(const char *dir)
01911 {
01912
01913
01914 char buffer[kMAXPATHLEN];
01915
01916 char *edir = (char *)dir;
01917 if (dir[0] == '/' && dir[1] == '/')
01918 edir++;
01919
01920 if ((gRDDirectory = opendir(edir)) == 0) {
01921 SPrintf(buffer,kMAXPATHLEN,"cannot open directory %s",edir);
01922 Perror(buffer);
01923 ErrorInfo("RootdOpenDir: %s", buffer);
01924 } else
01925 SPrintf(buffer,kMAXPATHLEN,"OK: directory %s open",edir);
01926
01927 NetSend(buffer, kROOTD_OPENDIR);
01928 }
01929
01930
01931 void RootdMkdir(const char *fdir)
01932 {
01933
01934
01935 char buffer[kMAXPATHLEN];
01936
01937 char *dir = (char *)fdir;
01938 if (fdir[0] == '/' && fdir[1] == '/')
01939 dir++;
01940
01941 if (gAnon) {
01942 SPrintf(buffer,kMAXPATHLEN,
01943 "anonymous users may not create directories");
01944 ErrorInfo("RootdMkdir: %s", buffer);
01945 } else if (mkdir(dir, 0755) < 0) {
01946 SPrintf(buffer,kMAXPATHLEN,"cannot create directory %s",dir);
01947 Perror(buffer);
01948 ErrorInfo("RootdMkdir: %s", buffer);
01949 } else
01950 SPrintf(buffer,kMAXPATHLEN,"OK: created directory %s",dir);
01951
01952 NetSend(buffer, kROOTD_MKDIR);
01953 }
01954
01955
01956 void RootdRmdir(const char *fdir)
01957 {
01958
01959
01960 char buffer[kMAXPATHLEN];
01961
01962 char *dir = (char *)fdir;
01963 if (fdir[0] == '/' && fdir[1] == '/')
01964 dir++;
01965
01966 if (gAnon) {
01967 SPrintf(buffer,kMAXPATHLEN,
01968 "anonymous users may not delete directories");
01969 ErrorInfo("RootdRmdir: %s", buffer);
01970 } else if (rmdir(dir) < 0) {
01971 SPrintf(buffer, kMAXPATHLEN, "cannot delete directory %s", dir);
01972 Perror(buffer);
01973 ErrorInfo("RootdRmdir: %s", buffer);
01974 } else
01975 SPrintf(buffer, kMAXPATHLEN, "deleted directory %s", dir);
01976
01977 NetSend(buffer, kROOTD_RMDIR);
01978 }
01979
01980
01981 void RootdLsdir(const char *cmd)
01982 {
01983
01984
01985 char buffer[kMAXPATHLEN];
01986
01987
01988 if (gAnon) {
01989 if (strlen(cmd) < 2 || strncmp(cmd, "ls", 2))
01990 SPrintf(buffer, kMAXPATHLEN, "ls %s", cmd);
01991 else
01992 SPrintf(buffer, kMAXPATHLEN, "%s", cmd);
01993 } else {
01994 if (strlen(cmd) < 2 || strncmp(cmd, "ls", 2))
01995 SPrintf(buffer, kMAXPATHLEN, "ls %s 2>/dev/null", cmd);
01996 else
01997 SPrintf(buffer, kMAXPATHLEN, "%s 2>/dev/null", cmd);
01998 }
01999
02000 FILE *pf;
02001 if ((pf = popen(buffer, "r")) == 0) {
02002 SPrintf(buffer,kMAXPATHLEN, "error in popen");
02003 Perror(buffer);
02004 NetSend(buffer, kROOTD_LSDIR);
02005 ErrorInfo("RootdLsdir: %s", buffer);
02006 return;
02007 }
02008
02009
02010 int ch, i = 0, cnt = 0;
02011
02012 for (ch = fgetc(pf); ch != EOF; ch = fgetc(pf)) {
02013 buffer[i++] = ch;
02014 cnt++;
02015 if (i == kMAXPATHLEN-1) {
02016 buffer[i] = 0;
02017 NetSend(buffer, kMESS_STRING);
02018 i = 0;
02019 }
02020 }
02021
02022
02023
02024 pclose(pf);
02025
02026 buffer[i] = 0;
02027 NetSend(buffer, kROOTD_LSDIR);
02028 }
02029
02030
02031 void RootdPwd()
02032 {
02033
02034
02035 char buffer[kMAXPATHLEN];
02036
02037 if (!getcwd(buffer, kMAXPATHLEN)) {
02038 SPrintf(buffer, kMAXPATHLEN, "current directory not readable");
02039 Perror(buffer);
02040 ErrorInfo("RootdPwd: %s", buffer);
02041 }
02042
02043 NetSend(buffer, kROOTD_PWD);
02044 }
02045
02046
02047 void RootdMv(const char *msg)
02048 {
02049
02050
02051 char file1[kMAXPATHLEN], file2[kMAXPATHLEN], buffer[kMAXPATHLEN];
02052 sscanf(msg, "%s %s", file1, file2);
02053
02054 if (gAnon) {
02055 SPrintf(buffer, kMAXPATHLEN, "anonymous users may not rename files");
02056 ErrorInfo("RootdMv: %s", buffer);
02057 } else if (rename(file1, file2) < 0) {
02058 SPrintf(buffer, kMAXPATHLEN, "cannot rename file %s to %s",
02059 file1, file2);
02060 Perror(buffer);
02061 ErrorInfo("RootdMv: %s", buffer);
02062 } else
02063 SPrintf(buffer, kMAXPATHLEN, "renamed file %s to %s",
02064 file1, file2);
02065
02066 NetSend(buffer, kROOTD_MV);
02067 }
02068
02069
02070 void RootdRm(const char *file)
02071 {
02072
02073
02074 char buffer[kMAXPATHLEN];
02075
02076 if (gAnon) {
02077 SPrintf(buffer, kMAXPATHLEN, "anonymous users may not delete files");
02078 ErrorInfo("RootdRm: %s", buffer);
02079 } else if (unlink(file) < 0) {
02080 SPrintf(buffer, kMAXPATHLEN, "cannot unlink file %s", file);
02081 Perror(buffer);
02082 ErrorInfo("RootdRm: %s", buffer);
02083 } else
02084 SPrintf(buffer, kMAXPATHLEN, "removed file %s", file);
02085
02086 NetSend(buffer, kROOTD_RM);
02087 }
02088
02089
02090 void RootdChmod(const char *msg)
02091 {
02092
02093
02094 char file[kMAXPATHLEN], buffer[kMAXPATHLEN];
02095 int mode;
02096
02097 sscanf(msg, "%s %d", file, &mode);
02098
02099 if (gAnon) {
02100 SPrintf(buffer, kMAXPATHLEN,
02101 "anonymous users may not change file permissions");
02102 ErrorInfo("RootdChmod: %s", buffer);
02103 } else if (chmod(file, mode) < 0) {
02104 SPrintf(buffer, kMAXPATHLEN, "cannot chmod file %s to 0%o", file, mode);
02105 Perror(buffer);
02106 ErrorInfo("RootdChmod: %s", buffer);
02107 } else
02108 SPrintf(buffer, kMAXPATHLEN, "changed permission of file %s to 0%o",
02109 file, mode);
02110
02111 NetSend(buffer, kROOTD_CHMOD);
02112 }
02113
02114
02115 static void RootdTerm(int)
02116 {
02117
02118
02119 ErrorInfo("RootdTerm: rootd.cxx: got a SIGTERM/SIGINT");
02120
02121 RpdAuthCleanup(0,0);
02122
02123 NetClose();
02124
02125 exit(0);
02126 }
02127
02128
02129 void RootdLoop()
02130 {
02131
02132
02133 char recvbuf[kMAXRECVBUF];
02134 EMessageTypes kind;
02135
02136
02137 #ifdef R__ROOTDDBG
02138 int debug = 1;
02139 while (debug)
02140 ;
02141 #endif
02142
02143
02144
02145 if (gClientProtocol > 9)
02146 RootdParallel();
02147
02148
02149 while (1) {
02150
02151 if (NetRecv(recvbuf, kMAXRECVBUF, kind) < 0)
02152 Error(ErrFatal, kErrFatal, "RootdLoop: error receiving message");
02153
02154 if (gDebug > 2 && kind != kROOTD_PASS)
02155 ErrorInfo("RootdLoop: kind:%d -- buf:'%s' (len:%d)",
02156 kind, recvbuf, strlen(recvbuf));
02157
02158 switch (kind) {
02159 case kROOTD_OPEN:
02160 RootdOpen(recvbuf);
02161 break;
02162 case kROOTD_PUT:
02163 RootdPut(recvbuf);
02164 break;
02165 case kROOTD_GET:
02166 RootdGet(recvbuf);
02167 break;
02168 case kROOTD_GETS:
02169 RootdGets(recvbuf);
02170 break;
02171 case kROOTD_FLUSH:
02172 RootdFlush();
02173 break;
02174 case kROOTD_CLOSE:
02175 RootdClose();
02176 if (gClientProtocol < 7)
02177 return;
02178 break;
02179 case kROOTD_FSTAT:
02180 RootdFstat(recvbuf);
02181 break;
02182 case kROOTD_STAT:
02183 RootdStat();
02184 break;
02185 case kROOTD_PUTFILE:
02186 RootdPutFile(recvbuf);
02187 break;
02188 case kROOTD_GETFILE:
02189 RootdGetFile(recvbuf);
02190 break;
02191 case kROOTD_CHDIR:
02192 RootdChdir(recvbuf);
02193 break;
02194 case kROOTD_MKDIR:
02195 RootdMkdir(recvbuf);
02196 break;
02197 case kROOTD_RMDIR:
02198 RootdRmdir(recvbuf);
02199 break;
02200 case kROOTD_LSDIR:
02201 RootdLsdir(recvbuf);
02202 break;
02203 case kROOTD_PWD:
02204 RootdPwd();
02205 break;
02206 case kROOTD_MV:
02207 RootdMv(recvbuf);
02208 break;
02209 case kROOTD_RM:
02210 RootdRm(recvbuf);
02211 break;
02212 case kROOTD_CHMOD:
02213 RootdChmod(recvbuf);
02214 break;
02215 case kROOTD_OPENDIR:
02216 RootdOpenDir(recvbuf);
02217 break;
02218 case kROOTD_FREEDIR:
02219 RootdFreeDir();
02220 break;
02221 case kROOTD_DIRENTRY:
02222 RootdGetDirEntry();
02223 break;
02224 case kROOTD_ACCESS:
02225 RootdAccess(recvbuf);
02226 break;
02227 case kROOTD_BYE:
02228 return;
02229 default:
02230 Error(ErrFatal, kErrBadOp, "RootdLoop: received bad opcode %d", kind);
02231 }
02232 continue;
02233 }
02234 }
02235
02236
02237 void Usage(const char* name, int rc)
02238 {
02239 fprintf(stderr, "\nUsage: %s [options] [rootsys-dir]\n", name);
02240 fprintf(stderr, "\nOptions:\n");
02241 fprintf(stderr, "\t-b tcpwindowsize Specify the tcp window size in bytes\n");
02242 #ifdef R__GLBS
02243 fprintf(stderr, "\t-C hostcertfile Specify the location of the Globus host certificate\n");
02244 #endif
02245 fprintf(stderr, "\t-d level set debug level [0..3]\n");
02246 fprintf(stderr, "\t-D rootdaemonrc Use alternate rootdaemonrc file\n");
02247 fprintf(stderr, "\t (see documentation)\n");
02248 fprintf(stderr, "\t-E Ignored for backward compatibility\n");
02249 fprintf(stderr, "\t-f Run in foreground\n");
02250 #ifdef R__GLBS
02251 fprintf(stderr, "\t-G gridmapfile Specify the location of th Globus gridmap\n");
02252 #endif
02253 fprintf(stderr, "\t-i Running from inetd\n");
02254 fprintf(stderr, "\t-noauth Do not require client authentication\n");
02255 fprintf(stderr, "\t-p port# Specify a different port to listen on\n");
02256 fprintf(stderr, "\t-P pwfile Use pwfile instead of .srootdpass\n");
02257 fprintf(stderr, "\t-r Files can only be opened in read-only mode\n");
02258 fprintf(stderr, "\t-R bitmask Bitmask specifies which methods allow authentication re-use\n");
02259 fprintf(stderr, "\t-s sshd_port# Specify the port for the sshd daemon\n");
02260 #ifdef R__KRB5
02261 fprintf(stderr, "\t-S keytabfile Use an alternate keytab file\n");
02262 #endif
02263 fprintf(stderr, "\t-T <tmpdir> Use an alternate temp dir\n");
02264 fprintf(stderr, "\t-w Do not check /etc/hosts.equiv and $HOME/.rhosts\n");
02265
02266 exit(rc);
02267 }
02268
02269
02270 int main(int argc, char **argv)
02271 {
02272 char *s;
02273 int checkhostsequiv= 1;
02274 int requireauth = 1;
02275 int tcpwindowsize = 65535;
02276 int sshdport = 22;
02277 int port1 = 0;
02278 int port2 = 0;
02279 int reuseallow = 0x1F;
02280 int login = 2;
02281 int foregroundflag = 0;
02282 std::string tmpdir = "";
02283 std::string confdir = "";
02284 std::string rootbindir = "";
02285 std::string altSRPpass = "";
02286 std::string daemonrc = "";
02287 std::string rootetcdir = "";
02288 #ifdef R__GLBS
02289 std::string gridmap = "";
02290 std::string hostcertconf = "";
02291 #endif
02292 char *progname = argv[0];
02293
02294
02295 RpdSetErrorHandler(Err, ErrSys, ErrFatal);
02296
02297
02298
02299 NetSetSigPipeHook(SigPipe);
02300
02301
02302 ErrorInit(argv[0]);
02303
02304
02305 RpdSetSysLogFlag(1);
02306
02307
02308
02309
02310 int i = 1;
02311 for (i = 1; i < argc; i++) {
02312 if (!strncmp(argv[i],"-f",2))
02313 foregroundflag = 1;
02314 if (!strncmp(argv[i],"-i",2))
02315 gInetdFlag = 1;
02316 }
02317 if (foregroundflag) {
02318 if (isatty(0) && isatty(1)) {
02319 RpdSetSysLogFlag(0);
02320 ErrorInfo("main: running in foreground mode:"
02321 " sending output to stderr");
02322 }
02323 if (gInetdFlag)
02324 Error(ErrFatal,-1,"-i and -f options are incompatible");
02325 }
02326
02327
02328 signal(SIGTERM, RootdTerm);
02329 signal(SIGINT, RootdTerm);
02330
02331 char *tmp = RootdExpandPathName(argv[0]);
02332 if (tmp) {
02333 int p = strlen(tmp)-1;
02334 while ((p+1) && tmp[p] != '/')
02335 p--;
02336 if (p+1) {
02337 tmp[p] = '\0';
02338 rootbindir = std::string(tmp);
02339 while ((p+1) && tmp[p] != '/')
02340 p--;
02341 if (p+1) {
02342 tmp[p] = '\0';
02343 confdir = std::string(tmp);
02344 }
02345 }
02346 free(tmp);
02347 }
02348
02349 while (--argc > 0 && (*++argv)[0] == '-')
02350 for (s = argv[0]+1; *s != 0; s++)
02351 switch (*s) {
02352
02353 case 'b':
02354 if (--argc <= 0) {
02355 Error(ErrFatal,kErrFatal,"-b requires a buffersize in bytes"
02356 " as argument");
02357 }
02358 tcpwindowsize = atoi(*++argv);
02359 break;
02360 #ifdef R__GLBS
02361 case 'C':
02362 if (--argc <= 0) {
02363 Error(ErrFatal, kErrFatal,"-C requires a file name for"
02364 " the host certificates file location");
02365 }
02366 hostcertconf = std::string(*++argv);
02367 break;
02368 #endif
02369 case 'd':
02370 if (--argc <= 0) {
02371 Error(ErrFatal,kErrFatal,"-d requires a debug level as"
02372 " argument");
02373 }
02374 gDebug = atoi(*++argv);
02375 break;
02376
02377 case 'D':
02378 if (--argc <= 0) {
02379 Error(ErrFatal, kErrFatal,"-D requires a file path name"
02380 " for the file defining access rules");
02381 }
02382 daemonrc = std::string(*++argv);
02383 break;
02384
02385 case 'E':
02386 Error(ErrFatal, kErrFatal,"Option '-E' is now dummy "
02387 "- ignored (see proofd/src/proofd.cxx for"
02388 " additional details)");
02389 break;
02390
02391 case 'f':
02392 if (gInetdFlag) {
02393 Error(ErrFatal,-1,"-i and -f options are incompatible");
02394 }
02395 foregroundflag = 1;
02396 break;
02397
02398 case 'F':
02399 gCastorFlag = 1;
02400 gInetdFlag = 1;
02401 reuseallow = 0x0;
02402 login = 1;
02403 if (--argc <= 0) {
02404 if (!gInetdFlag)
02405 fprintf(stderr,"-F requires a file path name for the"
02406 " CASTOR disk file to be accessed\n");
02407 Error(ErrFatal, kErrFatal,"-F requires a file path name"
02408 " for the CASTOR disk file to be accessed");
02409 }
02410 gCastorFile = std::string(*++argv);
02411 break;
02412
02413 #ifdef R__GLBS
02414 case 'G':
02415 if (--argc <= 0) {
02416 Error(ErrFatal,kErrFatal,"-G requires a file name for"
02417 " the gridmap file");
02418 }
02419 gridmap = std::string(*++argv);
02420 break;
02421 #endif
02422 case 'h':
02423 Usage(progname, 0);
02424 break;
02425
02426 case 'H':
02427 if (--argc <= 0) {
02428 if (!gInetdFlag && !gCastorFlag)
02429 fprintf(stderr,"-H requires the CASTOR request ID");
02430 Error(ErrFatal, kErrFatal,"-H requires the CASTOR request ID");
02431 }
02432 gCastorReqId = std::string(*++argv);
02433 break;
02434
02435 case 'i':
02436 if (foregroundflag) {
02437 Error(ErrFatal,-1,"-i and -f options are incompatible");
02438 }
02439 gInetdFlag = 1;
02440 break;
02441
02442 case 'n':
02443 if (!strncmp(argv[0]+1,"noauth",6)) {
02444 requireauth = 0;
02445 s += 5;
02446 }
02447 break;
02448
02449 case 'p':
02450 if (--argc <= 0) {
02451 Error(ErrFatal,kErrFatal,"-p requires a port number as"
02452 " argument");
02453 }
02454 char *p;
02455 port1 = strtol(*++argv, &p, 10);
02456 if (*p == '-') {
02457 p++;
02458 port2 = strtol(p, &p, 10);
02459 } else if (*p == '\0')
02460 port2 = port1;
02461 if (*p != '\0' || port2 < port1 || port2 < 0) {
02462 Error(ErrFatal,kErrFatal,"invalid port number or range: %s",
02463 *argv);
02464 }
02465 break;
02466
02467 case 'P':
02468 if (--argc <= 0) {
02469 Error(ErrFatal,kErrFatal,"-P requires a file name for SRP"
02470 " password file");
02471 }
02472 altSRPpass = std::string(*++argv);
02473 break;
02474
02475 case 'r':
02476 gReadOnly = 1;
02477 break;
02478
02479 case 'R':
02480 if (--argc <= 0) {
02481 Error(ErrFatal,kErrFatal,"-R requires a hex but mask as"
02482 " argument");
02483 }
02484 reuseallow = strtol(*++argv, (char **)0, 16);
02485 break;
02486
02487 case 's':
02488 if (--argc <= 0) {
02489 Error(ErrFatal,kErrFatal,"-s requires as argument a port"
02490 " number for the sshd daemon");
02491 }
02492 sshdport = atoi(*++argv);
02493 break;
02494 #ifdef R__KRB5
02495 case 'S':
02496 if (--argc <= 0) {
02497 Error(ErrFatal,kErrFatal,"-S requires a path to your"
02498 " keytab\n");
02499 }
02500 RpdSetKeytabFile((const char *)(*++argv));
02501 break;
02502 #endif
02503 case 'T':
02504 if (--argc <= 0) {
02505 Error(ErrFatal, kErrFatal,"-T requires a dir path for"
02506 " temporary files [/usr/tmp]");
02507 }
02508 tmpdir = std::string(*++argv);
02509 break;
02510
02511 case 'w':
02512 checkhostsequiv = 0;
02513 break;
02514
02515 default:
02516 if (!foregroundflag) fprintf(stderr, "\nUnknown command line option: %c\n", *s);
02517 Error(0, -1, "unknown command line option: %c", *s);
02518 Usage(progname, 1);
02519 }
02520
02521
02522 if (!tmpdir.length())
02523 tmpdir = std::string("/usr/tmp");
02524 if (access(tmpdir.c_str(), W_OK) == -1)
02525 tmpdir = std::string("/tmp");
02526
02527
02528 gRootdTab = std::string(tmpdir).append("/rootdtab");
02529
02530 if (argc > 0) {
02531 confdir = std::string(*argv);
02532 } else {
02533
02534 #ifndef ROOTPREFIX
02535 if (!confdir.length()) {
02536 if (getenv("ROOTSYS")) {
02537 confdir = getenv("ROOTSYS");
02538 if (gDebug > 0)
02539 ErrorInfo("main: no config directory specified using"
02540 " ROOTSYS (%s)", confdir.c_str());
02541 } else {
02542 if (gDebug > 0)
02543 ErrorInfo("main: no config directory specified");
02544 }
02545 }
02546 #else
02547 confdir = ROOTPREFIX;
02548 #endif
02549 }
02550 #ifdef ROOTBINDIR
02551 rootbindir= ROOTBINDIR;
02552 #endif
02553 #ifdef ROOTETCDIR
02554 rootetcdir= ROOTETCDIR;
02555 #endif
02556
02557
02558 if (!rootbindir.length())
02559 rootbindir = std::string(confdir).append("/bin");
02560
02561 if (rootbindir.length()) {
02562 char *tmp1 = new char[15 + rootbindir.length()];
02563 sprintf(tmp1, "ROOTBINDIR=%s", rootbindir.c_str());
02564 putenv(tmp1);
02565 }
02566
02567
02568 if (!rootetcdir.length())
02569 rootetcdir = std::string(confdir).append("/etc");
02570
02571 if (rootetcdir.length()) {
02572 char *tmp1 = new char[15 + rootetcdir.length()];
02573 sprintf(tmp1, "ROOTETCDIR=%s", rootetcdir.c_str());
02574 putenv(tmp1);
02575 }
02576
02577
02578 if (daemonrc.length()) {
02579 char *tmp1 = new char[15+daemonrc.length()];
02580 sprintf(tmp1, "ROOTDAEMONRC=%s", daemonrc.c_str());
02581 putenv(tmp1);
02582 }
02583 #ifdef R__GLBS
02584
02585 if (gridmap.length()) {
02586 char *tmp1 = new char[15+gridmap.length()];
02587 sprintf(tmp1, "GRIDMAP=%s", gridmap.c_str());
02588 putenv(tmp1);
02589 }
02590
02591 if (hostcertconf.length()) {
02592 char *tmp1 = new char[15+hostcertconf.length()];
02593 sprintf(tmp1, "ROOTHOSTCERT=%s", hostcertconf.c_str());
02594 putenv(tmp1);
02595 }
02596 #endif
02597
02598
02599 int rootdparentid = -1;
02600 if (!gInetdFlag)
02601 rootdparentid = getpid();
02602 else
02603 rootdparentid = getppid();
02604
02605
02606 unsigned int options = kDMN_RQAUTH | kDMN_HOSTEQ | kDMN_SYSLOG;
02607
02608 if (!requireauth)
02609 options &= ~kDMN_RQAUTH;
02610 if (!checkhostsequiv)
02611 options &= ~kDMN_HOSTEQ;
02612 if (foregroundflag)
02613 options &= ~kDMN_SYSLOG;
02614 RpdInit(gService, rootdparentid, gProtocol, options,
02615 reuseallow, sshdport,
02616 tmpdir.c_str(),altSRPpass.c_str(),login);
02617
02618
02619 if (RpdGenRSAKeys(0)) {
02620 Error(Err, -1, "rootd: unable to generate local RSA keys");
02621 }
02622
02623 if (!gInetdFlag) {
02624
02625
02626
02627
02628
02629 int fdkeep = NetInit(gService, port1, port2, tcpwindowsize);
02630 if (!foregroundflag)
02631 DaemonStart(1, fdkeep, gService);
02632 }
02633
02634 if (gDebug > 0)
02635 ErrorInfo("main: pid = %d, ppid = %d, gInetdFlag = %d, gProtocol = %d",
02636 getpid(), getppid(), gInetdFlag, gProtocol);
02637
02638
02639
02640
02641
02642
02643 while (1) {
02644
02645 if (NetOpen(gInetdFlag, gService) == 0) {
02646
02647
02648 int rci = RpdInitSession(gService, gUser,
02649 gClientProtocol, gAnon, gPasswd);
02650 if (rci == -1)
02651 Error(ErrFatal, -1, "rootd: failure initializing session");
02652 else if (rci == -2)
02653
02654 exit(0);
02655
02656 ErrorInfo("main: rootdparentid = %d (%d)", rootdparentid, getppid());
02657
02658
02659 RootdLoop();
02660 NetClose();
02661 exit(0);
02662 }
02663
02664
02665
02666 if (gCastorFlag) break;
02667
02668 }
02669
02670 }