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