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 if (chkType == NO_CHK_PATH_PERM) {
00318 return 0;
00319 } else if (chkType == DISALLOW_PATH_REG) {
00320 return PATH_REG_NOT_ALLOWED;
00321 }
00322
00323
00324 status = isValidFilePath (fileOpenInp->fileName);
00325 if (status < 0) return status;
00326
00327
00328 if (rodsServerHost == NULL) {
00329 rodsLog (LOG_NOTICE,
00330 "chkFilePathPerm: NULL rodsServerHost");
00331 return (SYS_INTERNAL_NULL_INPUT_ERR);
00332 }
00333
00334
00335
00336 if (chkType == CHK_NON_VAULT_PATH_PERM) {
00337 status = matchCliVaultPath (rsComm, fileOpenInp->fileName, rodsServerHost);
00338
00339 if (status == 1) {
00340
00341 return (status);
00342 } else if (status == -1) {
00343
00344 return CANT_REG_IN_VAULT_FILE;
00345 }
00346 } else if (chkType == DO_CHK_PATH_PERM) {
00347 std::string out_path;
00348 eirods::error ret = resc_mgr.validate_vault_path( fileOpenInp->fileName, rodsServerHost, out_path );
00349 if( ret.ok() ) {
00350
00351 return CANT_REG_IN_VAULT_FILE;
00352 }
00353 } else {
00354 return SYS_INVALID_INPUT_PARAM;
00355
00356 }
00357
00358 status = rsChkNVPathPermByHost (rsComm, fileOpenInp, rodsServerHost);
00359
00360 return (status);
00361 }
00362
00363
00364
00365
00366
00367
00368 int
00369 isValidFilePath (char *path)
00370 {
00371 char *tmpPtr = NULL;
00372 char *tmpPath = path;
00373 #if 0
00374 if (strstr (path, "/../") != NULL) {
00375
00376 rodsLog (LOG_ERROR,
00377 "isValidFilePath: input fileName %s contains /../", path);
00378 return SYS_INVALID_FILE_PATH;
00379 }
00380 #endif
00381 while ((tmpPtr = strstr (tmpPath, "/..")) != NULL) {
00382 if (tmpPtr[3] == '\0' || tmpPtr[3] == '/') {
00383
00384 rodsLog (LOG_ERROR,"isValidFilePath: inp fileName %s contains /../ or ends with /..",path);
00385 return SYS_INVALID_FILE_PATH;
00386 } else {
00387 tmpPath += 3;
00388 }
00389 }
00390 return 0;
00391 }
00392
00393
00394
00395
00396
00397
00398 int matchCliVaultPath(
00399 rsComm_t* _comm,
00400 const std::string& _path,
00401 rodsServerHost_t* _svr_host ) {
00402
00403
00404 if( !_comm ) {
00405 rodsLog( LOG_ERROR, "matchCliVaultPath :: null comm" );
00406 return SYS_INVALID_INPUT_PARAM;
00407 }
00408
00409 if( _path.empty() ) {
00410 rodsLog( LOG_ERROR, "matchCliVaultPath :: empty file path" );
00411 return SYS_INVALID_INPUT_PARAM;
00412 }
00413
00414 if( !_svr_host ) {
00415 rodsLog( LOG_ERROR, "matchCliVaultPath :: null server host" );
00416 return SYS_INVALID_INPUT_PARAM;
00417 }
00418
00419
00420
00421 std::string vault_path;
00422 eirods::error ret = resc_mgr.validate_vault_path( _path, _svr_host, vault_path );
00423 if( !ret.ok() || vault_path.empty() ) {
00424 return 0;
00425 }
00426
00427
00428
00429 std::string user_path = _path.substr( vault_path.size() );
00430
00431
00432
00433 const size_t home_pos = ( user_path[0] == '/' ) ? 1 : 0;
00434
00435
00436
00437 size_t pos = user_path.find( "home/" );
00438 if( home_pos != pos ) {
00439 rodsLog( LOG_NOTICE, "matchCliVaultPath :: home/ is not found in the proper location for path [%s]",
00440 user_path.c_str() );
00441 return -1;
00442 }
00443
00444
00445
00446 const size_t user_pos = home_pos + 5;
00447
00448
00449
00450 pos = user_path.find( _comm->clientUser.userName );
00451 if( user_pos != pos ) {
00452 rodsLog( LOG_NOTICE, "matchCliVaultPath :: [%s] is not found in the proper location for path [%s]",
00453 _comm->clientUser.userName, user_path.c_str() );
00454 return -1;
00455 }
00456
00457
00458
00459 return 1;
00460
00461 #if 0
00462 int len, nameLen;
00463 char *tmpPath;
00464 char *outVaultPath = NULL;
00465
00466
00467 if ((len =
00468 matchVaultPath (rsComm, filePath, rodsServerHost, &outVaultPath)) == 0) {
00469
00470 return (0);
00471 }
00472
00473
00474
00475 nameLen = strlen (rsComm->clientUser.userName);
00476
00477 tmpPath = filePath + len + 1;
00478
00479 if (strncmp (tmpPath, "home/", 5) != 0) return -1;
00480 tmpPath += 5;
00481 if( strncmp (tmpPath, rsComm->clientUser.userName, nameLen) == 0 &&
00482 (tmpPath[nameLen] == '/' || tmpPath[len] == '\0') )
00483 return 1;
00484 else
00485 return 0;
00486
00487 return -1;
00488 #endif
00489 }
00490
00491
00492
00493
00494 int
00495 filePathTypeInResc (
00496 rsComm_t* rsComm,
00497 char* objPath,
00498 char* fileName,
00499 char* rescHier,
00500 rescInfo_t* rescInfo ) {
00501 fileStatInp_t fileStatInp;
00502 rodsStat_t *myStat = NULL;
00503 int status;
00504
00505
00506
00507 std::string location;
00508 eirods::error ret = eirods::get_loc_for_hier_string( rescHier, location );
00509 if( !ret.ok() ) {
00510 eirods::log( PASSMSG( "failed in get_loc_for_hier_string", ret ) );
00511 return -1;
00512 }
00513
00514 memset (&fileStatInp, 0, sizeof (fileStatInp));
00515 rstrcpy (fileStatInp.fileName, fileName, MAX_NAME_LEN);
00516 rstrcpy (fileStatInp.rescHier, rescHier, MAX_NAME_LEN);
00517 rstrcpy (fileStatInp.objPath, objPath, MAX_NAME_LEN);
00518 fileStatInp.fileType = static_cast< fileDriverType_t >( -1 );
00519 rstrcpy (fileStatInp.addr.hostAddr, location.c_str(), NAME_LEN);
00520 status = rsFileStat (rsComm, &fileStatInp, &myStat);
00521
00522 if (status < 0 || NULL == myStat ) return status;
00523 if (myStat->st_mode & S_IFREG) {
00524 free (myStat);
00525 return LOCAL_FILE_T;
00526 } else if (myStat->st_mode & S_IFDIR) {
00527 free (myStat);
00528 return LOCAL_DIR_T;
00529 } else {
00530 free (myStat);
00531 return UNKNOWN_OBJ_T;
00532 }
00533 }
00534
00535 int
00536 bindStreamToIRods (rodsServerHost_t *rodsServerHost, int fd)
00537 {
00538 int fileInx;
00539
00540 fileInx = allocAndFillFileDesc (rodsServerHost, "", STREAM_FILE_NAME, "",
00541 UNIX_FILE_TYPE, fd, DEFAULT_FILE_MODE);
00542
00543 return fileInx;
00544 }
00545