00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "fileOpr.h"
00010 #include "fileStat.h"
00011 #include "rsGlobalExtern.h"
00012 #include "rcGlobalExtern.h"
00013
00014
00015
00016 #include "eirods_log.h"
00017 #include "eirods_file_object.h"
00018 #include "eirods_collection_object.h"
00019 #include "eirods_stacktrace.h"
00020 #include "eirods_resource_backport.h"
00021 #include "eirods_resource_manager.h"
00022
00023 int
00024 initFileDesc ()
00025 {
00026 memset (FileDesc, 0, sizeof (fileDesc_t) * NUM_FILE_DESC);
00027 return (0);
00028 }
00029
00030 int
00031 allocFileDesc ()
00032 {
00033 int i;
00034
00035 for (i = 3; i < NUM_FILE_DESC; i++) {
00036 if (FileDesc[i].inuseFlag == FD_FREE) {
00037 FileDesc[i].inuseFlag = FD_INUSE;
00038 return (i);
00039 };
00040 }
00041
00042 rodsLog (LOG_NOTICE,
00043 "allocFileDesc: out of FileDesc");
00044
00045 return (SYS_OUT_OF_FILE_DESC);
00046 }
00047
00048 int
00049 allocAndFillFileDesc (rodsServerHost_t *rodsServerHost, char* objPath, char *fileName,
00050 char* rescHier, fileDriverType_t fileType, int fd, int mode)
00051 {
00052 int fileInx;
00053
00054 fileInx = allocFileDesc ();
00055 if (fileInx < 0) {
00056 return (fileInx);
00057 }
00058
00059 FileDesc[fileInx].rodsServerHost = rodsServerHost;
00060 FileDesc[fileInx].objPath = strdup (objPath);
00061 FileDesc[fileInx].fileName = strdup (fileName);
00062 FileDesc[fileInx].rescHier = strdup (rescHier);
00063 FileDesc[fileInx].fileType = fileType;
00064 FileDesc[fileInx].mode = mode;
00065 FileDesc[fileInx].fd = fd;
00066
00067 return (fileInx);
00068 }
00069
00070 int
00071 freeFileDesc (int fileInx)
00072 {
00073 if (fileInx < 3 || fileInx >= NUM_FILE_DESC) {
00074 rodsLog (LOG_NOTICE,
00075 "freeFileDesc: fileInx %d out of range", fileInx);
00076 return (SYS_FILE_DESC_OUT_OF_RANGE);
00077 }
00078
00079 if (FileDesc[fileInx].fileName != NULL) {
00080 free (FileDesc[fileInx].fileName);
00081 }
00082
00083 if(FileDesc[fileInx].rescHier != NULL) {
00084 free (FileDesc[fileInx].rescHier);
00085 }
00086
00087
00088
00089 memset (&FileDesc[fileInx], 0, sizeof (fileDesc_t));
00090
00091 return (0);
00092 }
00093
00094 int
00095 getServerHostByFileInx (int fileInx, rodsServerHost_t **rodsServerHost)
00096 {
00097 int remoteFlag;
00098
00099 if (fileInx < 3 || fileInx >= NUM_FILE_DESC) {
00100 rodsLog (LOG_NOTICE,
00101 "getServerHostByFileInx: Bad fileInx value %d", fileInx);
00102 return (SYS_BAD_FILE_DESCRIPTOR);
00103 }
00104
00105 if (FileDesc[fileInx].inuseFlag == 0) {
00106 rodsLog (LOG_NOTICE,
00107 "getServerHostByFileInx: fileInx %d not active", fileInx);
00108 return (SYS_BAD_FILE_DESCRIPTOR);
00109 }
00110
00111 *rodsServerHost = FileDesc[fileInx].rodsServerHost;
00112 remoteFlag = (*rodsServerHost)->localFlag;
00113
00114 return (remoteFlag);
00115 }
00116
00117 int
00118 mkDirForFilePath (
00119 rsComm_t *rsComm,
00120 const char *startDir,
00121 const char *filePath,
00122 int mode)
00123 {
00124 int status;
00125
00126 char myDir[MAX_NAME_LEN], myFile[MAX_NAME_LEN];
00127
00128 if ((status = splitPathByKey (filePath, myDir, myFile, '/')) < 0) {
00129 rodsLog (LOG_NOTICE,
00130 "mkDirForFilePath: splitPathByKey for %s error, status = %d",
00131 filePath, status);
00132 return (status);
00133 }
00134
00135 status = mkFileDirR (rsComm, startDir, myDir, mode);
00136
00137 return (status);
00138 }
00139
00140
00141
00142 int mkFileDirR(
00143 rsComm_t *rsComm,
00144 const char *startDir,
00145 const char *destDir,
00146 int mode ) {
00147
00148 int startLen;
00149 int pathLen, tmpLen;
00150 char tmpPath[MAX_NAME_LEN];
00151 struct stat statbuf;
00152
00153 startLen = strlen (startDir);
00154 pathLen = strlen (destDir);
00155
00156 rstrcpy (tmpPath, destDir, MAX_NAME_LEN);
00157
00158 tmpLen = pathLen;
00159
00160 while (tmpLen > startLen) {
00161 eirods::collection_object tmp_coll_obj( tmpPath, eirods::EIRODS_LOCAL_USE_ONLY_RESOURCE, 0, 0 );
00162 eirods::error stat_err = fileStat( rsComm, tmp_coll_obj, &statbuf );
00163 if ( stat_err.code() >= 0) {
00164 if (statbuf.st_mode & S_IFDIR) {
00165 break;
00166 } else {
00167 rodsLog (LOG_NOTICE,
00168 "mkFileDirR: A local non-directory %s already exists \n",
00169 tmpPath);
00170 return (stat_err.code() );
00171 }
00172 }
00173
00174
00175 while (tmpLen && tmpPath[tmpLen] != '/')
00176 tmpLen --;
00177
00178 tmpPath[tmpLen] = '\0';
00179
00180 }
00181
00182
00183
00184 while (tmpLen < pathLen) {
00185
00186 tmpPath[tmpLen] = '/';
00187
00188 eirods::collection_object tmp_coll_obj( tmpPath, eirods::EIRODS_LOCAL_USE_ONLY_RESOURCE, mode, 0 );
00189 eirods::error mkdir_err = fileMkdir( rsComm, tmp_coll_obj );
00190 if ( !mkdir_err.ok() && (getErrno ( mkdir_err.code()) != EEXIST)) {
00191 std::stringstream msg;
00192 msg << "fileMkdir for [";
00193 msg << tmpPath;
00194 msg << "]";
00195 eirods::error ret_err = PASSMSG( msg.str(), mkdir_err );
00196 eirods::log( ret_err );
00197
00198 return mkdir_err.code();
00199 }
00200 while (tmpPath[tmpLen] != '\0')
00201 tmpLen ++;
00202 }
00203 return 0;
00204 }
00205
00206
00207
00208 int chkEmptyDir (int fileType, rsComm_t *rsComm, char *cacheDir) {
00209
00210 int status;
00211 char childPath[MAX_NAME_LEN];
00212 struct stat myFileStat;
00213 struct rodsDirent* myFileDirent = 0;
00214
00215
00216
00217 eirods::collection_object cacheDir_obj( cacheDir, eirods::EIRODS_LOCAL_USE_ONLY_RESOURCE, 0, 0 );
00218 eirods::error opendir_err = fileOpendir( rsComm, cacheDir_obj );
00219
00220
00221
00222
00223 if( !opendir_err.ok() ) {
00224 return 0;
00225 }
00226
00227
00228
00229 eirods::error readdir_err = fileReaddir( rsComm, cacheDir_obj, &myFileDirent );
00230 while( readdir_err.ok() && 0 == readdir_err.code() ) {
00231
00232
00233 if( strcmp( myFileDirent->d_name, "." ) == 0 ||
00234 strcmp( myFileDirent->d_name, "..") == 0) {
00235 readdir_err = fileReaddir( rsComm, cacheDir_obj, &myFileDirent );
00236 continue;
00237 }
00238
00239
00240
00241 snprintf( childPath, MAX_NAME_LEN, "%s/%s", cacheDir, myFileDirent->d_name );
00242 eirods::collection_object tmp_coll_obj( childPath, eirods::EIRODS_LOCAL_USE_ONLY_RESOURCE, 0, 0 );
00243 eirods::error stat_err = fileStat( rsComm, tmp_coll_obj, &myFileStat );
00244
00245
00246
00247 if( stat_err.code() < 0 ) {
00248 rodsLog( LOG_ERROR, "chkEmptyDir: fileStat error for %s, status = %d",
00249 childPath, status);
00250 break;
00251 }
00252
00253
00254
00255 if( myFileStat.st_mode & S_IFREG ) {
00256 rodsLog( LOG_ERROR, "chkEmptyDir: file %s exists",
00257 childPath, status);
00258 status = SYS_DIR_IN_VAULT_NOT_EMPTY;
00259 break;
00260 }
00261
00262
00263
00264 if (myFileStat.st_mode & S_IFDIR) {
00265 status = chkEmptyDir( -1, rsComm, childPath);
00266 if (status == SYS_DIR_IN_VAULT_NOT_EMPTY) {
00267 rodsLog( LOG_ERROR, "chkEmptyDir: dir %s is not empty", childPath );
00268 break;
00269 }
00270 }
00271
00272
00273
00274 readdir_err = fileReaddir( rsComm, cacheDir_obj, &myFileDirent );
00275
00276 }
00277
00278
00279
00280 eirods::error closedir_err = fileClosedir( rsComm, cacheDir_obj );
00281 if( !closedir_err.ok() ) {
00282 std::stringstream msg;
00283 msg << "fileClosedir failed for [";
00284 msg << cacheDir;
00285 msg << "]";
00286 eirods::error log_err = PASSMSG( msg.str(), closedir_err );
00287 eirods::log( log_err );
00288 }
00289
00290 if( status != SYS_DIR_IN_VAULT_NOT_EMPTY ) {
00291 eirods::collection_object coll_obj( cacheDir, eirods::EIRODS_LOCAL_USE_ONLY_RESOURCE, 0, 0 );
00292 eirods::error rmdir_err = fileRmdir( rsComm, coll_obj );
00293 if( !rmdir_err.ok() ) {
00294 std::stringstream msg;
00295 msg << "fileRmdir failed for [";
00296 msg << cacheDir;
00297 msg << "]";
00298 eirods::error err = PASSMSG( msg.str(), rmdir_err );
00299 eirods::log ( err );
00300 }
00301 status = 0;
00302 }
00303
00304 return status;
00305
00306 }
00307
00308
00309
00310
00311 int
00312 chkFilePathPerm (rsComm_t *rsComm, fileOpenInp_t *fileOpenInp,
00313 rodsServerHost_t *rodsServerHost, int chkType)
00314 {
00315 int status;
00316
00317
00318 char *outVaultPath = NULL;
00319
00320 if (chkType == NO_CHK_PATH_PERM) {
00321 return 0;
00322 } else if (chkType == DISALLOW_PATH_REG) {
00323 return PATH_REG_NOT_ALLOWED;
00324 }
00325
00326
00327 status = isValidFilePath (fileOpenInp->fileName);
00328 if (status < 0) return status;
00329
00330
00331 if (rodsServerHost == NULL) {
00332 rodsLog (LOG_NOTICE,
00333 "chkFilePathPerm: NULL rodsServerHost");
00334 return (SYS_INTERNAL_NULL_INPUT_ERR);
00335 }
00336
00337
00338
00339 if (chkType == CHK_NON_VAULT_PATH_PERM) {
00340 status = matchCliVaultPath (rsComm, fileOpenInp->fileName, rodsServerHost);
00341
00342 if (status == 1) {
00343
00344 return (status);
00345 } else if (status == -1) {
00346
00347 return CANT_REG_IN_VAULT_FILE;
00348 }
00349 } else if (chkType == DO_CHK_PATH_PERM) {
00350 int ret = matchVaultPath (rsComm, fileOpenInp->fileName, rodsServerHost, &outVaultPath );
00351 if( ret > 0 ) {
00352
00353
00354 return CANT_REG_IN_VAULT_FILE;
00355 }
00356 } else {
00357 return SYS_INVALID_INPUT_PARAM;
00358
00359 }
00360
00361 status = rsChkNVPathPermByHost (rsComm, fileOpenInp, rodsServerHost);
00362
00363 return (status);
00364 }
00365
00366
00367
00368
00369
00370
00371 int
00372 isValidFilePath (char *path)
00373 {
00374 char *tmpPtr = NULL;
00375 char *tmpPath = path;
00376 #if 0
00377 if (strstr (path, "/../") != NULL) {
00378
00379 rodsLog (LOG_ERROR,
00380 "isValidFilePath: input fileName %s contains /../", path);
00381 return SYS_INVALID_FILE_PATH;
00382 }
00383 #endif
00384 while ((tmpPtr = strstr (tmpPath, "/..")) != NULL) {
00385 if (tmpPtr[3] == '\0' || tmpPtr[3] == '/') {
00386
00387 rodsLog (LOG_ERROR,"isValidFilePath: inp fileName %s contains /../ or ends with /..",path);
00388 return SYS_INVALID_FILE_PATH;
00389 } else {
00390 tmpPath += 3;
00391 }
00392 }
00393 return 0;
00394 }
00395
00396 int
00397 matchVaultPath (rsComm_t *rsComm, char *filePath,
00398 rodsServerHost_t *rodsServerHost, char **outVaultPath)
00399 {
00400 rescGrpInfo_t *tmpRescGrpInfo;
00401 rescInfo_t *tmpRescInfo;
00402 int len;
00403 if (isValidFilePath (filePath) < 0) {
00404
00405 return (0);
00406 }
00407 tmpRescGrpInfo = RescGrpInfo;
00408
00409 while (tmpRescGrpInfo != NULL) {
00410 tmpRescInfo = tmpRescGrpInfo->rescInfo;
00411
00412 if (tmpRescInfo->rodsServerHost == rodsServerHost) {
00413 len = strlen (tmpRescInfo->rescVaultPath);
00414 if( strncmp ( tmpRescInfo->rescVaultPath, filePath, len ) == 0 &&
00415 ( filePath[len] == '/' || filePath[len] == '\0' ) ) {
00416 *outVaultPath = tmpRescInfo->rescVaultPath;
00417 return (len);
00418 }
00419 }
00420 tmpRescGrpInfo = tmpRescGrpInfo->next;
00421 }
00422
00423
00424 return (0);
00425 }
00426
00427
00428
00429
00430
00431
00432 int
00433 matchCliVaultPath (rsComm_t *rsComm, char *filePath,
00434 rodsServerHost_t *rodsServerHost)
00435 {
00436 int len, nameLen;
00437 char *tmpPath;
00438 char *outVaultPath = NULL;
00439
00440
00441 if ((len =
00442 matchVaultPath (rsComm, filePath, rodsServerHost, &outVaultPath)) == 0) {
00443
00444 return (0);
00445 }
00446
00447
00448
00449 nameLen = strlen (rsComm->clientUser.userName);
00450
00451 tmpPath = filePath + len + 1;
00452
00453 if (strncmp (tmpPath, "home/", 5) != -1) return -1;
00454 tmpPath += 5;
00455 if( strncmp (tmpPath, rsComm->clientUser.userName, nameLen) == 0 &&
00456 (tmpPath[nameLen] == '/' || tmpPath[len] == '\0') )
00457 return 1;
00458 else
00459 return 0;
00460
00461 return -1;
00462 }
00463
00464
00465
00466
00467 int
00468 filePathTypeInResc (
00469 rsComm_t* rsComm,
00470 char* objPath,
00471 char* fileName,
00472 char* rescHier,
00473 rescInfo_t* rescInfo ) {
00474 fileStatInp_t fileStatInp;
00475 rodsStat_t *myStat = NULL;
00476 int status;
00477
00478
00479
00480 std::string location;
00481 eirods::error ret = eirods::get_loc_for_hier_string( rescHier, location );
00482 if( !ret.ok() ) {
00483 eirods::log( PASSMSG( "failed in get_loc_for_hier_string", ret ) );
00484 return -1;
00485 }
00486
00487 memset (&fileStatInp, 0, sizeof (fileStatInp));
00488 rstrcpy (fileStatInp.fileName, fileName, MAX_NAME_LEN);
00489 rstrcpy (fileStatInp.rescHier, rescHier, MAX_NAME_LEN);
00490 rstrcpy (fileStatInp.objPath, objPath, MAX_NAME_LEN);
00491 fileStatInp.fileType = static_cast< fileDriverType_t >( -1 );
00492 rstrcpy (fileStatInp.addr.hostAddr, location.c_str(), NAME_LEN);
00493 status = rsFileStat (rsComm, &fileStatInp, &myStat);
00494
00495 if (status < 0 || NULL == myStat ) return status;
00496 if (myStat->st_mode & S_IFREG) {
00497 free (myStat);
00498 return LOCAL_FILE_T;
00499 } else if (myStat->st_mode & S_IFDIR) {
00500 free (myStat);
00501 return LOCAL_DIR_T;
00502 } else {
00503 free (myStat);
00504 return UNKNOWN_OBJ_T;
00505 }
00506 }
00507
00508 int
00509 bindStreamToIRods (rodsServerHost_t *rodsServerHost, int fd)
00510 {
00511 int fileInx;
00512
00513 fileInx = allocAndFillFileDesc (rodsServerHost, "", STREAM_FILE_NAME, "",
00514 UNIX_FILE_TYPE, fd, DEFAULT_FILE_MODE);
00515
00516 return fileInx;
00517 }
00518