00001
00002
00003
00004
00005
00006 #include "dataObjUnlink.h"
00007 #include "rodsLog.h"
00008 #include "icatDefines.h"
00009 #include "fileUnlink.h"
00010 #include "unregDataObj.h"
00011 #include "objMetaOpr.h"
00012 #include "dataObjOpr.h"
00013 #include "specColl.h"
00014 #include "resource.h"
00015 #include "rsGlobalExtern.h"
00016 #include "rcGlobalExtern.h"
00017 #include "reGlobalsExtern.h"
00018 #include "reDefines.h"
00019 #include "rmCollOld.h"
00020 #include "rmColl.h"
00021 #include "dataObjRename.h"
00022 #include "subStructFileUnlink.h"
00023 #include "modDataObjMeta.h"
00024 #include "phyBundleColl.h"
00025 #include "dataObjRepl.h"
00026 #include "regDataObj.h"
00027 #include "physPath.h"
00028
00029 int
00030 rsDataObjUnlink (rsComm_t *rsComm, dataObjInp_t *dataObjUnlinkInp)
00031 {
00032 int status;
00033 ruleExecInfo_t rei;
00034 int trashPolicy;
00035 dataObjInfo_t *dataObjInfoHead = NULL;
00036 rodsServerHost_t *rodsServerHost = NULL;
00037 int rmTrashFlag = 0;
00038 specCollCache_t *specCollCache = NULL;
00039
00040 resolveLinkedPath (rsComm, dataObjUnlinkInp->objPath, &specCollCache,
00041 &dataObjUnlinkInp->condInput);
00042 status = getAndConnRcatHost (rsComm, MASTER_RCAT,
00043 dataObjUnlinkInp->objPath, &rodsServerHost);
00044
00045 if (status < 0 || NULL == rodsServerHost ) {
00046 return (status);
00047 } else if (rodsServerHost->rcatEnabled == REMOTE_ICAT) {
00048 int retval;
00049 retval = rcDataObjUnlink (rodsServerHost->conn, dataObjUnlinkInp);
00050 return status;
00051 }
00052
00053 if (getValByKey (
00054 &dataObjUnlinkInp->condInput, IRODS_ADMIN_RMTRASH_KW) != NULL ||
00055 getValByKey (
00056 &dataObjUnlinkInp->condInput, IRODS_RMTRASH_KW) != NULL) {
00057 if (isTrashPath (dataObjUnlinkInp->objPath) == False) {
00058 return (SYS_INVALID_FILE_PATH);
00059 }
00060 rmTrashFlag = 1;
00061 }
00062
00063 dataObjUnlinkInp->openFlags = O_WRONLY;
00064 status = getDataObjInfoIncSpecColl (rsComm, dataObjUnlinkInp,
00065 &dataObjInfoHead);
00066
00067 if (status < 0) return (status);
00068
00069 if (dataObjUnlinkInp->oprType == UNREG_OPR ||
00070 getValByKey (&dataObjUnlinkInp->condInput, FORCE_FLAG_KW) != NULL ||
00071 getValByKey (&dataObjUnlinkInp->condInput, REPL_NUM_KW) != NULL ||
00072 dataObjInfoHead->specColl != NULL || rmTrashFlag == 1) {
00073 status = _rsDataObjUnlink (rsComm, dataObjUnlinkInp, &dataObjInfoHead);
00074 } else {
00075 initReiWithDataObjInp (&rei, rsComm, dataObjUnlinkInp);
00076 status = applyRule ("acTrashPolicy", NULL, &rei, NO_SAVE_REI);
00077 trashPolicy = rei.status;
00078
00079 if (trashPolicy != NO_TRASH_CAN) {
00080 status = rsMvDataObjToTrash (rsComm, dataObjUnlinkInp,
00081 &dataObjInfoHead);
00082 freeAllDataObjInfo (dataObjInfoHead);
00083 return status;
00084 } else {
00085 status = _rsDataObjUnlink (rsComm, dataObjUnlinkInp,
00086 &dataObjInfoHead);
00087 }
00088 }
00089
00090 initReiWithDataObjInp (&rei, rsComm, dataObjUnlinkInp);
00091 rei.doi = dataObjInfoHead;
00092 rei.status = status;
00093 rei.status = applyRule ("acPostProcForDelete", NULL, &rei, NO_SAVE_REI);
00094
00095 if (rei.status < 0) {
00096 rodsLog (LOG_NOTICE,
00097 "rsDataObjUnlink: acPostProcForDelete error for %s. status = %d",
00098 dataObjUnlinkInp->objPath, rei.status);
00099 }
00100
00101
00102 freeAllDataObjInfo (dataObjInfoHead);
00103
00104 return (status);
00105 }
00106
00107 int
00108 _rsDataObjUnlink (rsComm_t *rsComm, dataObjInp_t *dataObjUnlinkInp,
00109 dataObjInfo_t **dataObjInfoHead)
00110 {
00111 int status;
00112 int retVal = 0;
00113 dataObjInfo_t *tmpDataObjInfo, *myDataObjInfoHead;
00114
00115 status = chkPreProcDeleteRule (rsComm, dataObjUnlinkInp, *dataObjInfoHead);
00116 if (status < 0) return status;
00117
00118 #if 0
00119 ruleExecInfo_t rei;
00120 initReiWithDataObjInp (&rei, rsComm, dataObjUnlinkInp);
00121 rei.doi = *dataObjInfoHead;
00122
00123 status = applyRule ("acDataDeletePolicy", NULL, &rei, NO_SAVE_REI);
00124
00125 if (status < 0 && status != NO_MORE_RULES_ERR &&
00126 status != SYS_DELETE_DISALLOWED) {
00127 rodsLog (LOG_NOTICE,
00128 "_rsDataObjUnlink: acDataDeletePolicy error for %s. status = %d",
00129 dataObjUnlinkInp->objPath, status);
00130 return (status);
00131 }
00132
00133 if (rei.status == SYS_DELETE_DISALLOWED) {
00134 rodsLog (LOG_NOTICE,
00135 "_rsDataObjUnlink:disallowed for %s via acDataDeletePolicy,stat=%d",
00136 dataObjUnlinkInp->objPath, rei.status);
00137 return (rei.status);
00138 }
00139 #endif
00140
00141 myDataObjInfoHead = *dataObjInfoHead;
00142 if (strstr (myDataObjInfoHead->dataType, BUNDLE_STR) != NULL) {
00143 int numSubfiles;
00144 if (rsComm->proxyUser.authInfo.authFlag < LOCAL_PRIV_USER_AUTH) {
00145 return CAT_INSUFFICIENT_PRIVILEGE_LEVEL;
00146 }
00147 if (getValByKey (&dataObjUnlinkInp->condInput, REPL_NUM_KW) != NULL) {
00148 return SYS_CANT_MV_BUNDLE_DATA_BY_COPY;
00149 }
00150
00151
00152
00153 numSubfiles = getNumSubfilesInBunfileObj (rsComm, myDataObjInfoHead->objPath);
00154 if (numSubfiles > 0) {
00155 if (getValByKey (&dataObjUnlinkInp->condInput, EMPTY_BUNDLE_ONLY_KW) != NULL) {
00156
00157 return 0;
00158 } else {
00159 status = _unbunAndStageBunfileObj (rsComm, dataObjInfoHead, NULL, 1);
00160 if (status < 0) {
00161
00162
00163 if (getErrno (status) != EEXIST && getIrodsErrno (status) != SYS_TAR_STRUCT_FILE_EXTRACT_ERR) {
00164 rodsLogError( LOG_ERROR, status, "_rsDataObjUnlink:_unbunAndStageBunfileObj err for %s",
00165 myDataObjInfoHead->objPath);
00166 return (status);
00167 }
00168 }
00169
00170 *dataObjInfoHead = NULL;
00171 status = getDataObjInfoIncSpecColl (rsComm, dataObjUnlinkInp, dataObjInfoHead );
00172
00173 if (status < 0) return (status);
00174 }
00175 }
00176 }
00177
00178
00179 tmpDataObjInfo = *dataObjInfoHead;
00180 while (tmpDataObjInfo != NULL) {
00181 status = dataObjUnlinkS (rsComm, dataObjUnlinkInp, tmpDataObjInfo);
00182 if (status < 0) {
00183 if (retVal == 0) {
00184 retVal = status;
00185 }
00186 }
00187 if (dataObjUnlinkInp->specColl != NULL)
00188 break;
00189 tmpDataObjInfo = tmpDataObjInfo->next;
00190 }
00191
00192 if ((*dataObjInfoHead)->specColl == NULL)
00193 resolveDataObjReplStatus (rsComm, dataObjUnlinkInp);
00194
00195 return (retVal);
00196 }
00197
00198
00199
00200
00201 int
00202 resolveDataObjReplStatus (rsComm_t *rsComm, dataObjInp_t *dataObjUnlinkInp)
00203 {
00204 int status;
00205 dataObjInfo_t *dataObjInfoHead = NULL;
00206 dataObjInfo_t *newestDataObjInfo = NULL;
00207 dataObjInfo_t *tmpDataObjInfo;
00208
00209 if (getValByKey (&dataObjUnlinkInp->condInput, RESC_NAME_KW) == NULL &&
00210 getValByKey (&dataObjUnlinkInp->condInput, REPL_NUM_KW) == NULL) {
00211 return 0;
00212 }
00213 status = getDataObjInfo (rsComm, dataObjUnlinkInp,
00214 &dataObjInfoHead, ACCESS_DELETE_OBJECT, 1);
00215
00216 if (status < 0) return status;
00217
00218 tmpDataObjInfo = dataObjInfoHead;
00219 while (tmpDataObjInfo != NULL) {
00220 if (tmpDataObjInfo->replStatus == 0) {
00221 if (newestDataObjInfo == NULL) {
00222 newestDataObjInfo = tmpDataObjInfo;
00223 } else if (atoi (tmpDataObjInfo->dataModify) >
00224 atoi (newestDataObjInfo->dataModify)) {
00225 newestDataObjInfo = tmpDataObjInfo;
00226 }
00227 } else {
00228 newestDataObjInfo = NULL;
00229 break;
00230 }
00231 tmpDataObjInfo = tmpDataObjInfo->next;
00232 }
00233
00234
00235 if (newestDataObjInfo != NULL) {
00236 keyValPair_t regParam;
00237 char tmpStr[MAX_NAME_LEN];
00238 modDataObjMeta_t modDataObjMetaInp;
00239
00240 memset (®Param, 0, sizeof (regParam));
00241 memset (&modDataObjMetaInp, 0, sizeof (modDataObjMetaInp));
00242 snprintf (tmpStr, MAX_NAME_LEN, "%d", NEWLY_CREATED_COPY);
00243 addKeyVal (®Param, REPL_STATUS_KW, tmpStr);
00244 modDataObjMetaInp.dataObjInfo = newestDataObjInfo;
00245 modDataObjMetaInp.regParam = ®Param;
00246
00247 status = rsModDataObjMeta (rsComm, &modDataObjMetaInp);
00248
00249 clearKeyVal (®Param);
00250 }
00251 freeAllDataObjInfo (dataObjInfoHead);
00252 return (status);
00253 }
00254
00255 int
00256 dataObjUnlinkS (rsComm_t *rsComm, dataObjInp_t *dataObjUnlinkInp,
00257 dataObjInfo_t *dataObjInfo)
00258 {
00259 int status;
00260 unregDataObj_t unregDataObjInp;
00261
00262 if (dataObjInfo->specColl == NULL) {
00263 if (dataObjUnlinkInp->oprType == UNREG_OPR &&
00264 rsComm->clientUser.authInfo.authFlag != LOCAL_PRIV_USER_AUTH) {
00265 ruleExecInfo_t rei;
00266
00267 initReiWithDataObjInp (&rei, rsComm, dataObjUnlinkInp);
00268 rei.doi = dataObjInfo;
00269 rei.status = DO_CHK_PATH_PERM;
00270
00271 applyRule ("acSetChkFilePathPerm", NULL, &rei, NO_SAVE_REI);
00272 if (rei.status != NO_CHK_PATH_PERM) {
00273 char *outVaultPath;
00274 rodsServerHost_t *rodsServerHost;
00275 status = resolveHostByRescInfo (dataObjInfo->rescInfo,
00276 &rodsServerHost);
00277 if (status < 0) return status;
00278
00279 status = matchVaultPath (rsComm, dataObjInfo->filePath,
00280 rodsServerHost, &outVaultPath);
00281 if (status != 0) {
00282
00283 rodsLog (LOG_DEBUG,
00284 "dataObjUnlinkS: unregistering in vault file %s",
00285 dataObjInfo->filePath);
00286 return CANT_UNREG_IN_VAULT_FILE;
00287 }
00288 }
00289 #if 0
00290 } else if (RescTypeDef[dataObjInfo->rescInfo->rescTypeInx].driverType
00291 == WOS_FILE_TYPE && dataObjUnlinkInp->oprType != UNREG_OPR) {
00292
00293
00294 status = l3Unlink (rsComm, dataObjInfo);
00295 if (status < 0) {
00296 rodsLog (LOG_NOTICE,
00297 "dataObjUnlinkS: l3Unlink error for WOS file %s. status = %d",
00298 dataObjUnlinkInp->objPath, status);
00299 return status;
00300 }
00301 unregDataObjInp.dataObjInfo = dataObjInfo;
00302 unregDataObjInp.condInput = &dataObjUnlinkInp->condInput;
00303 status = rsUnregDataObj (rsComm, &unregDataObjInp);
00304 if (status < 0) {
00305 rodsLog (LOG_NOTICE,
00306 "dataObjUnlinkS: rsUnregDataObj error for %s. status = %d",
00307 dataObjUnlinkInp->objPath, status);
00308 }
00309 return status;
00310 #endif
00311 }
00312 unregDataObjInp.dataObjInfo = dataObjInfo;
00313 unregDataObjInp.condInput = &dataObjUnlinkInp->condInput;
00314 status = rsUnregDataObj (rsComm, &unregDataObjInp);
00315
00316 if (status < 0) {
00317 rodsLog (LOG_NOTICE,
00318 "dataObjUnlinkS: rsUnregDataObj error for %s. status = %d",
00319 dataObjUnlinkInp->objPath, status);
00320 return status;
00321 }
00322 }
00323
00324 if (dataObjUnlinkInp->oprType != UNREG_OPR) {
00325 status = l3Unlink (rsComm, dataObjInfo);
00326 if (status < 0) {
00327 int myError = getErrno (status);
00328 rodsLog (LOG_NOTICE,
00329 "dataObjUnlinkS: l3Unlink error for %s. status = %d",
00330 dataObjUnlinkInp->objPath, status);
00331
00332 if (myError != ENOENT && myError != EACCES) {
00333 char orphanPath[MAX_NAME_LEN];
00334 int status1 = 0;
00335 rodsLog (LOG_NOTICE,
00336 "dataObjUnlinkS: orphan file %s", dataObjInfo->filePath);
00337 while (1) {
00338 if (isOrphanPath (dataObjUnlinkInp->objPath) ==
00339 NOT_ORPHAN_PATH) {
00340
00341 status1 = rsMkOrphanPath (rsComm, dataObjInfo->objPath,
00342 orphanPath);
00343 if (status1 < 0) break;
00344
00345 rstrcpy (dataObjInfo->objPath, orphanPath,MAX_NAME_LEN);
00346 }
00347 status1 = svrRegDataObj (rsComm, dataObjInfo);
00348 if (status1 == CAT_NAME_EXISTS_AS_DATAOBJ ||
00349 status1 == CATALOG_ALREADY_HAS_ITEM_BY_THAT_NAME) {
00350 continue;
00351 } else if (status1 < 0) {
00352 rodsLogError (LOG_ERROR, status1,
00353 "dataObjUnlinkS: svrRegDataObj of orphan %s error",
00354 dataObjInfo->objPath);
00355 }
00356 break;
00357 }
00358 return (status);
00359 } else {
00360 status = 0;
00361 }
00362 }
00363 }
00364
00365 return (status);
00366 }
00367
00368 int
00369 l3Unlink (rsComm_t *rsComm, dataObjInfo_t *dataObjInfo)
00370 {
00371 int rescTypeInx;
00372 fileUnlinkInp_t fileUnlinkInp;
00373 int status;
00374
00375 if (getRescClass (dataObjInfo->rescInfo) == BUNDLE_CL) return 0;
00376
00377 if (dataObjInfo->rescInfo->rescStatus == INT_RESC_STATUS_DOWN)
00378 return SYS_RESC_IS_DOWN;
00379
00380 if (getStructFileType (dataObjInfo->specColl) >= 0) {
00381 subFile_t subFile;
00382 memset (&subFile, 0, sizeof (subFile));
00383 rstrcpy (subFile.subFilePath, dataObjInfo->subPath,
00384 MAX_NAME_LEN);
00385 rstrcpy (subFile.addr.hostAddr, dataObjInfo->rescInfo->rescLoc,
00386 NAME_LEN);
00387 subFile.specColl = dataObjInfo->specColl;
00388 status = rsSubStructFileUnlink (rsComm, &subFile);
00389 } else {
00390 rescTypeInx = dataObjInfo->rescInfo->rescTypeInx;
00391
00392
00393 switch (RescTypeDef[rescTypeInx].rescCat) {
00394 case FILE_CAT:
00395 memset (&fileUnlinkInp, 0, sizeof (fileUnlinkInp));
00396 fileUnlinkInp.fileType = (fileDriverType_t)RescTypeDef[rescTypeInx].driverType;
00397 rstrcpy (fileUnlinkInp.fileName, dataObjInfo->filePath,
00398 MAX_NAME_LEN);
00399 rstrcpy (fileUnlinkInp.addr.hostAddr,
00400 dataObjInfo->rescInfo->rescLoc, NAME_LEN);
00401 status = rsFileUnlink (rsComm, &fileUnlinkInp);
00402 break;
00403
00404 default:
00405 rodsLog (LOG_NOTICE,
00406 "l3Unlink: rescCat type %d is not recognized",
00407 RescTypeDef[rescTypeInx].rescCat);
00408 status = SYS_INVALID_RESC_TYPE;
00409 break;
00410 }
00411 }
00412 return (status);
00413 }
00414
00415 int
00416 rsMvDataObjToTrash (rsComm_t *rsComm, dataObjInp_t *dataObjInp,
00417 dataObjInfo_t **dataObjInfoHead)
00418 {
00419 int status;
00420 char trashPath[MAX_NAME_LEN];
00421 dataObjCopyInp_t dataObjRenameInp;
00422
00423 if (strstr ((*dataObjInfoHead)->dataType, BUNDLE_STR) != NULL) {
00424 return SYS_CANT_MV_BUNDLE_DATA_TO_TRASH;
00425 }
00426
00427 if (getValByKey (&dataObjInp->condInput, DATA_ACCESS_KW) == NULL) {
00428 addKeyVal (&dataObjInp->condInput, DATA_ACCESS_KW,
00429 ACCESS_DELETE_OBJECT);
00430 }
00431
00432 status = getDataObjInfo (rsComm, dataObjInp, dataObjInfoHead,
00433 ACCESS_DELETE_OBJECT, 0);
00434
00435 if (status < 0) {
00436 rodsLog (LOG_NOTICE,
00437 "rsMvDataObjToTrash: getDataObjInfo error for %s. status = %d",
00438 dataObjInp->objPath, status);
00439 return (status);
00440 }
00441
00442 status = chkPreProcDeleteRule (rsComm, dataObjInp, *dataObjInfoHead);
00443 if (status < 0) return status;
00444
00445 #if 0
00446
00447 initReiWithDataObjInp (&rei, rsComm, dataObjInp);
00448 rei.doi = *dataObjInfoHead;
00449
00450 status = applyRule ("acDataDeletePolicy", NULL, &rei, NO_SAVE_REI);
00451
00452 if (status < 0 && status != NO_MORE_RULES_ERR &&
00453 status != SYS_DELETE_DISALLOWED) {
00454 rodsLog (LOG_NOTICE,
00455 "rsMvDataObjToTrash: acDataDeletePolicy error for %s. status = %d",
00456 dataObjInp->objPath, status);
00457 return (status);
00458 }
00459
00460 if (rei.status == SYS_DELETE_DISALLOWED) {
00461 rodsLog (LOG_NOTICE,
00462 "rsMvDataObjToTrash:disallowed for %s via DataDeletePolicy,status=%d",
00463 dataObjInp->objPath, rei.status);
00464 return (rei.status);
00465 }
00466 #endif
00467
00468 status = rsMkTrashPath (rsComm, dataObjInp->objPath, trashPath);
00469
00470 if (status < 0) {
00471 return (status);
00472 }
00473
00474 memset (&dataObjRenameInp, 0, sizeof (dataObjRenameInp));
00475
00476 dataObjRenameInp.srcDataObjInp.oprType =
00477 dataObjRenameInp.destDataObjInp.oprType = RENAME_DATA_OBJ;
00478
00479 rstrcpy (dataObjRenameInp.destDataObjInp.objPath, trashPath, MAX_NAME_LEN);
00480 rstrcpy (dataObjRenameInp.srcDataObjInp.objPath, dataObjInp->objPath,
00481 MAX_NAME_LEN);
00482
00483 status = rsDataObjRename (rsComm, &dataObjRenameInp);
00484
00485 while (status == CAT_NAME_EXISTS_AS_DATAOBJ ||
00486 status == CAT_NAME_EXISTS_AS_COLLECTION ||
00487 status == SYS_PHY_PATH_INUSE ||
00488 getErrno (status) == EISDIR) {
00489 appendRandomToPath (dataObjRenameInp.destDataObjInp.objPath);
00490 status = rsDataObjRename (rsComm, &dataObjRenameInp);
00491 #if 0
00492 if (status1 < 0) {
00493 rodsLog (LOG_ERROR,
00494 "rsMvDataObjToTrash: rsDataObjRename error for %s",
00495 dataObjRenameInp.destDataObjInp.objPath);
00496 } else {
00497 status = 0;
00498 }
00499 #endif
00500 }
00501 if (status < 0) {
00502 rodsLog (LOG_ERROR,
00503 "rsMvDataObjToTrash: rcDataObjRename error for %s, status = %d",
00504 dataObjRenameInp.destDataObjInp.objPath, status);
00505 return (status);
00506 }
00507 return (status);
00508 }
00509
00510 int
00511 chkPreProcDeleteRule (rsComm_t *rsComm, dataObjInp_t *dataObjUnlinkInp,
00512 dataObjInfo_t *dataObjInfoHead)
00513 {
00514 dataObjInfo_t *tmpDataObjInfo;
00515 ruleExecInfo_t rei;
00516 int status = 0;
00517
00518 initReiWithDataObjInp (&rei, rsComm, dataObjUnlinkInp);
00519 tmpDataObjInfo = dataObjInfoHead;
00520 while (tmpDataObjInfo != NULL) {
00521
00522 rei.doi = tmpDataObjInfo;
00523
00524 status = applyRule ("acDataDeletePolicy", NULL, &rei, NO_SAVE_REI);
00525
00526 if (status < 0 && status != NO_MORE_RULES_ERR &&
00527 status != SYS_DELETE_DISALLOWED) {
00528 rodsLog (LOG_ERROR,
00529 "chkPreProcDeleteRule: acDataDeletePolicy err for %s. stat = %d",
00530 dataObjUnlinkInp->objPath, status);
00531 return (status);
00532 }
00533
00534 if (rei.status == SYS_DELETE_DISALLOWED) {
00535 rodsLog (LOG_ERROR,
00536 "chkPreProcDeleteRule:acDataDeletePolicy disallowed delete of %s",
00537 dataObjUnlinkInp->objPath);
00538 return (rei.status);
00539 }
00540 tmpDataObjInfo = tmpDataObjInfo->next;
00541 }
00542 return status;
00543 }