int
rsOpenCollection (rsComm_t *rsComm, collInp_t *openCollInp)
{
    int status;
    int handleInx;
    collHandle_t *collHandle;
    rodsObjStat_t *rodsObjStatOut = NULL;

    handleInx = allocCollHandle ();

    if (handleInx < 0) return (handleInx);

    collHandle = &CollHandle[handleInx];

    status = rsInitQueryHandle (&collHandle->queryHandle, rsComm);
   
    if (status < 0) return status;

    rstrcpy (collHandle->dataObjInp.objPath, openCollInp->collName, 
      MAX_NAME_LEN);
    if ((openCollInp->flags & INCLUDE_CONDINPUT_IN_QUERY) != 0) {
	replKeyVal (&openCollInp->condInput, &collHandle->dataObjInp.condInput);
    }
    status = rsObjStat (rsComm, &collHandle->dataObjInp, &rodsObjStatOut);


    if (status < 0) {
	rsCloseCollection (rsComm, &handleInx);
	return status;
    }

    if (rodsObjStatOut->objType != COLL_OBJ_T) {
	freeRodsObjStat (rodsObjStatOut);
	rsCloseCollection (rsComm, &handleInx);
	return CAT_NAME_EXISTS_AS_DATAOBJ;
    }

#if 0
    collHandle->dataObjInp.specColl = rodsObjStatOut->specColl;
#else
    replSpecColl (rodsObjStatOut->specColl, &collHandle->dataObjInp.specColl);
#endif
    if (rodsObjStatOut->specColl != NULL &&
      rodsObjStatOut->specColl->collClass == LINKED_COLL) {
	/* save the linked path */
	rstrcpy (collHandle->linkedObjPath, rodsObjStatOut->specColl->objPath,
	  MAX_NAME_LEN);
    };

    collHandle->rodsObjStat = rodsObjStatOut;

    collHandle->state = COLL_OPENED;
    collHandle->flags = openCollInp->flags;
    /* the collection exist. now query the data in it */
    return (handleInx);
}
示例#2
0
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);
}
示例#3
0
文件: collection.cpp 项目: bpow/irods
int
collStat( rsComm_t *rsComm, dataObjInp_t *dataObjInp,
          rodsObjStat_t **rodsObjStatOut ) {
    genQueryInp_t genQueryInp;
    genQueryOut_t *genQueryOut = NULL;
    int status;
    char condStr[MAX_NAME_LEN];
    sqlResult_t *dataId;
    sqlResult_t *ownerName;
    sqlResult_t *ownerZone;
    sqlResult_t *createTime;
    sqlResult_t *modifyTime;
    sqlResult_t *collType;
    sqlResult_t *collInfo1;
    sqlResult_t *collInfo2;

    /* see if objPath is a collection */
    memset( &genQueryInp, 0, sizeof( genQueryInp ) );

    snprintf( condStr, MAX_NAME_LEN, "='%s'", dataObjInp->objPath );
    addInxVal( &genQueryInp.sqlCondInp, COL_COLL_NAME, condStr );

    addInxIval( &genQueryInp.selectInp, COL_COLL_ID, 1 );
    /* XXXX COL_COLL_NAME added for queueSpecColl */
    addInxIval( &genQueryInp.selectInp, COL_COLL_NAME, 1 );
    addInxIval( &genQueryInp.selectInp, COL_COLL_OWNER_NAME, 1 );
    addInxIval( &genQueryInp.selectInp, COL_COLL_OWNER_ZONE, 1 );
    addInxIval( &genQueryInp.selectInp, COL_COLL_CREATE_TIME, 1 );
    addInxIval( &genQueryInp.selectInp, COL_COLL_MODIFY_TIME, 1 );
    /* XXXX may want to do this if spec coll is supported */
    addInxIval( &genQueryInp.selectInp, COL_COLL_TYPE, 1 );
    addInxIval( &genQueryInp.selectInp, COL_COLL_INFO1, 1 );
    addInxIval( &genQueryInp.selectInp, COL_COLL_INFO2, 1 );

    genQueryInp.maxRows = MAX_SQL_ROWS;

    status =  rsGenQuery( rsComm, &genQueryInp, &genQueryOut );
    if ( status >= 0 ) {
        *rodsObjStatOut = ( rodsObjStat_t * ) malloc( sizeof( rodsObjStat_t ) );
        memset( *rodsObjStatOut, 0, sizeof( rodsObjStat_t ) );
        ( *rodsObjStatOut )->objType = COLL_OBJ_T;
        status = ( int )COLL_OBJ_T;
        if ( ( dataId = getSqlResultByInx( genQueryOut,
                                           COL_COLL_ID ) ) == NULL ) {
            rodsLog( LOG_ERROR,
                     "_rsObjStat: getSqlResultByInx for COL_COLL_ID failed" );
            return UNMATCHED_KEY_OR_INDEX;
        }
        else if ( ( ownerName = getSqlResultByInx( genQueryOut,
                                COL_COLL_OWNER_NAME ) ) == NULL ) {
            rodsLog( LOG_ERROR,
                     "_rsObjStat:getSqlResultByInx for COL_COLL_OWNER_NAME failed" );
            return UNMATCHED_KEY_OR_INDEX;
        }
        else if ( ( ownerZone = getSqlResultByInx( genQueryOut,
                                COL_COLL_OWNER_ZONE ) ) == NULL ) {
            rodsLog( LOG_ERROR,
                     "_rsObjStat:getSqlResultByInx for COL_COLL_OWNER_ZONE failed" );
            return UNMATCHED_KEY_OR_INDEX;
        }
        else if ( ( createTime = getSqlResultByInx( genQueryOut,
                                 COL_COLL_CREATE_TIME ) ) == NULL ) {
            rodsLog( LOG_ERROR,
                     "_rsObjStat:getSqlResultByInx for COL_COLL_CREATE_TIME failed" );
            return UNMATCHED_KEY_OR_INDEX;
        }
        else if ( ( modifyTime = getSqlResultByInx( genQueryOut,
                                 COL_COLL_MODIFY_TIME ) ) == NULL ) {
            rodsLog( LOG_ERROR,
                     "_rsObjStat:getSqlResultByInx for COL_COLL_MODIFY_TIME failed" );
            return UNMATCHED_KEY_OR_INDEX;
        }
        else if ( ( collType = getSqlResultByInx( genQueryOut,
                               COL_COLL_TYPE ) ) == NULL ) {
            rodsLog( LOG_ERROR,
                     "_rsObjStat:getSqlResultByInx for COL_COLL_TYPE failed" );
            return UNMATCHED_KEY_OR_INDEX;
        }
        else if ( ( collInfo1 = getSqlResultByInx( genQueryOut,
                                COL_COLL_INFO1 ) ) == NULL ) {
            rodsLog( LOG_ERROR,
                     "_rsObjStat:getSqlResultByInx for COL_COLL_INFO1 failed" );
            return UNMATCHED_KEY_OR_INDEX;
        }
        else if ( ( collInfo2 = getSqlResultByInx( genQueryOut,
                                COL_COLL_INFO2 ) ) == NULL ) {
            rodsLog( LOG_ERROR,
                     "_rsObjStat:getSqlResultByInx for COL_COLL_INFO2 failed" );
            return UNMATCHED_KEY_OR_INDEX;
        }
        else {
            rstrcpy( ( *rodsObjStatOut )->dataId, dataId->value, NAME_LEN );
            rstrcpy( ( *rodsObjStatOut )->ownerName, ownerName->value,
                     NAME_LEN );
            rstrcpy( ( *rodsObjStatOut )->ownerZone, ownerZone->value,
                     NAME_LEN );
            rstrcpy( ( *rodsObjStatOut )->createTime, createTime->value,
                     TIME_LEN );
            rstrcpy( ( *rodsObjStatOut )->modifyTime, modifyTime->value,
                     TIME_LEN );

            if ( strlen( collType->value ) > 0 ) {
                specCollCache_t *specCollCache = 0;

                if ( ( specCollCache =
                            matchSpecCollCache( dataObjInp->objPath ) ) != NULL ) {
                    replSpecColl( &specCollCache->specColl,
                                  &( *rodsObjStatOut )->specColl );
                }
                else {
                    status = queueSpecCollCache( rsComm, genQueryOut, // JMC - backport 4680?
                                                 dataObjInp->objPath );
                    if ( status < 0 ) {
                        return status;
                    }
                    replSpecColl( &SpecCollCacheHead->specColl,
                                  &( *rodsObjStatOut )->specColl );
                }


            }
        }
    }

    clearGenQueryInp( &genQueryInp );
    freeGenQueryOut( &genQueryOut );

    return status;
}
示例#4
0
文件: specColl.cpp 项目: bpow/irods
int
specCollSubStat( rsComm_t *rsComm, specColl_t *specColl,
                 char *subPath, specCollPerm_t specCollPerm, dataObjInfo_t **dataObjInfo ) {
    int status;
    int objType;
    rodsStat_t *rodsStat = NULL;
    dataObjInfo_t *myDataObjInfo = NULL;;

    if ( dataObjInfo == NULL ) {
        return USER__NULL_INPUT_ERR;
    }
    *dataObjInfo = NULL;

    if ( specColl->collClass == MOUNTED_COLL ) {
        /* a mount point */
        myDataObjInfo = *dataObjInfo = ( dataObjInfo_t * ) malloc( sizeof( dataObjInfo_t ) );

        memset( myDataObjInfo, 0, sizeof( dataObjInfo_t ) );

        /*status = resolveResc (specColl->resource, &myDataObjInfo->rescInfo);
        if (status < 0) {
            rodsLog( LOG_ERROR,"specCollSubStat: resolveResc error for %s, status = %d",
                     specColl->resource, status);
            freeDataObjInfo (myDataObjInfo);
            *dataObjInfo = NULL;
            return status;
        }*/

        rstrcpy( myDataObjInfo->objPath, subPath, MAX_NAME_LEN );
        rstrcpy( myDataObjInfo->subPath, subPath, MAX_NAME_LEN );
        rstrcpy( myDataObjInfo->rescName, specColl->resource, NAME_LEN );
        rstrcpy( myDataObjInfo->rescHier, specColl->rescHier, MAX_NAME_LEN );
        rstrcpy( myDataObjInfo->dataType, "generic", NAME_LEN );

        status = getMountedSubPhyPath( specColl->collection,
                                       specColl->phyPath, subPath, myDataObjInfo->filePath );
        if ( status < 0 ) {
            freeDataObjInfo( myDataObjInfo );
            *dataObjInfo = NULL;
            return status;
        }
        replSpecColl( specColl, &myDataObjInfo->specColl );
    }
    else if ( specColl->collClass == LINKED_COLL ) {

        /* a link point */
        specCollCache_t *specCollCache = NULL;
        char newPath[MAX_NAME_LEN];
        specColl_t *curSpecColl;
        char *accessStr;
        dataObjInp_t myDataObjInp;
        rodsObjStat_t *rodsObjStatOut = NULL;

        *dataObjInfo = NULL;
        curSpecColl = specColl;

        status = getMountedSubPhyPath( curSpecColl->collection,
                                       curSpecColl->phyPath, subPath, newPath );
        if ( status < 0 ) {
            return status;
        }

        status = resolveLinkedPath( rsComm, newPath, &specCollCache, NULL );
        if ( status < 0 ) {
            return status;
        }
        if ( specCollCache != NULL &&
                specCollCache->specColl.collClass != LINKED_COLL ) {

            status = specCollSubStat( rsComm, &specCollCache->specColl,
                                      newPath, specCollPerm, dataObjInfo );
            return status;
        }
        bzero( &myDataObjInp, sizeof( myDataObjInp ) );
        rstrcpy( myDataObjInp.objPath, newPath, MAX_NAME_LEN );

        status = collStat( rsComm, &myDataObjInp, &rodsObjStatOut );
        if ( status >= 0 && NULL != rodsObjStatOut ) {      /* a collection */ // JMC cppcheck - nullptr
            myDataObjInfo = *dataObjInfo =
                                ( dataObjInfo_t * ) malloc( sizeof( dataObjInfo_t ) );
            memset( myDataObjInfo, 0, sizeof( dataObjInfo_t ) );
            replSpecColl( curSpecColl, &myDataObjInfo->specColl );
            rstrcpy( myDataObjInfo->objPath, newPath, MAX_NAME_LEN );
            myDataObjInfo->dataId = strtoll( rodsObjStatOut->dataId, 0, 0 );
            rstrcpy( myDataObjInfo->dataOwnerName, rodsObjStatOut->ownerName, NAME_LEN );
            rstrcpy( myDataObjInfo->dataOwnerZone, rodsObjStatOut->ownerZone, NAME_LEN );
            rstrcpy( myDataObjInfo->dataCreate,    rodsObjStatOut->createTime, TIME_LEN );
            rstrcpy( myDataObjInfo->dataModify,    rodsObjStatOut->modifyTime, TIME_LEN );
            freeRodsObjStat( rodsObjStatOut );
            return COLL_OBJ_T;
        }
        freeRodsObjStat( rodsObjStatOut );

        /* data object */
        if ( specCollPerm == READ_COLL_PERM ) {
            accessStr = ACCESS_READ_OBJECT;
        }
        else if ( specCollPerm == WRITE_COLL_PERM ) {
            accessStr = ACCESS_DELETE_OBJECT;
        }
        else {
            accessStr = NULL;
        }

        status = getDataObjInfo( rsComm, &myDataObjInp, dataObjInfo,
                                 accessStr, 0 );
        if ( status < 0 ) {
            myDataObjInfo = *dataObjInfo =
                                ( dataObjInfo_t * ) malloc( sizeof( dataObjInfo_t ) );
            memset( myDataObjInfo, 0, sizeof( dataObjInfo_t ) );
            replSpecColl( curSpecColl, &myDataObjInfo->specColl );
            rstrcpy( myDataObjInfo->objPath, newPath, MAX_NAME_LEN );
            rodsLog( LOG_DEBUG,
                     "specCollSubStat: getDataObjInfo error for %s, status = %d",
                     newPath, status );
            return status;
        }
        else {
            replSpecColl( curSpecColl, &( *dataObjInfo )->specColl );
            return DATA_OBJ_T;
        }
    }
    else if ( getStructFileType( specColl ) >= 0 ) {

        /* bundle */
        dataObjInp_t myDataObjInp;
        dataObjInfo_t *tmpDataObjInfo;

        bzero( &myDataObjInp, sizeof( myDataObjInp ) );
        rstrcpy( myDataObjInp.objPath, specColl->objPath, MAX_NAME_LEN );
        // add the resource hierarchy to the condInput of the inp
        addKeyVal( &myDataObjInp.condInput, RESC_HIER_STR_KW, specColl->rescHier );
        status = getDataObjInfo( rsComm, &myDataObjInp, dataObjInfo, NULL, 1 );
        if ( status < 0 ) {
            rodsLog( LOG_ERROR,
                     "specCollSubStat: getDataObjInfo error for %s, status = %d",
                     myDataObjInp.objPath, status );
            *dataObjInfo = NULL;
            return status;
        }

        /* screen out any stale copies */
        status = sortObjInfoForOpen( dataObjInfo, &myDataObjInp.condInput, 0 );
        if ( status < 0 ) {
            rodsLog( LOG_ERROR,
                     "specCollSubStat: sortObjInfoForOpen error for %s. status = %d",
                     myDataObjInp.objPath, status );
            return status;
        }

        if ( strlen( specColl->resource ) > 0 ) {
            if ( requeDataObjInfoByResc( dataObjInfo, specColl->resource,
                                         0, 1 ) >= 0 ) {
                if ( strcmp( specColl->resource,
                             ( *dataObjInfo )->rescName ) != 0 ) {
                    rodsLog( LOG_ERROR,
                             "specCollSubStat: %s in %s does not match cache resc %s",
                             myDataObjInp.objPath, ( *dataObjInfo )->rescName,
                             specColl->resource );
                    freeAllDataObjInfo( *dataObjInfo );
                    *dataObjInfo = NULL;
                    return SYS_CACHE_STRUCT_FILE_RESC_ERR;
                }
            }
            else {
                rodsLog( LOG_ERROR,
                         "specCollSubStat: requeDataObjInfoByResc %s, resc %s error",
                         myDataObjInp.objPath, specColl->resource );
                freeAllDataObjInfo( *dataObjInfo );
                *dataObjInfo = NULL;
                return SYS_CACHE_STRUCT_FILE_RESC_ERR;
            }
        }

        /* free all the other dataObjInfo */
        if ( ( *dataObjInfo )->next != NULL ) {
            freeAllDataObjInfo( ( *dataObjInfo )->next );
            ( *dataObjInfo )->next = NULL;
        }

        /* fill in DataObjInfo */
        tmpDataObjInfo = *dataObjInfo;
        replSpecColl( specColl, &tmpDataObjInfo->specColl );
        rstrcpy( specColl->resource, tmpDataObjInfo->rescName, NAME_LEN );
        rstrcpy( specColl->rescHier, tmpDataObjInfo->rescHier, MAX_NAME_LEN );
        rstrcpy( specColl->phyPath, tmpDataObjInfo->filePath, MAX_NAME_LEN );
        rstrcpy( tmpDataObjInfo->subPath, subPath, MAX_NAME_LEN );
        specColl->replNum = tmpDataObjInfo->replNum;

        if ( strcmp( ( *dataObjInfo )->subPath, specColl->collection ) == 0 ) {
            /* no need to go down */
            return COLL_OBJ_T;
        }
    }
    else {
        rodsLog( LOG_ERROR,
                 "specCollSubStat: Unknown specColl collClass = %d",
                 specColl->collClass );
        return SYS_UNKNOWN_SPEC_COLL_CLASS;
    }
    status = l3Stat( rsComm, *dataObjInfo, &rodsStat );

    if ( status < 0 ) {
        return status;
    }

    if ( rodsStat->st_ctim != 0 ) {
        snprintf( ( *dataObjInfo )->dataCreate, TIME_LEN, "%d", rodsStat->st_ctim );
        snprintf( ( *dataObjInfo )->dataModify, TIME_LEN, "%d", rodsStat->st_mtim );
    }

    if ( rodsStat->st_mode & S_IFDIR ) {
        objType = COLL_OBJ_T;
    }
    else {
        objType = DATA_OBJ_T;
        ( *dataObjInfo )->dataSize = rodsStat->st_size;
    }
    free( rodsStat );

    return objType;
}
示例#5
0
文件: specColl.cpp 项目: bpow/irods
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;
}
示例#6
0
int
rsObjStat (rsComm_t *rsComm, dataObjInp_t *dataObjInp,
rodsObjStat_t **rodsObjStatOut)
{
    int status;
    rodsServerHost_t *rodsServerHost = NULL;
    specCollCache_t *specCollCache = NULL;
    int linkCnt;

    linkCnt = resolveLinkedPath (rsComm, dataObjInp->objPath, &specCollCache, 
      NULL);

    *rodsObjStatOut = NULL;
    status = getAndConnRcatHost (rsComm, SLAVE_RCAT, dataObjInp->objPath,
      &rodsServerHost);
    if (status < 0) {
       return(status);
    }
    if (rodsServerHost->localFlag == LOCAL_HOST) {
#ifdef RODS_CAT
        status = _rsObjStat (rsComm, dataObjInp, rodsObjStatOut);
#else
        status = SYS_NO_RCAT_SERVER_ERR;
#endif
    } else {
	if (isLocalZone (dataObjInp->objPath)) {
	    /* Since the iCat is on a remote host, see if it is a sub path of 
             * a cached specColl locally first. If it is, it will save time 
             * resolving it */
            status = statPathInSpecColl (rsComm, dataObjInp->objPath, 1,
              rodsObjStatOut);
	    if (status >= 0) {
		/* the path is in a specColl */
		return status;
	    } else if (status != SYS_SPEC_COLL_NOT_IN_CACHE) {
		/* path is in the path of specColl cache but does not exist */
                if (linkCnt > 0 && *rodsObjStatOut != NULL) {
		    /* a soft link - returns specColl */
                    if ((*rodsObjStatOut)->specColl == NULL) {
                        replSpecColl (&specCollCache->specColl,
                          &(*rodsObjStatOut)->specColl);
                    }
                    rstrcpy ((*rodsObjStatOut)->specColl->objPath, 
		      dataObjInp->objPath, MAX_NAME_LEN);
                }
		return status;
	    }
	    /* falls through if the path is not in a cached specColl */
	}
	/* not in cache, need to do a remote call */
        status = rcObjStat (rodsServerHost->conn, dataObjInp, 
	  rodsObjStatOut);
	if (status >= 0 && (*rodsObjStatOut)->specColl != NULL) {
	    /* queue it in cache */
	    queueSpecCollCacheWithObjStat (*rodsObjStatOut);
	}
    }

    if (linkCnt > 0 && *rodsObjStatOut != NULL) {
	/* fill in (*rodsObjStatOut)->specColl if it is linked */
        if ((*rodsObjStatOut)->specColl == NULL) {
            replSpecColl (&specCollCache->specColl,
              &(*rodsObjStatOut)->specColl);
	}
	rstrcpy ((*rodsObjStatOut)->specColl->objPath, dataObjInp->objPath, 
	  MAX_NAME_LEN);
    }
    return (status);
}