int resolveLinkedPath( rsComm_t *rsComm, char *objPath, specCollCache_t **specCollCache, keyValPair_t *condInput ) { int linkCnt = 0; specColl_t *curSpecColl; char prevNewPath[MAX_NAME_LEN]; specCollCache_t *oldSpecCollCache = NULL; int status; *specCollCache = NULL; if ( getValByKey( condInput, TRANSLATED_PATH_KW ) != NULL ) { return 0; } addKeyVal( condInput, TRANSLATED_PATH_KW, "" ); while ( getSpecCollCache( rsComm, objPath, 0, specCollCache ) >= 0 && ( *specCollCache )->specColl.collClass == LINKED_COLL ) { oldSpecCollCache = *specCollCache; if ( linkCnt++ >= MAX_LINK_CNT ) { rodsLog( LOG_ERROR, "resolveLinkedPath: linkCnt for %s exceeds %d", objPath, MAX_LINK_CNT ); return SYS_LINK_CNT_EXCEEDED_ERR; } curSpecColl = &( *specCollCache )->specColl; if ( strcmp( curSpecColl->collection, objPath ) == 0 && getValByKey( condInput, NO_TRANSLATE_LINKPT_KW ) != NULL ) { return 0; } rstrcpy( prevNewPath, objPath, MAX_NAME_LEN ); status = getMountedSubPhyPath( curSpecColl->collection, curSpecColl->phyPath, prevNewPath, objPath ); if ( status < 0 ) { return status; } } if ( *specCollCache == NULL ) { *specCollCache = oldSpecCollCache; } return linkCnt; }
int _rsObjStat (rsComm_t *rsComm, dataObjInp_t *dataObjInp, rodsObjStat_t **rodsObjStatOut) { int status; char *tmpStr; specCollCache_t *specCollCache; /* do data first to catch data registered in spec Coll */ if ((tmpStr = getValByKey (&dataObjInp->condInput, SEL_OBJ_TYPE_KW)) == NULL || strcmp (tmpStr, "dataObj") == 0) { status = dataObjStat (rsComm, dataObjInp, rodsObjStatOut); if (status >= 0) return (status); } if (tmpStr == NULL || strcmp (tmpStr, "collection") == 0) { status = collStat (rsComm, dataObjInp, rodsObjStatOut); /* specColl may already been obtained from collStat */ if (status >= 0) { if ((*rodsObjStatOut)->specColl == NULL) { if (getSpecCollCache (rsComm, dataObjInp->objPath, 0, &specCollCache) >= 0) { replSpecColl (&specCollCache->specColl, &(*rodsObjStatOut)->specColl); } } return (status); } } /* not normal dataObj or coll. now check specColl */ /* XXXX need to check a rule if it supports spec collection */ status = statPathInSpecColl (rsComm, dataObjInp->objPath, 0, rodsObjStatOut); /* use USER_FILE_DOES_NOT_EXIST instead of OBJ_PATH_DOES_NOT_EXIST * because icommand depends on it */ if (status < 0) status = USER_FILE_DOES_NOT_EXIST; return (status); }
int rsGetHostForGet (rsComm_t *rsComm, dataObjInp_t *dataObjInp, char **outHost) { int status; rescInfo_t *myRescInfo; char *myResc; rodsServerHost_t *rodsServerHost; rodsHostAddr_t addr; specCollCache_t *specCollCache = NULL; char *myHost; int remoteFlag; *outHost = NULL; #if 0 if (isLocalZone (dataObjInp->objPath) == 0) { /* it is a remote zone. better connect to this host */ *outHost = strdup (THIS_ADDRESS); return 0; } #endif resolveLinkedPath (rsComm, dataObjInp->objPath, &specCollCache, NULL); if (isLocalZone (dataObjInp->objPath) == 0) { #if 0 /* it is a remote zone. better connect to this host */ *outHost = strdup (THIS_ADDRESS); return 0; #else resolveLinkedPath (rsComm, dataObjInp->objPath, &specCollCache, &dataObjInp->condInput); remoteFlag = getAndConnRcatHost (rsComm, SLAVE_RCAT, dataObjInp->objPath, &rodsServerHost); if (remoteFlag < 0) { return (remoteFlag); } else if (remoteFlag == LOCAL_HOST) { *outHost = strdup (THIS_ADDRESS); return 0; } else { status = rcGetHostForGet (rodsServerHost->conn, dataObjInp, outHost); if (status >= 0 && *outHost != NULL && strcmp (*outHost, THIS_ADDRESS) == 0) { free (*outHost); *outHost = strdup (rodsServerHost->hostName->name); } return (status); } #endif } status = getSpecCollCache (rsComm, dataObjInp->objPath, 0, &specCollCache); if (status >= 0) { if (specCollCache->specColl.collClass == MOUNTED_COLL) { status = resolveResc (specCollCache->specColl.resource, &myRescInfo); if (status < 0) { rodsLog (LOG_ERROR, "rsGetHostForGet: resolveResc error for %s, status = %d", specCollCache->specColl.resource, status); return status; } /* mounted coll will fall through with myRescInfo */ } else { *outHost = strdup (THIS_ADDRESS); return 0; } } else if ((myResc = getValByKey (&dataObjInp->condInput, RESC_NAME_KW)) != NULL && resolveResc (myResc, &myRescInfo) >= 0) { /* user specified a resource. myRescInfo set and fall through */ } else { /* normal type */ status = getBestRescForGet (rsComm, dataObjInp, &myRescInfo); if (myRescInfo == NULL) { *outHost = strdup (THIS_ADDRESS); return status; } } /* get down here when we got a valid myRescInfo */ if (getRescClass (myRescInfo) == COMPOUND_CL) { *outHost = strdup (THIS_ADDRESS); return 0; } bzero (&addr, sizeof (addr)); rstrcpy (addr.hostAddr, myRescInfo->rescLoc, NAME_LEN); status = resolveHost (&addr, &rodsServerHost); if (status < 0) return status; if (rodsServerHost->localFlag == LOCAL_HOST) { *outHost = strdup (THIS_ADDRESS); return 0; } myHost = getSvrAddr (rodsServerHost); if (myHost != NULL) { *outHost = strdup (myHost); return 0; } else { *outHost = NULL; return SYS_INVALID_SERVER_HOST; } }
/* resolvePathInSpecColl - given the object path in dataObjInp->objPath, see if * it is in the path of a special collection (mounted or structfile). * If it is not in a special collection, returns a -ive value. * The inCachOnly flag asks it to check the specColl in the global cache only * If it is, returns a dataObjInfo struct with dataObjInfo->specColl != NULL. * Returns COLL_OBJ_T if the path is a collection or DATA_OBJ_T if the * path is a data oobject. */ int resolvePathInSpecColl( rsComm_t *rsComm, char *objPath, specCollPerm_t specCollPerm, int inCachOnly, dataObjInfo_t **dataObjInfo ) { specCollCache_t *specCollCache; specColl_t *cachedSpecColl; int status; char *accessStr; if ( objPath == NULL ) { return SYS_INTERNAL_NULL_INPUT_ERR; } if ( ( status = getSpecCollCache( rsComm, objPath, inCachOnly, &specCollCache ) ) < 0 ) { return status; } else { cachedSpecColl = &specCollCache->specColl; } if ( specCollPerm != UNKNOWN_COLL_PERM ) { if ( specCollPerm == WRITE_COLL_PERM ) { accessStr = ACCESS_DELETE_OBJECT; } else { accessStr = ACCESS_READ_OBJECT; } if ( specCollCache->perm < specCollPerm ) { status = checkCollAccessPerm( rsComm, cachedSpecColl->collection, accessStr ); if ( status < 0 ) { rodsLog( LOG_ERROR, "resolvePathInSpecColl:checkCollAccessPerm err for %s,stat=%d", cachedSpecColl->collection, status ); return status; } else { specCollCache->perm = specCollPerm; } } } status = specCollSubStat( rsComm, cachedSpecColl, objPath, specCollPerm, dataObjInfo ); if ( status < 0 ) { if ( *dataObjInfo != NULL ) { /* does not exist. return the dataObjInfo anyway */ return SYS_SPEC_COLL_OBJ_NOT_EXIST; } rodsLog( LOG_ERROR, "resolvePathInSpecColl: specCollSubStat error for %s, status = %d", objPath, status ); return status; } else { if ( *dataObjInfo != NULL ) { if ( specCollPerm == WRITE_COLL_PERM ) { ( *dataObjInfo )->writeFlag = 1; } } } return status; }
int statPathInSpecColl( rsComm_t *rsComm, char *objPath, int inCachOnly, rodsObjStat_t **rodsObjStatOut ) { int status; dataObjInfo_t *dataObjInfo = NULL; specColl_t *specColl; specCollCache_t *specCollCache; if ( ( status = getSpecCollCache( rsComm, objPath, inCachOnly, &specCollCache ) ) < 0 ) { if ( status != SYS_SPEC_COLL_NOT_IN_CACHE && status != CAT_NO_ROWS_FOUND ) { rodsLog( LOG_ERROR, "statPathInSpecColl: getSpecCollCache for %s, status = %d", objPath, status ); } return status; } if ( *rodsObjStatOut == NULL ) { *rodsObjStatOut = ( rodsObjStat_t * ) malloc( sizeof( rodsObjStat_t ) ); } memset( *rodsObjStatOut, 0, sizeof( rodsObjStat_t ) ); specColl = &specCollCache->specColl; rstrcpy( ( *rodsObjStatOut )->dataId, specCollCache->collId, NAME_LEN ); rstrcpy( ( *rodsObjStatOut )->ownerName, specCollCache->ownerName, NAME_LEN ); rstrcpy( ( *rodsObjStatOut )->ownerZone, specCollCache->ownerZone, NAME_LEN ); status = specCollSubStat( rsComm, specColl, objPath, UNKNOWN_COLL_PERM, &dataObjInfo ); if ( status < 0 ) { if ( dataObjInfo != NULL ) { if ( dataObjInfo->specColl != NULL ) { ( *rodsObjStatOut )->specColl = dataObjInfo->specColl; } else { replSpecColl( &specCollCache->specColl, &( *rodsObjStatOut )->specColl ); } if ( specColl->collClass == LINKED_COLL ) { rstrcpy( ( *rodsObjStatOut )->specColl->objPath, dataObjInfo->objPath, MAX_NAME_LEN ); } else { ( *rodsObjStatOut )->specColl->objPath[0] = '\0'; } dataObjInfo->specColl = NULL; } ( *rodsObjStatOut )->objType = UNKNOWN_OBJ_T; rstrcpy( ( *rodsObjStatOut )->createTime, specCollCache->createTime, TIME_LEN ); rstrcpy( ( *rodsObjStatOut )->modifyTime, specCollCache->modifyTime, TIME_LEN ); freeAllDataObjInfo( dataObjInfo ); /* XXXXX 0 return is creating a problem for fuse */ return 0; } else { ( *rodsObjStatOut )->specColl = dataObjInfo->specColl; dataObjInfo->specColl = NULL; if ( specColl->collClass == LINKED_COLL ) { rstrcpy( ( *rodsObjStatOut )->ownerName, dataObjInfo->dataOwnerName, NAME_LEN ); rstrcpy( ( *rodsObjStatOut )->ownerZone, dataObjInfo->dataOwnerZone, NAME_LEN ); snprintf( ( *rodsObjStatOut )->dataId, NAME_LEN, "%lld", dataObjInfo->dataId ); /* save the linked path here */ rstrcpy( ( *rodsObjStatOut )->specColl->objPath, dataObjInfo->objPath, MAX_NAME_LEN ); } ( *rodsObjStatOut )->objType = ( objType_t )status; ( *rodsObjStatOut )->objSize = dataObjInfo->dataSize; rstrcpy( ( *rodsObjStatOut )->createTime, dataObjInfo->dataCreate, TIME_LEN ); rstrcpy( ( *rodsObjStatOut )->modifyTime, dataObjInfo->dataModify, TIME_LEN ); freeAllDataObjInfo( dataObjInfo ); } return status; }
int linkCollReg (rsComm_t *rsComm, dataObjInp_t *phyPathRegInp) { collInp_t collCreateInp; int status; char *linkPath = NULL; char *collType; int len; rodsObjStat_t *rodsObjStatOut = NULL; specCollCache_t *specCollCache = NULL; if ((linkPath = getValByKey (&phyPathRegInp->condInput, FILE_PATH_KW)) == NULL) { rodsLog (LOG_ERROR, "linkCollReg: No linkPath input for %s", phyPathRegInp->objPath); return (SYS_INVALID_FILE_PATH); } collType = getValByKey (&phyPathRegInp->condInput, COLLECTION_TYPE_KW); if (collType == NULL || strcmp (collType, LINK_POINT_STR) != 0) { rodsLog (LOG_ERROR, "linkCollReg: Bad COLLECTION_TYPE_KW for linkPath %s", phyPathRegInp->objPath); return (SYS_INTERNAL_NULL_INPUT_ERR); } if (phyPathRegInp->objPath[0] != '/' || linkPath[0] != '/') { rodsLog (LOG_ERROR, "linkCollReg: linkPath %s or collection %s not absolute path", linkPath, phyPathRegInp->objPath); return (SYS_COLL_LINK_PATH_ERR); } len = strlen (phyPathRegInp->objPath); if (strncmp (linkPath, phyPathRegInp->objPath, len) == 0 && linkPath[len] == '/') { rodsLog (LOG_ERROR, "linkCollReg: linkPath %s inside collection %s", linkPath, phyPathRegInp->objPath); return (SYS_COLL_LINK_PATH_ERR); } len = strlen (linkPath); if (strncmp (phyPathRegInp->objPath, linkPath, len) == 0 && phyPathRegInp->objPath[len] == '/') { rodsLog (LOG_ERROR, "linkCollReg: collection %s inside linkPath %s", linkPath, phyPathRegInp->objPath); return (SYS_COLL_LINK_PATH_ERR); } if (getSpecCollCache (rsComm, linkPath, 0, &specCollCache) >= 0 && specCollCache->specColl.collClass != LINKED_COLL) { rodsLog (LOG_ERROR, "linkCollReg: linkPath %s is in a spec coll path", linkPath); return (SYS_COLL_LINK_PATH_ERR); } status = collStat (rsComm, phyPathRegInp, &rodsObjStatOut); if (status < 0) { /* does not exist. make one */ collInp_t collCreateInp; memset (&collCreateInp, 0, sizeof (collCreateInp)); rstrcpy (collCreateInp.collName, phyPathRegInp->objPath, MAX_NAME_LEN); status = rsRegColl (rsComm, &collCreateInp); if (status < 0) { rodsLog (LOG_ERROR, "linkCollReg: rsRegColl error for %s, status = %d", collCreateInp.collName, status); return status; } status = collStat (rsComm, phyPathRegInp, &rodsObjStatOut); if (status < 0) return status; } if (rodsObjStatOut->specColl != NULL && rodsObjStatOut->specColl->collClass != LINKED_COLL) { freeRodsObjStat (rodsObjStatOut); rodsLog (LOG_ERROR, "linkCollReg: link collection %s in a spec coll path", phyPathRegInp->objPath); return (SYS_COLL_LINK_PATH_ERR); } freeRodsObjStat (rodsObjStatOut); if (isCollEmpty (rsComm, phyPathRegInp->objPath) == False) { rodsLog (LOG_ERROR, "linkCollReg: collection %s not empty", phyPathRegInp->objPath); return (SYS_COLLECTION_NOT_EMPTY); } /* mk the collection */ memset (&collCreateInp, 0, sizeof (collCreateInp)); rstrcpy (collCreateInp.collName, phyPathRegInp->objPath, MAX_NAME_LEN); addKeyVal (&collCreateInp.condInput, COLLECTION_TYPE_KW, collType); /* have to use dataObjInp.objPath because structFile path was removed */ addKeyVal (&collCreateInp.condInput, COLLECTION_INFO1_KW, linkPath); /* try to mod the coll first */ status = rsModColl (rsComm, &collCreateInp); if (status < 0) { /* try to create it */ status = rsRegColl (rsComm, &collCreateInp); } return (status); }
int structFileReg (rsComm_t *rsComm, dataObjInp_t *phyPathRegInp) { collInp_t collCreateInp; int status; dataObjInfo_t *dataObjInfo = NULL; char *structFilePath = NULL; dataObjInp_t dataObjInp; char *collType; int len; rodsObjStat_t *rodsObjStatOut = NULL; specCollCache_t *specCollCache = NULL; rescInfo_t *rescInfo = NULL; #if 0 /* fixed */ /* make it a privileged call for now */ if (rsComm->clientUser.authInfo.authFlag < LOCAL_PRIV_USER_AUTH) return(CAT_INSUFFICIENT_PRIVILEGE_LEVEL); #endif if ((structFilePath = getValByKey (&phyPathRegInp->condInput, FILE_PATH_KW)) == NULL) { rodsLog (LOG_ERROR, "structFileReg: No structFilePath input for %s", phyPathRegInp->objPath); return (SYS_INVALID_FILE_PATH); } collType = getValByKey (&phyPathRegInp->condInput, COLLECTION_TYPE_KW); if (collType == NULL) { rodsLog (LOG_ERROR, "structFileReg: Bad COLLECTION_TYPE_KW for structFilePath %s", dataObjInp.objPath); return (SYS_INTERNAL_NULL_INPUT_ERR); } len = strlen (phyPathRegInp->objPath); if (strncmp (structFilePath, phyPathRegInp->objPath, len) == 0 && (structFilePath[len] == '\0' || structFilePath[len] == '/')) { rodsLog (LOG_ERROR, "structFileReg: structFilePath %s inside collection %s", structFilePath, phyPathRegInp->objPath); return (SYS_STRUCT_FILE_INMOUNTED_COLL); } /* see if the struct file is in spec coll */ if (getSpecCollCache (rsComm, structFilePath, 0, &specCollCache) >= 0) { rodsLog (LOG_ERROR, "structFileReg: structFilePath %s is in a mounted path", structFilePath); return (SYS_STRUCT_FILE_INMOUNTED_COLL); } status = collStat (rsComm, phyPathRegInp, &rodsObjStatOut); if (status < 0) return status; if (rodsObjStatOut->specColl != NULL) { freeRodsObjStat (rodsObjStatOut); rodsLog (LOG_ERROR, "structFileReg: %s already mounted", phyPathRegInp->objPath); return (SYS_MOUNT_MOUNTED_COLL_ERR); } freeRodsObjStat (rodsObjStatOut); if (isCollEmpty (rsComm, phyPathRegInp->objPath) == False) { rodsLog (LOG_ERROR, "structFileReg: collection %s not empty", phyPathRegInp->objPath); return (SYS_COLLECTION_NOT_EMPTY); } memset (&dataObjInp, 0, sizeof (dataObjInp)); rstrcpy (dataObjInp.objPath, structFilePath, sizeof (dataObjInp)); /* user need to have write permission */ dataObjInp.openFlags = O_WRONLY; status = getDataObjInfoIncSpecColl (rsComm, &dataObjInp, &dataObjInfo); if (status < 0) { int myStatus; /* try to make one */ dataObjInp.condInput = phyPathRegInp->condInput; /* have to remove FILE_PATH_KW because getFullPathName will use it */ rmKeyVal (&dataObjInp.condInput, FILE_PATH_KW); myStatus = rsDataObjCreate (rsComm, &dataObjInp); if (myStatus < 0) { rodsLog (LOG_ERROR, "structFileReg: Problem with open/create structFilePath %s, status = %d", dataObjInp.objPath, status); return (status); } else { openedDataObjInp_t dataObjCloseInp; bzero (&dataObjCloseInp, sizeof (dataObjCloseInp)); rescInfo = L1desc[myStatus].dataObjInfo->rescInfo; dataObjCloseInp.l1descInx = myStatus; rsDataObjClose (rsComm, &dataObjCloseInp); } } else { rescInfo = dataObjInfo->rescInfo; } if (!structFileSupport (rsComm, phyPathRegInp->objPath, collType, rescInfo)) { rodsLog (LOG_ERROR, "structFileReg: structFileDriver type %s does not exist for %s", collType, dataObjInp.objPath); return (SYS_NOT_SUPPORTED); } /* mk the collection */ memset (&collCreateInp, 0, sizeof (collCreateInp)); rstrcpy (collCreateInp.collName, phyPathRegInp->objPath, MAX_NAME_LEN); addKeyVal (&collCreateInp.condInput, COLLECTION_TYPE_KW, collType); /* have to use dataObjInp.objPath because structFile path was removed */ addKeyVal (&collCreateInp.condInput, COLLECTION_INFO1_KW, dataObjInp.objPath); /* try to mod the coll first */ status = rsModColl (rsComm, &collCreateInp); if (status < 0) { /* try to create it */ status = rsRegColl (rsComm, &collCreateInp); } return (status); }
int rsGetHostForPut (rsComm_t *rsComm, dataObjInp_t *dataObjInp, char **outHost) { int status; rescGrpInfo_t *myRescGrpInfo; rescInfo_t *myRescInfo; rodsServerHost_t *rodsServerHost; rodsHostAddr_t addr; specCollCache_t *specCollCache = NULL; char *myHost; int remoteFlag; *outHost = NULL; #if 0 if (isLocalZone (dataObjInp->objPath) == 0) { /* it is a remote zone. better connect to this host */ *outHost = strdup (THIS_ADDRESS); return 0; } #endif if (getValByKey (&dataObjInp->condInput, ALL_KW) != NULL || getValByKey (&dataObjInp->condInput, FORCE_FLAG_KW) != NULL) { /* going to ALL copies or overwriting files. not sure which is the * best */ *outHost = strdup (THIS_ADDRESS); return 0; } resolveLinkedPath (rsComm, dataObjInp->objPath, &specCollCache, NULL); if (isLocalZone (dataObjInp->objPath) == 0) { #if 0 /* it is a remote zone. better connect to this host */ *outHost = strdup (THIS_ADDRESS); return 0; #else resolveLinkedPath (rsComm, dataObjInp->objPath, &specCollCache, &dataObjInp->condInput); remoteFlag = getAndConnRcatHost (rsComm, SLAVE_RCAT, dataObjInp->objPath, &rodsServerHost); if (remoteFlag < 0) { return (remoteFlag); } else if (remoteFlag == LOCAL_HOST) { *outHost = strdup (THIS_ADDRESS); return 0; } else { status = rcGetHostForPut (rodsServerHost->conn, dataObjInp, outHost); if (status >= 0 && *outHost != NULL && strcmp (*outHost, THIS_ADDRESS) == 0) { free (*outHost); *outHost = strdup (rodsServerHost->hostName->name); } return (status); } #endif } status = getSpecCollCache (rsComm, dataObjInp->objPath, 0, &specCollCache); if (status >= 0) { if (specCollCache->specColl.collClass == MOUNTED_COLL) { status = resolveResc (specCollCache->specColl.resource, &myRescInfo); if (status < 0) { rodsLog (LOG_ERROR, "rsGetHostForPut: resolveResc error for %s, status = %d", specCollCache->specColl.resource, status); return status; } /* mounted coll will fall through */ } else { *outHost = strdup (THIS_ADDRESS); return 0; } } else { /* normal type */ status = getRescGrpForCreate (rsComm, dataObjInp, &myRescGrpInfo); if (status < 0) return status; myRescInfo = myRescGrpInfo->rescInfo; freeAllRescGrpInfo (myRescGrpInfo); /* status == 1 means random sorting scheme */ if ((status == 1 && getRescCnt (myRescGrpInfo) > 1) || getRescClass (myRescInfo) == COMPOUND_CL) { *outHost = strdup (THIS_ADDRESS); return 0; } } /* get down here when we got a valid myRescInfo */ bzero (&addr, sizeof (addr)); rstrcpy (addr.hostAddr, myRescInfo->rescLoc, NAME_LEN); status = resolveHost (&addr, &rodsServerHost); if (status < 0) return status; if (rodsServerHost->localFlag == LOCAL_HOST) { *outHost = strdup (THIS_ADDRESS); return 0; } myHost = getSvrAddr (rodsServerHost); if (myHost != NULL) { *outHost = strdup (myHost); return 0; } else { *outHost = NULL; return SYS_INVALID_SERVER_HOST; } }