Exemple #1
0
int
getRescForGetInColl( rsComm_t *rsComm, collInp_t *collInp,
                     hostSearchStat_t *hostSearchStat ) {
    collEnt_t *collEnt;
    int handleInx;
    int status;

    if ( collInp == NULL || hostSearchStat == NULL ) {
        return USER__NULL_INPUT_ERR;
    }

    handleInx = rsOpenCollection( rsComm, collInp );
    if ( handleInx < 0 ) {
        return handleInx;
    }

    while ( ( status = rsReadCollection( rsComm, &handleInx, &collEnt ) ) >= 0 ) {
        if ( collEnt->objType == DATA_OBJ_T ) {
            dataObjInp_t dataObjInp;
            bzero( &dataObjInp, sizeof( dataObjInp ) );
            snprintf( dataObjInp.objPath, MAX_NAME_LEN, "%s/%s",
                      collEnt->collName, collEnt->dataName );
            status = getRescForGetInDataObj( rsComm, &dataObjInp,
                                             hostSearchStat );
            if ( status < 0 ) {
                rodsLog( LOG_NOTICE,
                         "getRescForGetInColl: getRescForGetInDataObj %s err, stat=%d",
                         dataObjInp.objPath, status );
            }
        }
        else if ( collEnt->objType == COLL_OBJ_T ) {
            collInp_t myCollInp;
            bzero( &myCollInp, sizeof( myCollInp ) );
            rstrcpy( myCollInp.collName, collEnt->collName, MAX_NAME_LEN );
            status = getRescForGetInColl( rsComm, &myCollInp, hostSearchStat );
            if ( status < 0 ) {
                rodsLog( LOG_NOTICE,
                         "getRescForGetInColl: getRescForGetInColl %s err, stat=%d",
                         collEnt->collName, status );
            }
        }
        free( collEnt );    /* just free collEnt but not content */
        if ( hostSearchStat->totalCount >= MAX_HOST_TO_SEARCH ) {
            /* done */
            rsCloseCollection( rsComm, &handleInx );
            return 0;
        }
    }
    rsCloseCollection( rsComm, &handleInx );
    return 0;
}
Exemple #2
0
int
isCollEmpty( rsComm_t *rsComm, char *collection ) {
    collInp_t openCollInp;
    collEnt_t *collEnt;
    int handleInx;
    int entCnt = 0;

    if ( rsComm == NULL || collection == NULL ) {
        rodsLog( LOG_ERROR,
                 "isCollEmpty: Input rsComm or collection is NULL" );
        return True;
    }

    memset( &openCollInp, 0, sizeof( openCollInp ) );
    rstrcpy( openCollInp.collName, collection, MAX_NAME_LEN );
    /* cannot query recur because collection is sorted in wrong order */
    openCollInp.flags = 0;
    handleInx = rsOpenCollection( rsComm, &openCollInp );
    if ( handleInx < 0 ) {
        rodsLog( LOG_ERROR,
                 "isCollEmpty: rsOpenCollection of %s error. status = %d",
                 openCollInp.collName, handleInx );
        return True;
    }

    while ( rsReadCollection( rsComm, &handleInx, &collEnt ) >= 0 ) {
        entCnt++;
        free( collEnt );    /* just free collEnt but not content */
    }

    rsCloseCollection( rsComm, &handleInx );

    if ( entCnt > 0 ) {
        return False;
    }
    else {
        return True;
    }
}
Exemple #3
0
int
rsCollRepl (rsComm_t *rsComm, collInp_t *collReplInp,
collOprStat_t **collOprStat)
{
    int status;
    dataObjInp_t dataObjInp;
    collEnt_t *collEnt;
    int handleInx;
    transferStat_t myTransStat;
    int totalFileCnt;
    int fileCntPerStatOut;
    int savedStatus = 0;
    int remoteFlag;
    rodsServerHost_t *rodsServerHost;

    /* try to connect to dest resc */
    bzero (&dataObjInp, sizeof (dataObjInp));
    rstrcpy (dataObjInp.objPath, collReplInp->collName, MAX_NAME_LEN);	
    remoteFlag = getAndConnRemoteZone (rsComm, &dataObjInp, &rodsServerHost,
      REMOTE_CREATE);

    if (remoteFlag < 0) {
        return (remoteFlag);
    } else if (remoteFlag == REMOTE_HOST) {
	int retval;
        retval = _rcCollRepl (rodsServerHost->conn, collReplInp, collOprStat);
        if (retval < 0) return retval;
        status = svrSendZoneCollOprStat (rsComm, rodsServerHost->conn,
          *collOprStat, retval);
        return status;
    }

    fileCntPerStatOut = FILE_CNT_PER_STAT_OUT;
    if (collOprStat != NULL) *collOprStat = NULL;
    collReplInp->flags = RECUR_QUERY_FG;
    handleInx = rsOpenCollection (rsComm, collReplInp);
    if (handleInx < 0) {
        rodsLog (LOG_ERROR,
          "rsCollRepl: rsOpenCollection of %s error. status = %d",
          collReplInp->collName, handleInx);
        return (handleInx);
    }

    if (collOprStat != NULL) {
        *collOprStat = (collOprStat_t*)malloc (sizeof (collOprStat_t));
        memset (*collOprStat, 0, sizeof (collOprStat_t));
    }

    if (CollHandle[handleInx].rodsObjStat->specColl != NULL) {
        rodsLog (LOG_ERROR,
          "rsCollRepl: unable to replicate mounted collection %s",
          collReplInp->collName);
        rsCloseCollection (rsComm, &handleInx);
        return (0);
    }

    while ((status = rsReadCollection (rsComm, &handleInx, &collEnt)) >= 0) {
        if (collEnt->objType == DATA_OBJ_T) {
	    if (totalFileCnt == 0) totalFileCnt = 
		CollHandle[handleInx].dataObjSqlResult.totalRowCount;

	    bzero (&dataObjInp, sizeof (dataObjInp));
            snprintf (dataObjInp.objPath, MAX_NAME_LEN, "%s/%s",
              collEnt->collName, collEnt->dataName);
	    dataObjInp.condInput = collReplInp->condInput;

    	    memset (&myTransStat, 0, sizeof (myTransStat));
            status = _rsDataObjRepl (rsComm, &dataObjInp,
	      &myTransStat, NULL);

            if (status == SYS_COPY_ALREADY_IN_RESC) {
		savedStatus = status;
                status = 0;
            }

            if (status < 0) {
                rodsLogError (LOG_ERROR, status,
                  "rsCollRepl: rsDataObjRepl failed for %s. status = %d",
                  dataObjInp.objPath, status);
		savedStatus = status;
                break;
            } else {
		if (collOprStat != NULL) {
		    (*collOprStat)->bytesWritten += myTransStat.bytesWritten;
		    (*collOprStat)->filesCnt ++; 
		}
	    }
	    if (collOprStat != NULL &&
	      (*collOprStat)->filesCnt >= fileCntPerStatOut) {
	        rstrcpy ((*collOprStat)->lastObjPath, dataObjInp.objPath,
	          MAX_NAME_LEN);
	        (*collOprStat)->totalFileCnt = totalFileCnt;
	        status = svrSendCollOprStat (rsComm, *collOprStat);
	        if (status < 0) {
                    rodsLogError (LOG_ERROR, status,
                      "rsCollRepl: svrSendCollOprStat failed for %s. status = %d",
                      dataObjInp.objPath, status);
		    *collOprStat = NULL;
	            savedStatus = status;
	            break;
	        }
                 *collOprStat = (collOprStat_t*)malloc (sizeof (collOprStat_t));
                 memset (*collOprStat, 0, sizeof (collOprStat_t));
	    }
        }
	free (collEnt);	    /* just free collEnt but not content */
    }
    rsCloseCollection (rsComm, &handleInx);

    return (savedStatus);
}
Exemple #4
0
int
_rsPhyBundleColl( rsComm_t*                 rsComm,
                  structFileExtAndRegInp_t* phyBundleCollInp,
                  const char *_resc_name ) {

    collInp_t collInp;
    bzero( &collInp, sizeof( collInp ) );
    rstrcpy( collInp.collName, phyBundleCollInp->collection, MAX_NAME_LEN );
    collInp.flags = RECUR_QUERY_FG | VERY_LONG_METADATA_FG | NO_TRIM_REPL_FG;

    char* srcRescName = getValByKey( &phyBundleCollInp->condInput, RESC_NAME_KW );
    if ( srcRescName != NULL ) {
        collInp.flags |= INCLUDE_CONDINPUT_IN_QUERY;
        addKeyVal( &collInp.condInput, RESC_NAME_KW, srcRescName );
    }

    int handleInx = rsOpenCollection( rsComm, &collInp );

    if ( handleInx < 0 ) {
        rodsLog( LOG_ERROR,
                 "_rsPhyBundleColl: rsOpenCollection of %s error. status = %d",
                 collInp.collName, handleInx );
        return handleInx;
    }

    if ( CollHandle[handleInx].rodsObjStat->specColl != NULL ) {
        rodsLog( LOG_ERROR,
                 "_rsPhyBundleColl: unable to bundle special collection %s",
                 collInp.collName );
        rsCloseCollection( rsComm, &handleInx );
        return 0;
    }

    /* create the bundle file */
    char* dataType  = getValByKey( &phyBundleCollInp->condInput, DATA_TYPE_KW ); // JMC - backport 4658
    char* rescHier = getValByKey( &phyBundleCollInp->condInput, RESC_HIER_STR_KW );
    dataObjInp_t dataObjInp;
    int   l1descInx = createPhyBundleDataObj( rsComm, phyBundleCollInp->collection,
                      _resc_name, rescHier, &dataObjInp, dataType ); // JMC - backport 4658

    if ( l1descInx < 0 ) {
        return l1descInx;
    }

    // =-=-=-=-=-=-=-
    // JMC - backport 4528
    int chksumFlag    = -1;
    if ( getValByKey( &phyBundleCollInp->condInput, VERIFY_CHKSUM_KW ) != NULL ) {
        L1desc[l1descInx].chksumFlag = VERIFY_CHKSUM;
        chksumFlag = 1;
    }
    else {
        chksumFlag = 0;
    }
    // =-=-=-=-=-=-=-
    // JMC - backport 4771
    int maxSubFileCnt = -1; // JMC - backport 4528, 4771
    if ( getValByKey( &phyBundleCollInp->condInput, MAX_SUB_FILE_KW ) != NULL ) {
        maxSubFileCnt = atoi( getValByKey( &phyBundleCollInp->condInput, MAX_SUB_FILE_KW ) );
    }
    else {
        maxSubFileCnt = MAX_SUB_FILE_CNT;
    }

    rodsLong_t maxBunSize;
    if ( getValByKey( &phyBundleCollInp->condInput, MAX_BUNDLE_SIZE_KW ) != NULL ) {
        maxBunSize = atoi( getValByKey( &phyBundleCollInp->condInput, MAX_BUNDLE_SIZE_KW ) ) * OneGig;
    }
    else {
        maxBunSize = MAX_BUNDLE_SIZE * OneGig;
    }

    // =-=-=-=-=-=-=-
    char phyBunDir[MAX_NAME_LEN];
    createPhyBundleDir( rsComm, L1desc[l1descInx].dataObjInfo->filePath,
                        phyBunDir, L1desc[l1descInx].dataObjInfo->rescHier );

    curSubFileCond_t     curSubFileCond;
    bunReplCacheHeader_t bunReplCacheHeader;
    bzero( &bunReplCacheHeader, sizeof( bunReplCacheHeader ) );
    bzero( &curSubFileCond, sizeof( curSubFileCond ) );

    int        status      = -1;
    int        savedStatus =  0;
    collEnt_t* collEnt     =  NULL;
    while ( ( status = rsReadCollection( rsComm, &handleInx, &collEnt ) ) >= 0 ) {
        if ( collEnt->objType == DATA_OBJ_T ) {
            if ( curSubFileCond.collName[0] == '\0' ) {
                /* a new dataObj.  */
                rstrcpy( curSubFileCond.collName, collEnt->collName,
                         MAX_NAME_LEN );
                rstrcpy( curSubFileCond.dataName, collEnt->dataName,
                         MAX_NAME_LEN );
                curSubFileCond.dataId = strtoll( collEnt->dataId, 0, 0 );
            }
            else if ( strcmp( curSubFileCond.collName, collEnt->collName ) != 0
                      || strcmp( curSubFileCond.dataName, collEnt->dataName ) != 0 ) {
                /* a new file, need to handle the old one */
                if ( bunReplCacheHeader.numSubFiles >= maxSubFileCnt || // JMC - backport 4771
                        bunReplCacheHeader.totSubFileSize + collEnt->dataSize > maxBunSize ) {
                    /* bundle is full */
                    status = bundleAndRegSubFiles( rsComm, l1descInx,
                                                   phyBunDir, phyBundleCollInp->collection,
                                                   &bunReplCacheHeader, chksumFlag ); // JMC - backport 4528
                    if ( status < 0 ) {
                        rodsLog( LOG_ERROR,
                                 "_rsPhyBundleColl:bunAndRegSubFiles err for %s,stst=%d",
                                 phyBundleCollInp->collection, status );
                        savedStatus = status;
                    }
                    else {
                        /* create a new bundle file */
                        l1descInx = createPhyBundleDataObj( rsComm,
                                                            phyBundleCollInp->collection, _resc_name,
                                                            rescHier, &dataObjInp, dataType ); // JMC - backport 4658

                        if ( l1descInx < 0 ) {
                            rodsLog( LOG_ERROR,
                                     "_rsPhyBundleColl:createPhyBundleDataObj err for %s,stat=%d",
                                     phyBundleCollInp->collection, l1descInx );
                            freeCollEnt( collEnt );
                            return l1descInx;
                        }

                        createPhyBundleDir( rsComm,
                                            L1desc[l1descInx].dataObjInfo->filePath, phyBunDir, L1desc[l1descInx].dataObjInfo->rescHier );
                        /* need to reset subPhyPath since phyBunDir has
                         * changed */
                        /* At this point subPhyPath[0] == 0 if it has gone
                         * through replAndAddSubFileToDir below. != 0 if it has
                         * not and already a good cache copy */
                        if ( curSubFileCond.subPhyPath[0] != '\0' )
                            setSubPhyPath( phyBunDir, curSubFileCond.dataId,
                                           curSubFileCond.subPhyPath );

                    }
                }       /* end of new bundle file */
                status = replAndAddSubFileToDir( rsComm, &curSubFileCond, _resc_name, phyBunDir, &bunReplCacheHeader );
                if ( status < 0 ) {
                    savedStatus = status;
                    rodsLog( LOG_ERROR,
                             "_rsPhyBundleColl:replAndAddSubFileToDir err for %s,sta=%d",
                             curSubFileCond.subPhyPath, status );
                }
                curSubFileCond.bundled = 0;
                curSubFileCond.subPhyPath[0] =
                    curSubFileCond.cachePhyPath[0] = '\0';
                rstrcpy( curSubFileCond.collName, collEnt->collName,
                         MAX_NAME_LEN );
                rstrcpy( curSubFileCond.dataName, collEnt->dataName,
                         MAX_NAME_LEN );
                curSubFileCond.dataId = strtoll( collEnt->dataId, 0, 0 );
            }   /* end of  name compare */

            if ( curSubFileCond.bundled > 0 ) {
                /* already bundled. skip */
            }
            else if ( isDataObjBundled( collEnt ) ) {
                /* already bundled, skip */
                curSubFileCond.bundled = 1;
                curSubFileCond.subPhyPath[0] = '\0';
                curSubFileCond.cachePhyPath[0] = '\0';
                /* XXXX there was a bug that if dataSize == 0, replStatus is 0.
                 * This bug has been fixed since 3.1 */
            }
            else if ( ( collEnt->replStatus > 0 || curSubFileCond.subPhyPath[0] == '\0' ) &&  // JMC - backport 4755
                      strcmp( collEnt->resource, _resc_name ) == 0 ) {
                /* have a good copy in cache resource */
                setSubPhyPath( phyBunDir, curSubFileCond.dataId, curSubFileCond.subPhyPath );
                rstrcpy( curSubFileCond.cachePhyPath, collEnt->phyPath, MAX_NAME_LEN );
                curSubFileCond.cacheReplNum = collEnt->replNum;
                curSubFileCond.subFileSize = collEnt->dataSize;
            }

        } // if data obj

        free( collEnt );    /* just free collEnt but not content */

    } // while
    /* handle any remaining */

    status = replAndAddSubFileToDir( rsComm, &curSubFileCond,
                                     _resc_name, phyBunDir, &bunReplCacheHeader );
    if ( status < 0 ) {
        savedStatus = status;
        rodsLog( LOG_ERROR,
                 "_rsPhyBundleColl:replAndAddSubFileToDir err for %s,stat=%d",
                 curSubFileCond.subPhyPath, status );
    }

    status = bundleAndRegSubFiles( rsComm, l1descInx, phyBunDir,
                                   phyBundleCollInp->collection, &bunReplCacheHeader, chksumFlag ); // JMC - backport 4528
    if ( status < 0 ) {
        rodsLog( LOG_ERROR,
                 "_rsPhyBundleColl:bunAndRegSubFiles err for %s,stat=%d",
                 phyBundleCollInp->collection, status );
    }

    clearKeyVal( &collInp.condInput );
    rsCloseCollection( rsComm, &handleInx );

    if ( status >= 0 && savedStatus < 0 ) {
        return savedStatus;
    }
    else {
        return status;
    }
}
int _rsStructFileBundle( rsComm_t*                 rsComm,
                         structFileExtAndRegInp_t* structFileBundleInp ) {
    int status;
    int handleInx;
    char phyBunDir[MAX_NAME_LEN];
    char tmpPath[MAX_NAME_LEN];
    int l1descInx;
    char* dataType = 0; // JMC - backport 4664
    openedDataObjInp_t dataObjCloseInp;

    // =-=-=-=-=-=-=-
    // create an empty data obj
    dataObjInp_t dataObjInp;
    memset( &dataObjInp, 0, sizeof( dataObjInp ) );
    dataObjInp.openFlags = O_WRONLY;

    // =-=-=-=-=-=-=-
    // get the data type of the structured file
    dataType = getValByKey( &structFileBundleInp->condInput, DATA_TYPE_KW );

    // =-=-=-=-=-=-=-
    // ensure that the file name will end in .zip, if necessary
    if ( dataType != NULL && strstr( dataType, ZIP_DT_STR ) != NULL ) {
        int len = strlen( structFileBundleInp->objPath );
        if ( strcmp( &structFileBundleInp->objPath[len - 4], ".zip" ) != 0 ) {
            strcat( structFileBundleInp->objPath, ".zip" );
        }
    }

    // =-=-=-=-=-=-=-
    // capture the object path in the data obj struct
    rstrcpy( dataObjInp.objPath, structFileBundleInp->objPath, MAX_NAME_LEN );

    // =-=-=-=-=-=-=-
    // replicate the condInput. may have resource input
    replKeyVal( &structFileBundleInp->condInput, &dataObjInp.condInput );

    // =-=-=-=-=-=-=-
    // open the file if we are in an add operation, otherwise create the new file
    if ( ( structFileBundleInp->oprType & ADD_TO_TAR_OPR ) != 0 ) { // JMC - backport 4643
        l1descInx = rsDataObjOpen( rsComm, &dataObjInp );

    }
    else {
        l1descInx = rsDataObjCreate( rsComm, &dataObjInp );

    }

    // =-=-=-=-=-=-=-
    // error check create / open
    if ( l1descInx < 0 ) {
        rodsLog( LOG_ERROR, "rsStructFileBundle: rsDataObjCreate of %s error. status = %d",
                 dataObjInp.objPath, l1descInx );
        return l1descInx;
    }

    // =-=-=-=-=-=-=-
    // FIXME :: Why, when we replicate them above?
    clearKeyVal( &dataObjInp.condInput ); // JMC - backport 4637
    // ???? l3Close (rsComm, l1descInx);

    // =-=-=-=-=-=-=-
    // zip does not like a zero length file as target
    //L1desc[ l1descInx ].l3descInx = 0;
    //if( dataType != NULL && strstr( dataType, ZIP_DT_STR ) != NULL ) {
    //    if( ( structFileBundleInp->oprType & ADD_TO_TAR_OPR) == 0 ) { // JMC - backport 4643
    //        l3Unlink( rsComm, L1desc[l1descInx].dataObjInfo );
    //    }
    //}

    // =-=-=-=-=-=-=-
    // check object permissions / stat
    chkObjPermAndStat_t chkObjPermAndStatInp;
    memset( &chkObjPermAndStatInp, 0, sizeof( chkObjPermAndStatInp ) );
    rstrcpy( chkObjPermAndStatInp.objPath, structFileBundleInp->collection, MAX_NAME_LEN );
    chkObjPermAndStatInp.flags = CHK_COLL_FOR_BUNDLE_OPR;
    addKeyVal( &chkObjPermAndStatInp.condInput, RESC_NAME_KW,     L1desc[l1descInx].dataObjInfo->rescName );

    // =-=-=-=-=-=-=-
    // get the resc hier string
    std::string resc_hier;
    char* resc_hier_ptr = getValByKey( &structFileBundleInp->condInput, RESC_HIER_STR_KW );
    if ( !resc_hier_ptr ) {
        rodsLog( LOG_NOTICE, "_rsStructFileBundle :: RESC_HIER_STR_KW is NULL" );
    }
    else {
        addKeyVal( &chkObjPermAndStatInp.condInput, RESC_HIER_STR_KW, resc_hier_ptr );
        resc_hier = resc_hier_ptr;
    }

    status = rsChkObjPermAndStat( rsComm, &chkObjPermAndStatInp );
    if ( status < 0 ) {
        rodsLog( LOG_ERROR, "rsStructFileBundle: rsChkObjPermAndStat of %s error. stat = %d",
                 chkObjPermAndStatInp.objPath, status );
        dataObjCloseInp.l1descInx = l1descInx;
        rsDataObjClose( rsComm, &dataObjCloseInp );
        return status;
    }

    clearKeyVal( &chkObjPermAndStatInp.condInput );

    // =-=-=-=-=-=-=-
    // create the special hidden directory where the bundling happens
    createPhyBundleDir( rsComm, L1desc[ l1descInx ].dataObjInfo->filePath, phyBunDir, L1desc[ l1descInx ].dataObjInfo->rescHier );

    // =-=-=-=-=-=-=-
    // build a collection open input structure
    collInp_t collInp;
    bzero( &collInp, sizeof( collInp ) );
    collInp.flags = RECUR_QUERY_FG | VERY_LONG_METADATA_FG | NO_TRIM_REPL_FG | INCLUDE_CONDINPUT_IN_QUERY;
    rstrcpy( collInp.collName, structFileBundleInp->collection, MAX_NAME_LEN );
    addKeyVal( &collInp.condInput, RESC_NAME_KW, L1desc[ l1descInx ].dataObjInfo->rescName );

    rodsLog( LOG_DEBUG, "rsStructFileBundle: calling rsOpenCollection for [%s]", structFileBundleInp->collection );

    // =-=-=-=-=-=-=-
    // open the collection from which we will bundle
    handleInx = rsOpenCollection( rsComm, &collInp );
    if ( handleInx < 0 ) {
        rodsLog( LOG_ERROR, "rsStructFileBundle: rsOpenCollection of %s error. status = %d",
                 collInp.collName, handleInx );
        rmdir( phyBunDir );
        return handleInx;
    }

    // =-=-=-=-=-=-=-
    // preserve the collection path?
    int collLen = 0;
    if ( ( structFileBundleInp->oprType & PRESERVE_COLL_PATH ) != 0 ) {
        // =-=-=-=-=-=-=-
        // preserve the last entry of the coll path
        char* tmpPtr = collInp.collName;
        int   tmpLen = 0;
        collLen = 0;

        // =-=-=-=-=-=-=-
        // find length to the last '/'
        while ( *tmpPtr != '\0' ) {
            if ( *tmpPtr == '/' ) {
                collLen = tmpLen;
            }

            tmpLen++;
            tmpPtr++;
        }

    }
    else {
        collLen = strlen( collInp.collName );

    }

    // =-=-=-=-=-=-=-
    // preserve the collection path?
    collEnt_t* collEnt = NULL;
    while ( ( status = rsReadCollection( rsComm, &handleInx, &collEnt ) ) >= 0 ) {
        if ( NULL == collEnt ) {
            rodsLog(
                LOG_ERROR,
                "rsStructFileBundle: collEnt is NULL" );
            continue;
        }

        // =-=-=-=-=-=-=-
        // entry is a data object
        if ( collEnt->objType == DATA_OBJ_T ) {
            // =-=-=-=-=-=-=-
            // filter out any possible replicas that are not on this resource
            if ( resc_hier != collEnt->resc_hier ) {
                rodsLog(
                    LOG_DEBUG,
                    "_rsStructFileBundle - skipping [%s] on resc [%s]",
                    collEnt->phyPath,
                    collEnt->resc_hier );
                free( collEnt );
                collEnt = NULL;
                continue;
            }

            if ( collEnt->collName[collLen] == '\0' ) {
                snprintf(
                    tmpPath,
                    MAX_NAME_LEN,
                    "%s/%s",
                    phyBunDir,
                    collEnt->dataName );
            }
            else {
                snprintf(
                    tmpPath,
                    MAX_NAME_LEN, "%s/%s/%s",
                    phyBunDir,
                    collEnt->collName + collLen + 1,
                    collEnt->dataName );
                status = mkDirForFilePath(
                             rsComm,
                             strlen( phyBunDir ),
                             tmpPath,
                             collEnt->resc_hier,
                             getDefDirMode() );
                if ( status < 0 ) {
                    rodsLog(
                        LOG_ERROR,
                        "mkDirForFilePath failed in _rsStructFileBundle with status %d",
                        status );
                    free( collEnt );
                    return status;
                }
            }

            // =-=-=-=-=-=-=-
            // add a link
            status = link( collEnt->phyPath, tmpPath );
            if ( status < 0 ) {
                rodsLog(
                    LOG_ERROR,
                    "rsStructFileBundle: link error %s to %s. errno = %d",
                    collEnt->phyPath,
                    tmpPath,
                    errno );
                rmLinkedFilesInUnixDir( phyBunDir );
                rmdir( phyBunDir );
                free( collEnt );
                return UNIX_FILE_LINK_ERR - errno;
            }
            else {
                rodsLog(
                    LOG_DEBUG,
                    "_rsStructFileBundle - LINK  [%s] on resc [%s]",
                    collEnt->phyPath,
                    collEnt->resc_hier );
            }
        }
        else {
            // =-=-=-=-=-=-=-
            // entry is a collection
            if ( ( int ) strlen( collEnt->collName ) + 1 <= collLen ) {
                free( collEnt );
                collEnt = NULL;
                continue;
            }
            snprintf( tmpPath, MAX_NAME_LEN, "%s/%s", phyBunDir, collEnt->collName + collLen );
            status = mkFileDirR( rsComm, strlen( phyBunDir ), tmpPath, resc_hier.c_str(), getDefDirMode() );
            if ( status < 0 ) {
                rodsLog( LOG_ERROR, "mkFileDirR failed in _rsStructFileBundle with status %d", status );
                free( collEnt );
                return status;
            }
        } // else

        free( collEnt );
        collEnt = NULL;

    } // while

    // =-=-=-=-=-=-=-
    // clean up key vals and close the collection
    clearKeyVal( &collInp.condInput );
    rsCloseCollection( rsComm, &handleInx );

    // =-=-=-=-=-=-=-
    // call the helper function to do the actual bundling
    status = phyBundle( rsComm, L1desc[l1descInx].dataObjInfo, phyBunDir,
                        collInp.collName, structFileBundleInp->oprType ); // JMC - backport 4643

    int savedStatus = 0;
    if ( status < 0 ) {
        rodsLog( LOG_ERROR, "rsStructFileBundle: phyBundle of %s error. stat = %d",
                 L1desc[ l1descInx ].dataObjInfo->objPath, status );
        L1desc[ l1descInx ].bytesWritten = 0;
        savedStatus = status;
    }
    else {
        // mark it was written so the size would be adjusted
        L1desc[ l1descInx ].bytesWritten = 1;
    }

    // =-=-=-=-=-=-=-
    // clean up after the bundle directory
    rmLinkedFilesInUnixDir( phyBunDir );
    rmdir( phyBunDir );

    dataObjCloseInp.l1descInx = l1descInx;
    status = rsDataObjClose( rsComm, &dataObjCloseInp );
    if ( status >= 0 ) {
        return savedStatus;
    }

    return status;
}
int
chkCollForBundleOpr( rsComm_t *rsComm,
                     chkObjPermAndStat_t *chkObjPermAndStatInp ) {
#ifdef RODS_CAT
    int status;
    collInp_t openCollInp;
    collEnt_t *collEnt = NULL;
    collEnt_t *curCollEnt = NULL;
    int handleInx;
    int curCopyGood = False;
    char *resource;
    char *resc_hier;
    rodsLong_t myId;
    char myPath[MAX_NAME_LEN];

    if ( ( resource = getValByKey( &chkObjPermAndStatInp->condInput,
                                   RESC_NAME_KW ) ) == NULL ) {
        rodsLog( LOG_ERROR,
                 "chkCollForBundleOpr: RESC_NAME_KW not specified for %s",
                 chkObjPermAndStatInp->objPath );
        return SYS_INVALID_RESC_INPUT;
    }

    if ( ( resc_hier = getValByKey( &chkObjPermAndStatInp->condInput,
                                    RESC_HIER_STR_KW ) ) == NULL ) {
        rodsLog( LOG_ERROR,
                 "chkCollForBundleOpr: RESC_HIER_STR_KW not specified for %s",
                 chkObjPermAndStatInp->objPath );
        return SYS_INVALID_RESC_INPUT;
    }

    memset( &openCollInp, 0, sizeof( openCollInp ) );
    rstrcpy( openCollInp.collName, chkObjPermAndStatInp->objPath, MAX_NAME_LEN );
    openCollInp.flags =
        RECUR_QUERY_FG | LONG_METADATA_FG | NO_TRIM_REPL_FG;
    handleInx = rsOpenCollection( rsComm, &openCollInp );
    if ( handleInx < 0 ) {
        rodsLog( LOG_ERROR,
                 "chkCollForBundleOpr: rsOpenCollection of %s error. status = %d",
                 openCollInp.collName, handleInx );
        return handleInx;
    }
    while ( ( status = rsReadCollection( rsComm, &handleInx, &collEnt ) ) >= 0 ) {
        if ( collEnt->specColl.collClass != NO_SPEC_COLL ) {
            if ( strcmp( resource, collEnt->specColl.resource ) != 0 ) {
                rodsLog( LOG_ERROR,
                         "chkCollForBundleOpr: specColl resc %s does not match %s",
                         collEnt->specColl.resource, resource );
                rsCloseCollection( rsComm, &handleInx );
                return SYS_COPY_NOT_EXIST_IN_RESC;
            }
            /* check permission */
            myId = chlCheckAndGetObjectID( rsComm, "-c",
                                           collEnt->specColl.collection, ACCESS_READ_OBJECT );
            if ( myId < 0 ) {
                status = myId;
                rodsLog( LOG_ERROR,
                         "chkCollForBundleOpr: no accPerm to specColl %s. status = %d",
                         collEnt->specColl.collection, status );
                rsCloseCollection( rsComm, &handleInx );
                return status;
            }
            free( collEnt );
            collEnt = NULL;
            continue;
        }

        if ( collEnt->objType == DATA_OBJ_T ) {
            if ( curCollEnt == NULL ) {
                curCollEnt = collEnt;
                saveCollEntForChkColl( collEnt );
                if ( collEnt->replStatus > 0 &&
                        strcmp( resource,  collEnt->resource ) == 0 &&
                        strcmp( resc_hier, collEnt->resc_hier ) == 0 ) {
                    curCopyGood = True;
                }
            }
            else {
                if ( strcmp( curCollEnt->dataName, collEnt->dataName ) == 0 &&
                        strcmp( curCollEnt->collName, collEnt->collName ) == 0 ) {
                    if ( collEnt->replStatus                     >  0 &&
                            strcmp( resource,  collEnt->resource ) == 0 &&
                            strcmp( resc_hier, collEnt->resc_hier ) == 0 ) {
                        /* a good copy */
                        freeCollEntForChkColl( curCollEnt );
                        curCopyGood = True;
                        curCollEnt = collEnt;
                        saveCollEntForChkColl( collEnt );
                    }
                }
                else {
                    /* encounter a new data obj */
                    snprintf( myPath, MAX_NAME_LEN, "%s/%s",
                              curCollEnt->collName, curCollEnt->dataName );

                    if ( curCopyGood == False ) {
                        status = replDataObjForBundle( rsComm,
                                                       curCollEnt->collName, curCollEnt->dataName,
                                                       resource, curCollEnt->resc_hier, resc_hier, 0, NULL );

                        if ( status < 0 ) {
                            rodsLog( LOG_ERROR,
                                     "chkCollForBundleOpr: %s no good copy in %s [%d]",
                                     myPath, resource, status );
                            rsCloseCollection( rsComm, &handleInx );
                            freeCollEntForChkColl( curCollEnt );
                            return SYS_COPY_NOT_EXIST_IN_RESC;
                        }
                    }
                    else {

                    }
                    freeCollEntForChkColl( curCollEnt );
                    curCopyGood = False;
                    curCollEnt = NULL;

                    /* we have a good copy. Check the permission */
                    myId = chlCheckAndGetObjectID( rsComm, "-d", myPath,
                                                   ACCESS_READ_OBJECT );
                    if ( myId < 0 && myId != CAT_UNKNOWN_FILE ) {
                        /* could return CAT_UNKNOWN_FILE if mounted files */
                        status = myId;
                        rodsLog( LOG_ERROR,
                                 "chkCollForBundleOpr: no accPerm to %s. status = %d",
                                 myPath, status );
                        rsCloseCollection( rsComm, &handleInx );
                        return status;
                    }
                    else {
                        /* copy is OK */
                        curCollEnt = collEnt;
                        saveCollEntForChkColl( collEnt );
                        collEnt = NULL;
                        if ( curCollEnt->replStatus > 0 &&
                                strcmp( resource, curCollEnt->resource ) == 0 &&
                                strcmp( resc_hier, curCollEnt->resc_hier ) == 0 ) {
                            /* a good copy */
                            curCopyGood = True;
                        }
                    }
                }
            }
        }
        else {
            free( collEnt );
        }
    }

    /* handle what's left */
    if ( curCollEnt != NULL ) {
        if ( curCopyGood == False ) {
            status = replDataObjForBundle( rsComm, curCollEnt->collName,
                                           curCollEnt->dataName, resource, curCollEnt->resc_hier, resc_hier, 0, NULL );
            if ( status < 0 ) {
                rodsLog( LOG_ERROR,
                         "chkCollForBundleOpr:%s does not have a good copy in %s",
                         chkObjPermAndStatInp->objPath, resource );
                status = SYS_COPY_NOT_EXIST_IN_RESC;
            }
        }
        else {
            freeCollEntForChkColl( curCollEnt );
        }
    }
    else {
        status = 0;
    }

    rsCloseCollection( rsComm, &handleInx );

    return 0;
#else
    return SYS_NO_RCAT_SERVER_ERR;
#endif
}
Exemple #7
0
int
_rsPhyRmColl( rsComm_t *rsComm, collInp_t *rmCollInp,
              dataObjInfo_t *dataObjInfo, collOprStat_t **collOprStat ) {

    char *tmpValue;
    int status;
    collInp_t openCollInp;
    collEnt_t *collEnt;
    int handleInx;
    dataObjInp_t dataObjInp;
    collInp_t tmpCollInp;
    int rmtrashFlag = 0;
    int savedStatus = 0;
    int fileCntPerStatOut = FILE_CNT_PER_STAT_OUT;
    int entCnt = 0;
    ruleExecInfo_t rei;
    collInfo_t collInfo;

    memset( &openCollInp, 0, sizeof( openCollInp ) );
    rstrcpy( openCollInp.collName, rmCollInp->collName, MAX_NAME_LEN );
    /* cannot query recur because collection is sorted in wrong order */
    openCollInp.flags = 0;
    handleInx = rsOpenCollection( rsComm, &openCollInp );
    if ( handleInx < 0 ) {
        rodsLog( LOG_ERROR,
                 "_rsPhyRmColl: rsOpenCollection of %s error. status = %d",
                 openCollInp.collName, handleInx );
        return handleInx;
    }

    memset( &dataObjInp, 0, sizeof( dataObjInp ) );
    memset( &tmpCollInp, 0, sizeof( tmpCollInp ) );
    /* catch the UNREG_OPR */
    dataObjInp.oprType = tmpCollInp.oprType = rmCollInp->oprType;

    if ( ( tmpValue = getValByKey( &rmCollInp->condInput, AGE_KW ) ) != NULL ) {
        if ( CollHandle[handleInx].rodsObjStat != NULL ) {
            /* when a collection is moved, the modfiyTime of the object in
              * the collectin does not change. So, we'll depend on the
              * modfiyTime of the collection */
            int ageLimit = atoi( tmpValue ) * 60;
            int modifyTime =
                atoi( CollHandle[handleInx].rodsObjStat->modifyTime );
            if ( ( time( 0 ) - modifyTime ) < ageLimit ) {
                rsCloseCollection( rsComm, &handleInx );
                return 0;
            }
        }
        addKeyVal( &dataObjInp.condInput, AGE_KW, tmpValue );
        addKeyVal( &tmpCollInp.condInput, AGE_KW, tmpValue );
    }
    addKeyVal( &dataObjInp.condInput, FORCE_FLAG_KW, "" );
    addKeyVal( &tmpCollInp.condInput, FORCE_FLAG_KW, "" );

    if ( ( tmpValue = getValByKey( &rmCollInp->condInput, AGE_KW ) ) != NULL ) {
        addKeyVal( &dataObjInp.condInput, AGE_KW, tmpValue );
        addKeyVal( &tmpCollInp.condInput, AGE_KW, tmpValue );
    }

    if ( collOprStat != NULL && *collOprStat == NULL ) {
        *collOprStat = ( collOprStat_t* )malloc( sizeof( collOprStat_t ) );
        memset( *collOprStat, 0, sizeof( collOprStat_t ) );
    }



    if ( getValByKey( &rmCollInp->condInput, ADMIN_RMTRASH_KW ) != NULL ) {
        if ( isTrashPath( rmCollInp->collName ) == False ) {
            return SYS_INVALID_FILE_PATH;
        }
        if ( rsComm->clientUser.authInfo.authFlag != LOCAL_PRIV_USER_AUTH ) {
            return CAT_INSUFFICIENT_PRIVILEGE_LEVEL;
        }
        addKeyVal( &tmpCollInp.condInput, ADMIN_RMTRASH_KW, "" );
        addKeyVal( &dataObjInp.condInput, ADMIN_RMTRASH_KW, "" );
        rmtrashFlag = 2;
    }
    else if ( getValByKey( &rmCollInp->condInput, RMTRASH_KW ) != NULL ) {
        if ( isTrashPath( rmCollInp->collName ) == False ) {
            return SYS_INVALID_FILE_PATH;
        }
        addKeyVal( &tmpCollInp.condInput, RMTRASH_KW, "" );
        addKeyVal( &dataObjInp.condInput, RMTRASH_KW, "" );
        rmtrashFlag = 1;
    }
    // =-=-=-=-=-=-=-
    // JMC - backport 4552
    if ( getValByKey( &rmCollInp->condInput, EMPTY_BUNDLE_ONLY_KW ) != NULL ) {
        addKeyVal( &tmpCollInp.condInput, EMPTY_BUNDLE_ONLY_KW, "" );
        addKeyVal( &dataObjInp.condInput, EMPTY_BUNDLE_ONLY_KW, "" );
    }
    // =-=-=-=-=-=-=-
    while ( ( status = rsReadCollection( rsComm, &handleInx, &collEnt ) ) >= 0 ) {
        if ( entCnt == 0 ) {
            entCnt ++;
            /* cannot rm non-empty home collection */
            if ( isHomeColl( rmCollInp->collName ) ) {
                return CANT_RM_NON_EMPTY_HOME_COLL;
            }
        }
        if ( collEnt->objType == DATA_OBJ_T ) {
            snprintf( dataObjInp.objPath, MAX_NAME_LEN, "%s/%s",
                      collEnt->collName, collEnt->dataName );

            status = rsDataObjUnlink( rsComm, &dataObjInp );
            if ( status < 0 ) {
                rodsLog( LOG_ERROR,
                         "_rsPhyRmColl:rsDataObjUnlink failed for %s. stat = %d",
                         dataObjInp.objPath, status );
                /* need to set global error here */
                savedStatus = status;
            }
            else if ( collOprStat != NULL ) {
                ( *collOprStat )->filesCnt ++;
                if ( ( *collOprStat )->filesCnt >= fileCntPerStatOut ) {
                    rstrcpy( ( *collOprStat )->lastObjPath, dataObjInp.objPath,
                             MAX_NAME_LEN );
                    status = svrSendCollOprStat( rsComm, *collOprStat );
                    if ( status < 0 ) {
                        rodsLogError( LOG_ERROR, status,
                                      "_rsPhyRmColl: svrSendCollOprStat failed for %s. status = %d",
                                      rmCollInp->collName, status );
                        *collOprStat = NULL;
                        savedStatus = status;
                        break;
                    }
                    *collOprStat = ( collOprStat_t* )malloc( sizeof( collOprStat_t ) );
                    memset( *collOprStat, 0, sizeof( collOprStat_t ) );
                }
            }
        }
        else if ( collEnt->objType == COLL_OBJ_T ) {
            if ( strcmp( collEnt->collName, rmCollInp->collName ) == 0 ) {
                continue;    /* duplicate */
            }
            rstrcpy( tmpCollInp.collName, collEnt->collName, MAX_NAME_LEN );
            if ( collEnt->specColl.collClass != NO_SPEC_COLL ) {
                if ( strcmp( collEnt->collName, collEnt->specColl.collection )
                        == 0 ) {
                    continue;    /* no mount point */
                }
            }
            initReiWithCollInp( &rei, rsComm, &tmpCollInp, &collInfo );
            status = applyRule( "acPreprocForRmColl", NULL, &rei, NO_SAVE_REI );
            if ( status < 0 ) {
                if ( rei.status < 0 ) {
                    status = rei.status;
                }
                rodsLog( LOG_ERROR,
                         "_rsPhyRmColl:acPreprocForRmColl error for %s,stat=%d",
                         tmpCollInp.collName, status );
                return status;
            }
            status = _rsRmCollRecur( rsComm, &tmpCollInp, collOprStat );
            rei.status = status;
            rei.status = applyRule( "acPostProcForRmColl", NULL, &rei,
                                    NO_SAVE_REI );
            if ( rei.status < 0 ) {
                rodsLog( LOG_ERROR,
                         "_rsRmColl:acPostProcForRmColl error for %s,stat=%d",
                         tmpCollInp.collName, status );
            }
        }
        if ( status < 0 ) {
            savedStatus = status;
        }
        free( collEnt );    /* just free collEnt but not content */
    }
    rsCloseCollection( rsComm, &handleInx );

    if ( ( rmtrashFlag > 0 && ( isTrashHome( rmCollInp->collName ) > 0 || // JMC - backport 4561
                                isOrphanPath( rmCollInp->collName ) == is_ORPHAN_HOME ) )   ||
            ( isBundlePath( rmCollInp->collName ) == True                 &&
              getValByKey( &rmCollInp->condInput, EMPTY_BUNDLE_ONLY_KW ) != NULL ) ) {
        /* don't rm user's home trash coll or orphan collection */
        status = 0;
    }
    else {
        if ( dataObjInfo != NULL && dataObjInfo->specColl != NULL ) {
            if ( dataObjInfo->specColl->collClass == LINKED_COLL ) {
                rstrcpy( rmCollInp->collName, dataObjInfo->objPath,
                         MAX_NAME_LEN );
                status = svrUnregColl( rsComm, rmCollInp );
            }
            else {
                status = l3Rmdir( rsComm, dataObjInfo );
            }
        }
        else {
            status = svrUnregColl( rsComm, rmCollInp );
            if ( status < 0 ) {
                savedStatus = status;
            }
        }
    }
    clearKeyVal( &tmpCollInp.condInput );
    clearKeyVal( &dataObjInp.condInput );

    return savedStatus;
}
int
_rsStructFileBundle (rsComm_t *rsComm,
structFileExtAndRegInp_t *structFileBundleInp)
{
    int status;
    dataObjInp_t dataObjInp;
    openedDataObjInp_t dataObjCloseInp;
    collInp_t collInp;
    collEnt_t *collEnt = NULL;
    int handleInx;
    int collLen;
    char phyBunDir[MAX_NAME_LEN];
    char tmpPath[MAX_NAME_LEN];
    chkObjPermAndStat_t chkObjPermAndStatInp;
    int l1descInx;
    int savedStatus = 0;
    char *dataType;

    /* open the structured file */
    memset (&dataObjInp, 0, sizeof (dataObjInp));
    dataType = getValByKey (&structFileBundleInp->condInput, DATA_TYPE_KW);
    if (dataType != NULL && strstr (dataType, ZIP_DT_STR) != NULL) {
	/* zipFile type. must end with .zip */
	int len = strlen (structFileBundleInp->objPath);
	if (strcmp (&structFileBundleInp->objPath[len - 4], ".zip") != 0) {
	    strcat (structFileBundleInp->objPath, ".zip");
        }
    }
    rstrcpy (dataObjInp.objPath, structFileBundleInp->objPath, 
      MAX_NAME_LEN);
 
    /* replicate the condInput. may have resource input */
    replKeyVal (&structFileBundleInp->condInput, &dataObjInp.condInput);

    dataObjInp.openFlags = O_WRONLY;  

    if ((structFileBundleInp->oprType & ADD_TO_TAR_OPR) != 0) {
        l1descInx = rsDataObjOpen (rsComm, &dataObjInp);
    } else {
        l1descInx = rsDataObjCreate (rsComm, &dataObjInp);
    }
    if (l1descInx < 0) {
        rodsLog (LOG_ERROR,
          "rsStructFileBundle: rsDataObjCreate of %s error. status = %d",
          dataObjInp.objPath, l1descInx);
        return (l1descInx);
    }
    clearKeyVal (&dataObjInp.condInput);
    l3Close (rsComm, l1descInx);
    L1desc[l1descInx].l3descInx = 0;
    /* zip does not like a zero length file as target */
    if ((structFileBundleInp->oprType & ADD_TO_TAR_OPR) == 0)
        l3Unlink (rsComm, L1desc[l1descInx].dataObjInfo);

    memset (&chkObjPermAndStatInp, 0, sizeof (chkObjPermAndStatInp));
    rstrcpy (chkObjPermAndStatInp.objPath, 
      structFileBundleInp->collection, MAX_NAME_LEN); 
    chkObjPermAndStatInp.flags = CHK_COLL_FOR_BUNDLE_OPR;
    addKeyVal (&chkObjPermAndStatInp.condInput, RESC_NAME_KW,
      L1desc[l1descInx].dataObjInfo->rescName);

    status = rsChkObjPermAndStat (rsComm, &chkObjPermAndStatInp);

    clearKeyVal (&chkObjPermAndStatInp.condInput);

    if (status < 0) {
        rodsLog (LOG_ERROR,
          "rsStructFileBundle: rsChkObjPermAndStat of %s error. stat = %d",
          chkObjPermAndStatInp.objPath, status);
        dataObjCloseInp.l1descInx = l1descInx;
        rsDataObjClose (rsComm, &dataObjCloseInp);
        return (status);
    }

    createPhyBundleDir (rsComm, L1desc[l1descInx].dataObjInfo->filePath,
      phyBunDir);

    bzero (&collInp, sizeof (collInp));
    rstrcpy (collInp.collName, structFileBundleInp->collection, MAX_NAME_LEN);
    collInp.flags = RECUR_QUERY_FG | VERY_LONG_METADATA_FG |
      NO_TRIM_REPL_FG | INCLUDE_CONDINPUT_IN_QUERY;
    addKeyVal (&collInp.condInput, RESC_NAME_KW, 
      L1desc[l1descInx].dataObjInfo->rescName);
    handleInx = rsOpenCollection (rsComm, &collInp);
    if (handleInx < 0) {
        rodsLog (LOG_ERROR,
          "rsStructFileBundle: rsOpenCollection of %s error. status = %d",
          collInp.collName, handleInx);
        rmdir (phyBunDir);
        return (handleInx);
    }
    if ((structFileBundleInp->oprType & PRESERVE_COLL_PATH) != 0) {
	/* preserver the last entry of the coll path */
	char *tmpPtr = collInp.collName;
	int tmpLen = 0;
	collLen = 0;
	/* find length to the last '/' */
        while (*tmpPtr != '\0') {
	    if (*tmpPtr == '/') collLen = tmpLen;
	    tmpLen++;
	    tmpPtr++;
	}
    } else {
        collLen = strlen (collInp.collName);
    }
    while ((status = rsReadCollection (rsComm, &handleInx, &collEnt)) >= 0) {
        if (collEnt->objType == DATA_OBJ_T) {
            if (collEnt->collName[collLen] == '\0') {
                snprintf (tmpPath, MAX_NAME_LEN, "%s/%s",
                  phyBunDir, collEnt->dataName);
            } else {
                snprintf (tmpPath, MAX_NAME_LEN, "%s/%s/%s",
                 phyBunDir, collEnt->collName + collLen + 1, collEnt->dataName);               
	        mkDirForFilePath (UNIX_FILE_TYPE, rsComm, phyBunDir, 
	          tmpPath, getDefDirMode ());
            }
            /* add a link */
            status = link (collEnt->phyPath, tmpPath);
            if (status < 0) {
                rodsLog (LOG_ERROR,
                  "rsStructFileBundle: link error %s to %s. errno = %d",
                  collEnt->phyPath, tmpPath, errno);
                rmLinkedFilesInUnixDir (phyBunDir);
                rmdir (phyBunDir);
                return (UNIX_FILE_LINK_ERR - errno);
            }
        } else {        /* a collection */
	    if ((int) strlen (collEnt->collName) + 1 <= collLen) {
		free (collEnt);
		continue;
	    }
            snprintf (tmpPath, MAX_NAME_LEN, "%s/%s",
              phyBunDir, collEnt->collName + collLen);
            mkdirR (phyBunDir, tmpPath, getDefDirMode ());
	}
	if (collEnt != NULL) {
	    free (collEnt);
	    collEnt = NULL;
	}
    }
    clearKeyVal (&collInp.condInput);
    rsCloseCollection (rsComm, &handleInx);

    status = phyBundle (rsComm, L1desc[l1descInx].dataObjInfo, phyBunDir,
      collInp.collName, structFileBundleInp->oprType);
    if (status < 0) {
        rodsLog (LOG_ERROR,
          "rsStructFileBundle: phyBundle of %s error. stat = %d",
          L1desc[l1descInx].dataObjInfo->objPath, status);
	L1desc[l1descInx].bytesWritten = 0;
	savedStatus = status;
    } else {
        /* mark it was written so the size would be adjusted */
        L1desc[l1descInx].bytesWritten = 1;
    }

    rmLinkedFilesInUnixDir (phyBunDir);
    rmdir (phyBunDir);

    dataObjCloseInp.l1descInx = l1descInx;
    status = rsDataObjClose (rsComm, &dataObjCloseInp);

    if (status >= 0)
	return savedStatus;
    else
        return (status);
}
int
rsNcGetAggInfo (rsComm_t *rsComm, ncOpenInp_t *ncOpenInp,
ncAggInfo_t **ncAggInfo)
{
    specCollCache_t *specCollCache = NULL;
    collInp_t collInp;
    int handleInx;
    collEnt_t *collEnt;
    int status = 0;
    int status2 = 0;
    int savedStatus = 0;
    ncOpenInp_t childNcOpenInp;
    ncAggElement_t *ncAggElement = NULL;
    bytesBuf_t *packedBBuf = NULL;

    bzero (&collInp, sizeof (collInp));
    rstrcpy (collInp.collName, ncOpenInp->objPath, MAX_NAME_LEN);
    resolveLinkedPath (rsComm, collInp.collName, &specCollCache,
      &ncOpenInp->condInput);
    collInp.flags = VERY_LONG_METADATA_FG; 
    handleInx = rsOpenCollection (rsComm, &collInp);
    if (handleInx < 0) {
        rodsLog (LOG_ERROR,
          "rsNcGetAggInfo: rsOpenCollection of %s error. status = %d",
          collInp.collName, handleInx);
        return (handleInx);
    }
    bzero (&childNcOpenInp, sizeof (childNcOpenInp));
    *ncAggInfo = (ncAggInfo_t *) calloc (1, sizeof (ncAggInfo_t));
    rstrcpy ((*ncAggInfo)->ncObjectName, ncOpenInp->objPath, MAX_NAME_LEN);
    while ((status2 = rsReadCollection (rsComm, &handleInx, &collEnt)) >= 0) {
        if (collEnt->objType != DATA_OBJ_T) {
            free (collEnt);
            continue;
        } else if (strcmp (collEnt->dataType, "netcdf") != 0) {
            if (strcmp (collEnt->dataName, NC_AGG_INFO_FILE_NAME) != 0) {
                rodsLog (LOG_NOTICE,
                  "rsNcGetAggInfo: dataType of %s in %s is not 'netcdf' type",
                  collEnt->dataName, collInp.collName);
                savedStatus = NETCDF_INVALID_DATA_TYPE;
            }
            free (collEnt);
            continue;
        } 
        snprintf (childNcOpenInp.objPath, MAX_NAME_LEN, "%s/%s",
          collInp.collName, collEnt->dataName);
        status = rsNcGetAggElement (rsComm, &childNcOpenInp, &ncAggElement);
        if (status < 0) {
            rodsLogError (LOG_ERROR, status,
              "rsNcGetAggInfo: rsNcGetAggElement of %s error.",
              childNcOpenInp.objPath);
            free (collEnt);
            break;
        } else {
            status = addNcAggElement (ncAggElement, *ncAggInfo);
            free (ncAggElement);
            if (status < 0) {
                free (collEnt);
                break;
            }
        }
        free (collEnt);
    }
    rsCloseCollection (rsComm, &handleInx);
    if (status2 < 0 && status2 != CAT_NO_ROWS_FOUND && status >= 0) {
        status = status2;
    }
    if (status >= 0 && (ncOpenInp->mode & NC_WRITE) != 0) {
        dataObjInp_t dataObjInp;
        portalOprOut_t *portalOprOut = NULL;
        status = packStruct ((void *) *ncAggInfo, &packedBBuf, "NcAggInfo_PI",
          RodsPackTable, 0, XML_PROT);
        if (status < 0) {
            rodsLogError (LOG_ERROR, status,
              "rsNcGetAggInfo: packStruct error for %s",
              childNcOpenInp.objPath);
          return status;
        }
        /* write it */
        bzero (&dataObjInp, sizeof (dataObjInp));
        replKeyVal (&ncOpenInp->condInput, &dataObjInp.condInput);
        snprintf (dataObjInp.objPath, MAX_NAME_LEN, "%s/%s",
          collInp.collName, NC_AGG_INFO_FILE_NAME);
        dataObjInp.dataSize = packedBBuf->len;
        dataObjInp.oprType = PUT_OPR;
        addKeyVal (&dataObjInp.condInput, DATA_INCLUDED_KW, "");
        addKeyVal (&dataObjInp.condInput, FORCE_FLAG_KW, "");
        status = rsDataObjPut (rsComm, &dataObjInp, packedBBuf, &portalOprOut);
        clearBBuf (packedBBuf);
        clearKeyVal (&dataObjInp.condInput);
        if (portalOprOut != NULL) free (portalOprOut);
        if (status < 0) {
            rodsLogError (LOG_ERROR, status,
              "rsNcGetAggInfo: rsDataObjPut error for %s", dataObjInp.objPath);
        }
    }
    if (status < 0) {
        return status;
    } else {
        return savedStatus;
    }
}