static size_t my_read_obj(void *buffer, size_t size, size_t nmemb, void* userp) {
        struct readData_t *readData = (struct readData_t *) userp;

        dataObjInp_t file;
        openedDataObjInp_t openedFile;
        bytesBuf_t bytesBuf;

        size_t bytesRead;

        // Make sure we have something to read from
        if (!readData) {
            rodsLog(LOG_ERROR, "irods_http_send_file: readData is NULL");
            return CURL_READFUNC_ABORT;
        }

        // Zero fill input structs
        memset(&file, 0, sizeof (dataObjInp_t));
        memset(&openedFile, 0, sizeof (openedDataObjInp_t));
        memset(&bytesBuf, 0, sizeof (bytesBuf_t));

        // If this is the first call we need to create our data object before reading from it
        if (!readData->desc) {
            strncpy(file.objPath, readData->path, MAX_NAME_LEN);

            // readData->desc = 5;
            readData->desc = rsDataObjOpen(readData->rsComm, &file);

            // TODO: <= 2 instead of < 0? Look up rsDataObjOpen return codes
            if (readData->desc < 0) {
                rodsLog(LOG_ERROR, "irods_http_send_file: Cannot read iRODS object %s Status =  %d",readData->path, readData->desc);
                return CURL_READFUNC_ABORT;
            }
        }

        // Setup buffer for rsDataObjRead
        bytesBuf.len = (int)(size * nmemb);
        bytesBuf.buf = buffer;

        // Setup input struct for rsDataObjRead
        openedFile.l1descInx = readData->desc;
        openedFile.len = bytesBuf.len;

        // bytesRead = 0;
        bytesRead = rsDataObjRead(readData->rsComm, &openedFile, &bytesBuf);
        if (bytesRead < 0) {
            rodsLog(LOG_ERROR, "irods_http_send_file: Problem reading iRODS object. Status =  %d", bytesRead);
            return CURL_READFUNC_ABORT;
        }

        return (bytesRead);
    }
Пример #2
0
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;
}
Пример #3
0
int
rsDataObjCopy( rsComm_t *rsComm, dataObjCopyInp_t *dataObjCopyInp,
               transferStat_t **transStat ) {
    dataObjInp_t *srcDataObjInp, *destDataObjInp;
    int srcL1descInx, destL1descInx;
    int status;
    int existFlag;
    uint createMode;
    int remoteFlag;
    rodsServerHost_t *rodsServerHost;
    specCollCache_t *specCollCache = NULL;

    srcDataObjInp = &dataObjCopyInp->srcDataObjInp;
    destDataObjInp = &dataObjCopyInp->destDataObjInp;

    resolveLinkedPath( rsComm, srcDataObjInp->objPath, &specCollCache, &srcDataObjInp->condInput );
    resolveLinkedPath( rsComm, destDataObjInp->objPath, &specCollCache, &destDataObjInp->condInput );

    remoteFlag = getAndConnRemoteZoneForCopy( rsComm, dataObjCopyInp, &rodsServerHost );
    if ( remoteFlag < 0 ) {
        return remoteFlag;
    }
    else if ( remoteFlag == REMOTE_HOST ) {
        status = _rcDataObjCopy( rodsServerHost->conn, dataObjCopyInp,
                                 transStat );
        return status;
    }

    if ( strcmp( srcDataObjInp->objPath, destDataObjInp->objPath ) == 0 ) {
        rodsLog( LOG_ERROR,
                 "rsDataObjCopy: same src and dest objPath %s not allowed",
                 srcDataObjInp->objPath );
        return USER_INPUT_PATH_ERR;
    }

    addKeyVal( &srcDataObjInp->condInput, PHYOPEN_BY_SIZE_KW, "" );

    srcL1descInx = rsDataObjOpen( rsComm, srcDataObjInp );

    if ( srcL1descInx < 0 ) {
        std::stringstream msg;
        char* sys_error = NULL;
        const char* rods_error = rodsErrorName( srcL1descInx, &sys_error );
        msg << __FUNCTION__;
        msg << " - Failed to open source object: \"";
        msg << srcDataObjInp->objPath;
        msg << "\" - ";
        msg << rods_error << " " << sys_error;
        irods::log( LOG_ERROR, msg.str() );
        free( sys_error );
        return srcL1descInx;
    }

    /* have to set L1desc[srcL1descInx].dataSize because open set this to -1 */
    destDataObjInp->dataSize = L1desc[srcL1descInx].dataSize =
                                   L1desc[srcL1descInx].dataObjInfo->dataSize;

    createMode = atoi( L1desc[srcL1descInx].dataObjInfo->dataMode );

    if ( createMode >= 0100 ) {
        destDataObjInp->createMode = createMode;
    }

    L1desc[srcL1descInx].oprType = COPY_SRC;

    if ( L1desc[srcL1descInx].l3descInx <= 2 ) {
        /* dataSingleBuf */
        addKeyVal( &destDataObjInp->condInput, NO_OPEN_FLAG_KW, "" );
    }

    destL1descInx = rsDataObjCreate( rsComm, destDataObjInp );
    if ( destL1descInx == CAT_UNKNOWN_COLLECTION ) {
        /* collection does not exist. make one */
        char parColl[MAX_NAME_LEN], child[MAX_NAME_LEN];
        splitPathByKey( destDataObjInp->objPath, parColl, MAX_NAME_LEN, child, MAX_NAME_LEN, '/' );
        rsMkCollR( rsComm, "/", parColl );
        destL1descInx = rsDataObjCreate( rsComm, destDataObjInp );
    }

    if ( destL1descInx < 0 ) {
        clearKeyVal( &destDataObjInp->condInput );
        std::stringstream msg;
        char* sys_error = NULL;
        const char* rods_error = rodsErrorName( destL1descInx, &sys_error );
        msg << __FUNCTION__;
        msg << " - Failed to create destination object: \"";
        msg << destDataObjInp->objPath;
        msg << "\" - ";
        msg << rods_error << " " << sys_error;
        irods::log( LOG_ERROR, msg.str() );
        free( sys_error );
        return destL1descInx;
    }

    if ( L1desc[destL1descInx].replStatus == NEWLY_CREATED_COPY ) {
        existFlag = 0;
    }
    else {
        existFlag = 1;
    }

    L1desc[destL1descInx].oprType = COPY_DEST;

    L1desc[destL1descInx].srcL1descInx = srcL1descInx;

    rstrcpy( L1desc[destL1descInx].dataObjInfo->dataType,

             L1desc[srcL1descInx].dataObjInfo->dataType, NAME_LEN );
    /* set dataSize for verification in _rsDataObjClose */

    L1desc[destL1descInx].dataSize =
        L1desc[srcL1descInx].dataObjInfo->dataSize;

    status = _rsDataObjCopy( rsComm, destL1descInx, existFlag, transStat );

    clearKeyVal( &destDataObjInp->condInput );

    return status;
}
Пример #4
0
int 
msiLoadMetadataFromXml(msParam_t *targetObj, msParam_t *xmlObj, ruleExecInfo_t *rei) 
{
	/* for parsing msParams and to open iRODS objects */
	dataObjInp_t xmlDataObjInp, *myXmlDataObjInp;
	dataObjInp_t targetObjInp, *myTargetObjInp;
	int xmlObjID;

	/* for getting size of objects to read from */
	rodsObjStat_t *rodsObjStatOut = NULL;

	/* for reading from iRODS objects */
	openedDataObjInp_t openedDataObjInp;
	bytesBuf_t *xmlBuf;

	/* misc. to avoid repeating rei->rsComm */
	rsComm_t *rsComm;

	/* for xml parsing */
	xmlDocPtr doc;

	/* for XPath evaluation */
	xmlXPathContextPtr xpathCtx;
	xmlXPathObjectPtr xpathObj;
	xmlChar xpathExpr[] = "//AVU";
	xmlNodeSetPtr nodes;
	int avuNbr, i;
	
	/* for new AVU creation */
	modAVUMetadataInp_t modAVUMetadataInp;
	int max_attr_len = 2700;
	char attrStr[max_attr_len];



	/*********************************  USUAL INIT PROCEDURE **********************************/
	
	/* For testing mode when used with irule --test */
	RE_TEST_MACRO ("    Calling msiLoadMetadataFromXml")


	/* Sanity checks */
	if (rei == NULL || rei->rsComm == NULL)
	{
		rodsLog (LOG_ERROR, "msiLoadMetadataFromXml: input rei or rsComm is NULL.");
		return (SYS_INTERNAL_NULL_INPUT_ERR);
	}

	rsComm = rei->rsComm;


	
	/********************************** RETRIEVE INPUT PARAMS **************************************/

	/* Get path of target object */
	rei->status = parseMspForDataObjInp (targetObj, &targetObjInp, &myTargetObjInp, 0);
	if (rei->status < 0)
	{
		rodsLog (LOG_ERROR, "msiLoadMetadataFromXml: input targetObj error. status = %d", rei->status);
		return (rei->status);
	}


	/* Get path of XML document */
	rei->status = parseMspForDataObjInp (xmlObj, &xmlDataObjInp, &myXmlDataObjInp, 0);
	if (rei->status < 0)
	{
		rodsLog (LOG_ERROR, "msiLoadMetadataFromXml: input xmlObj error. status = %d", rei->status);
		return (rei->status);
	}



	/******************************** OPEN AND READ FROM XML OBJECT ********************************/

	/* Open XML file */
	if ((xmlObjID = rsDataObjOpen(rsComm, &xmlDataObjInp)) < 0) 
	{
		rodsLog (LOG_ERROR, "msiLoadMetadataFromXml: Cannot open XML data object. status = %d", xmlObjID);
		return (xmlObjID);
	}


	/* Get size of XML file */
	rei->status = rsObjStat (rsComm, &xmlDataObjInp, &rodsObjStatOut);
	if (rei->status < 0 || !rodsObjStatOut)
	{
		rodsLog (LOG_ERROR, "msiLoadMetadataFromXml: Cannot stat XML data object. status = %d", rei->status);
		return (rei->status);
	}


	/* xmlBuf init */
	/* memory for xmlBuf->buf is allocated in rsFileRead() */
	xmlBuf = (bytesBuf_t *) malloc (sizeof (bytesBuf_t));
	memset (xmlBuf, 0, sizeof (bytesBuf_t));


	/* Read XML file */
	memset (&openedDataObjInp, 0, sizeof (openedDataObjInp_t));
	openedDataObjInp.l1descInx = xmlObjID;
	openedDataObjInp.len = (int)rodsObjStatOut->objSize;

	rei->status = rsDataObjRead (rsComm, &openedDataObjInp, xmlBuf);
	
	/* Make sure that the result is null terminated */
	if (strlen((char*)xmlBuf->buf) > (size_t)openedDataObjInp.len)
	{
		((char*)xmlBuf->buf)[openedDataObjInp.len-1]='\0';
	}


	/* Close XML file */
	rei->status = rsDataObjClose (rsComm, &openedDataObjInp);

	/* cleanup */
	freeRodsObjStat (rodsObjStatOut);



	/******************************** PARSE XML DOCUMENT ********************************/

	xmlSubstituteEntitiesDefault(1);
	xmlLoadExtDtdDefaultValue = 1;


	/* Parse xmlBuf.buf into an xmlDocPtr */
	doc = xmlParseDoc((xmlChar*)xmlBuf->buf);


	/* Create xpath evaluation context */
	xpathCtx = xmlXPathNewContext(doc);
	if(xpathCtx == NULL) 
	{
		rodsLog (LOG_ERROR, "msiLoadMetadataFromXml: Unable to create new XPath context.");
		xmlFreeDoc(doc); 
		return(-1);
	}


	/* Evaluate xpath expression */
	xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx);
	if(xpathObj == NULL) 
	{
		rodsLog (LOG_ERROR, "msiLoadMetadataFromXml: Unable to evaluate XPath expression \"%s\".", xpathExpr);
		xmlXPathFreeContext(xpathCtx); 
		xmlFreeDoc(doc); 
		return(-1);
	}

	/* How many AVU nodes did we get? */
	if ((nodes = xpathObj->nodesetval) != NULL)
	{
		avuNbr = nodes->nodeNr;
	}
	else 
	{
		avuNbr = 0;
	}



	/******************************** CREATE AVU TRIPLETS ********************************/

	/* Add a new AVU for each node. It's ok to process the nodes in forward order since we're not modifying them */
	for(i = 0; i < avuNbr; i++) 
	{
		if (nodes->nodeTab[i])
		{
//			/* temporary: Add index number to avoid duplicating attribute names */
//			memset(attrStr, '\0', MAX_NAME_LEN);
//			snprintf(attrStr, MAX_NAME_LEN - 1, "%04d: %s", i+1, (char*)xmlNodeGetContent(getChildNodeByName(nodes->nodeTab[i], "Attribute")) );

			/* Truncate if needed. No prefix. */
			memset(attrStr, '\0', max_attr_len);
			snprintf(attrStr, max_attr_len - 1, "%s", (char*)xmlNodeGetContent(getChildNodeByName(nodes->nodeTab[i], "Attribute")) );

			/* init modAVU input */
			memset (&modAVUMetadataInp, 0, sizeof(modAVUMetadataInp_t));
			modAVUMetadataInp.arg0 = "add";
			modAVUMetadataInp.arg1 = "-d";

			/* Use target object if one was provided, otherwise look for it in the XML doc */
			if (myTargetObjInp->objPath != NULL && strlen(myTargetObjInp->objPath) > 0)
			{
				modAVUMetadataInp.arg2 = myTargetObjInp->objPath;
			}
			else
			{
				modAVUMetadataInp.arg2 = xmlURIUnescapeString((char*)xmlNodeGetContent(getChildNodeByName(nodes->nodeTab[i], "Target")),
						MAX_NAME_LEN, NULL);
			}

			modAVUMetadataInp.arg3 = attrStr;
			modAVUMetadataInp.arg4 = (char*)xmlNodeGetContent(getChildNodeByName(nodes->nodeTab[i], "Value"));
			modAVUMetadataInp.arg5 = (char*)xmlNodeGetContent(getChildNodeByName(nodes->nodeTab[i], "Unit"));
			
			/* invoke rsModAVUMetadata() */
			rei->status = rsModAVUMetadata (rsComm, &modAVUMetadataInp);
		}
	}



	/************************************** WE'RE DONE **************************************/

	/* cleanup of all xml parsing stuff */
	xmlFreeDoc(doc);
        xmlCleanupParser();

	return (rei->status);
}
Пример #5
0
/**
 * \fn msiXmlDocSchemaValidate(msParam_t *xmlObj, msParam_t *xsdObj, msParam_t *status, ruleExecInfo_t *rei)
 *
 * \brief  This microservice validates an XML file against an XSD schema, both iRODS objects.
 * 
 * \module xml
 * 
 * \since pre-2.1
 * 
 * \author  Antoine de Torcy
 * \date    2008/05/29
 * 
 * \usage See clients/icommands/test/rules3.0/
 *
 * \param[in] xmlObj - a msParam of type DataObjInp_MS_T or STR_MS_T which is irods path of the XML object.
 * \param[in] xsdObj - a msParam of type DataObjInp_MS_T or STR_MS_T which is irods path of the XSD object.
 * \param[out] status - a msParam of type INT_MS_T which is a validation result.
 * \param[in,out] rei - The RuleExecInfo structure that is automatically
 *    handled by the rule engine. The user does not include rei as a
 *    parameter in the rule invocation.
 *
 * \DolVarDependence None
 * \DolVarModified None
 * \iCatAttrDependence None
 * \iCatAttrModified None
 * \sideeffect None
 *
 * \return integer
 * \retval 0 on success
 * \pre None
 * \post None
 * \sa None
**/
int 
msiXmlDocSchemaValidate(msParam_t *xmlObj, msParam_t *xsdObj, msParam_t *status, ruleExecInfo_t *rei) 
{
	/* for parsing msParams and to open iRODS objects */
	dataObjInp_t xmlObjInp, *myXmlObjInp;
	dataObjInp_t xsdObjInp, *myXsdObjInp;
	int xmlObjID, xsdObjID;

	/* for getting size of objects to read from */
	rodsObjStat_t *rodsObjStatOut = NULL;

	/* for reading from iRODS objects */
	openedDataObjInp_t openedDataObjInp;
	bytesBuf_t *xmlBuf = NULL;
	char *tail;

	/* for xml parsing and validating */
	xmlDocPtr doc, xsd_doc;
	xmlSchemaParserCtxtPtr parser_ctxt;
	xmlSchemaPtr schema;
	xmlSchemaValidCtxtPtr valid_ctxt;
	bytesBuf_t *errBuf;

	/* misc. to avoid repeating rei->rsComm */
	rsComm_t *rsComm;



	/*************************************  USUAL INIT PROCEDURE **********************************/
	
	/* For testing mode when used with irule --test */
	RE_TEST_MACRO ("    Calling msiXmlDocSchemaValidate")


	/* Sanity checks */
	if (rei == NULL || rei->rsComm == NULL)
	{
		rodsLog (LOG_ERROR, "msiXmlDocSchemaValidate: input rei or rsComm is NULL.");
		return (SYS_INTERNAL_NULL_INPUT_ERR);
	}

	rsComm = rei->rsComm;



	/************************************ ADDITIONAL INIT SETTINGS *********************************/

	/* XML constants */
	xmlSubstituteEntitiesDefault(1);
	xmlLoadExtDtdDefaultValue = 1;


	/* allocate memory for output error buffer */
	errBuf = (bytesBuf_t *)malloc(sizeof(bytesBuf_t));
	errBuf->buf = strdup("");
	errBuf->len = strlen((char*)errBuf->buf);

	/* Default status is failure, overwrite if success */
	fillBufLenInMsParam (status, -1, NULL);

	
	/********************************** RETRIEVE INPUT PARAMS **************************************/

	/* Get path of XML document */
	rei->status = parseMspForDataObjInp (xmlObj, &xmlObjInp, &myXmlObjInp, 0);
	if (rei->status < 0)
	{
		rodsLog (LOG_ERROR, "msiXmlDocSchemaValidate: input xmlObj error. status = %d", rei->status);
		free(errBuf);
		return (rei->status);
	}


	/* Get path of schema */
	rei->status = parseMspForDataObjInp (xsdObj, &xsdObjInp, &myXsdObjInp, 0);
	if (rei->status < 0)
	{
		rodsLog (LOG_ERROR, "msiXmlDocSchemaValidate: input xsdObj error. status = %d", rei->status);
		free(errBuf);
		return (rei->status);
	}


	/******************************** OPEN AND READ FROM XML OBJECT ********************************/

	/* Open XML file */
	if ((xmlObjID = rsDataObjOpen(rsComm, &xmlObjInp)) < 0) 
	{
		rodsLog (LOG_ERROR, "msiXmlDocSchemaValidate: Cannot open XML data object. status = %d", xmlObjID);
		free(errBuf);
		return (xmlObjID);
	}


	/* Get size of XML file */
	rei->status = rsObjStat (rsComm, &xmlObjInp, &rodsObjStatOut);
	if (rei->status < 0 || !rodsObjStatOut)
	{
		rodsLog (LOG_ERROR, "msiXmlDocSchemaValidate: Cannot stat XML data object. status = %d", rei->status);
		free(errBuf);
		return (rei->status);
	}


	/* xmlBuf init */
	/* memory for xmlBuf->buf is allocated in rsFileRead() */
	xmlBuf = (bytesBuf_t *) malloc (sizeof (bytesBuf_t));
	memset (xmlBuf, 0, sizeof (bytesBuf_t));


	/* Read content of XML file */
	memset (&openedDataObjInp, 0, sizeof (openedDataObjInp_t));
	openedDataObjInp.l1descInx = xmlObjID;
	openedDataObjInp.len = (int)rodsObjStatOut->objSize + 1;	/* extra byte to add a null char */

	rei->status = rsDataObjRead (rsComm, &openedDataObjInp, xmlBuf);

	/* add terminating null character */
	tail = (char*)xmlBuf->buf;
	tail[openedDataObjInp.len - 1] = '\0';


	/* Close XML file */
	rei->status = rsDataObjClose (rsComm, &openedDataObjInp);

	/* cleanup */
	freeRodsObjStat (rodsObjStatOut);



	/*************************************** PARSE XML DOCUMENT **************************************/

	/* Parse xmlBuf.buf into an xmlDocPtr */
	doc = xmlParseDoc((xmlChar*)xmlBuf->buf);
	clearBBuf(xmlBuf);

	if (doc == NULL)
	{
		rodsLog (LOG_ERROR, "msiXmlDocSchemaValidate: XML document cannot be loaded or is not well-formed.");
		free(errBuf);
	    xmlCleanupParser();

	    return (USER_INPUT_FORMAT_ERR);
	}



	/******************************** OPEN AND READ FROM XSD OBJECT ********************************/

	/* Open schema file */
	if ((xsdObjID = rsDataObjOpen(rsComm, &xsdObjInp)) < 0) 
	{
		rodsLog (LOG_ERROR, "msiXmlDocSchemaValidate: Cannot open XSD data object. status = %d", xsdObjID);
		free(errBuf);
		xmlFreeDoc(doc);
	    xmlCleanupParser();

		return (xsdObjID);
	}


	/* Get size of schema file */
	rei->status = rsObjStat (rsComm, &xsdObjInp, &rodsObjStatOut);


	/* Read entire schema file */
	memset (&openedDataObjInp, 0, sizeof (openedDataObjInp_t));
	openedDataObjInp.l1descInx = xsdObjID;
	openedDataObjInp.len = (int)rodsObjStatOut->objSize + 1;	/* to add null char */

	rei->status = rsDataObjRead (rsComm, &openedDataObjInp, xmlBuf);

	/* add terminating null character */
	tail = (char*)xmlBuf->buf;
	tail[openedDataObjInp.len - 1] = '\0';


	/* Close schema file */
	rei->status = rsDataObjClose (rsComm, &openedDataObjInp);

	/* cleanup */
	freeRodsObjStat (rodsObjStatOut);



	/*************************************** PARSE XSD DOCUMENT **************************************/

	/* Parse xmlBuf.buf into an xmlDocPtr */
	xsd_doc = xmlParseDoc((xmlChar*)xmlBuf->buf);
	clearBBuf(xmlBuf);

	if (xsd_doc == NULL)
	{
		rodsLog (LOG_ERROR, "msiXmlDocSchemaValidate: XML Schema cannot be loaded or is not well-formed.");
		free(errBuf);
		xmlFreeDoc(doc);
		xmlCleanupParser();

	    return (USER_INPUT_FORMAT_ERR);
	}



	/**************************************** VALIDATE DOCUMENT **************************************/

	/* Create a parser context */
	parser_ctxt = xmlSchemaNewDocParserCtxt(xsd_doc);
	if (parser_ctxt == NULL)
	{
		rodsLog (LOG_ERROR, "msiXmlDocSchemaValidate: Unable to create a parser context for the schema.");
		free(errBuf);
		xmlFreeDoc(xsd_doc);
		xmlFreeDoc(doc);
	    xmlCleanupParser();

	    return (USER_INPUT_FORMAT_ERR);
	}


	/* Parse the XML schema */
	schema = xmlSchemaParse(parser_ctxt);
	if (schema == NULL) 
	{
		rodsLog (LOG_ERROR, "msiXmlDocSchemaValidate: Invalid schema.");
		free(errBuf);
		xmlSchemaFreeParserCtxt(parser_ctxt);
		xmlFreeDoc(doc);
		xmlFreeDoc(xsd_doc);
        xmlCleanupParser();

	    return (USER_INPUT_FORMAT_ERR);
	}


	/* Create a validation context */
	valid_ctxt = xmlSchemaNewValidCtxt(schema);
	if (valid_ctxt == NULL) 
	{
		rodsLog (LOG_ERROR, "msiXmlDocSchemaValidate: Unable to create a validation context for the schema.");
		free(errBuf);
		xmlSchemaFree(schema);
		xmlSchemaFreeParserCtxt(parser_ctxt);
		xmlFreeDoc(xsd_doc);
		xmlFreeDoc(doc);
	    xmlCleanupParser();

	    return (USER_INPUT_FORMAT_ERR);
	}


	/* Set myErrorCallback() as the default handler for error messages and warnings */
	xmlSchemaSetValidErrors(valid_ctxt, (xmlSchemaValidityErrorFunc)myErrorCallback, (xmlSchemaValidityWarningFunc)myErrorCallback, errBuf);


	/* Validate XML doc */
	rei->status = xmlSchemaValidateDoc(valid_ctxt, doc);



	/******************************************* WE'RE DONE ******************************************/

	/* return both error code and messages through status */
	resetMsParam (status);
	fillBufLenInMsParam (status, rei->status, errBuf);


	/* cleanup of all xml parsing stuff */
	xmlSchemaFreeValidCtxt(valid_ctxt);
	xmlSchemaFree(schema);
	xmlSchemaFreeParserCtxt(parser_ctxt);
	xmlFreeDoc(doc);
	xmlFreeDoc(xsd_doc);
	xmlCleanupParser();

	return (rei->status);
}
Пример #6
0
int _writeString( char *writeId, char *writeStr, ruleExecInfo_t *rei ) {

    // =-=-=-=-=-=-=-
    // JMC - backport 4619
    dataObjInp_t dataObjInp;
    openedDataObjInp_t openedDataObjInp;
    bytesBuf_t tmpBBuf;
    int fd, i;
    // =-=-=-=-=-=-=-

    if ( writeId != NULL && strcmp( writeId, "serverLog" ) == 0 ) {
        rodsLog( LOG_NOTICE, "writeString: inString = %s", writeStr );
        return 0;
    }

    // =-=-=-=-=-=-=-
    // JMC - backport 4619
    if ( writeId != NULL && writeId[0] == '/' ) {
        /* writing to an existing iRODS file */

        if ( rei == NULL || rei->rsComm == NULL ) {
            rodsLog( LOG_ERROR, "_writeString: input rei or rsComm is NULL" );
            return SYS_INTERNAL_NULL_INPUT_ERR;
        }

        bzero( &dataObjInp, sizeof( dataObjInp ) );
        dataObjInp.openFlags = O_RDWR;
        snprintf( dataObjInp.objPath, MAX_NAME_LEN, "%s", writeId );
        fd = rsDataObjOpen( rei->rsComm, &dataObjInp );
        if ( fd < 0 ) {
            rodsLog( LOG_ERROR, "_writeString: rsDataObjOpen failed. status = %d", fd );
            return fd;
        }

        bzero( &openedDataObjInp, sizeof( openedDataObjInp ) );
        openedDataObjInp.l1descInx = fd;
        openedDataObjInp.offset = 0;
        openedDataObjInp.whence = SEEK_END;
        fileLseekOut_t *dataObjLseekOut = NULL;
        i = rsDataObjLseek( rei->rsComm, &openedDataObjInp, &dataObjLseekOut );
        free( dataObjLseekOut );
        if ( i < 0 ) {
            rodsLog( LOG_ERROR, "_writeString: rsDataObjLseek failed. status = %d", i );
            return i;
        }

        bzero( &openedDataObjInp, sizeof( openedDataObjInp ) );
        openedDataObjInp.l1descInx = fd;
        tmpBBuf.len = openedDataObjInp.len = strlen( writeStr ) + 1;
        tmpBBuf.buf =  writeStr;
        i = rsDataObjWrite( rei->rsComm, &openedDataObjInp, &tmpBBuf );
        if ( i < 0 ) {
            rodsLog( LOG_ERROR, "_writeString: rsDataObjWrite failed. status = %d", i );
            return i;
        }

        bzero( &openedDataObjInp, sizeof( openedDataObjInp ) );
        openedDataObjInp.l1descInx = fd;
        i = rsDataObjClose( rei->rsComm, &openedDataObjInp );
        return i;
    }

    // =-=-=-=-=-=-=-

    msParam_t * mP = NULL;
    msParamArray_t * inMsParamArray = rei->msParamArray;
    execCmdOut_t *myExecCmdOut;
    if ( ( ( mP = getMsParamByLabel( inMsParamArray, "ruleExecOut" ) ) != NULL ) &&
            ( mP->inOutStruct != NULL ) ) {
        if ( !strcmp( mP->type, STR_MS_T ) ) {
            myExecCmdOut = ( execCmdOut_t* )malloc( sizeof( execCmdOut_t ) );
            memset( myExecCmdOut, 0, sizeof( execCmdOut_t ) );
            mP->inOutStruct = myExecCmdOut;
            mP->type = strdup( ExecCmdOut_MS_T );
        }
        else {
            myExecCmdOut = ( execCmdOut_t* )mP->inOutStruct;
        }
    }
    else {
        myExecCmdOut = ( execCmdOut_t* )malloc( sizeof( execCmdOut_t ) );
        memset( myExecCmdOut, 0, sizeof( execCmdOut_t ) );
        if ( mP == NULL ) {
            addMsParam( inMsParamArray, "ruleExecOut", ExecCmdOut_MS_T, myExecCmdOut, NULL );
        }
        else {
            mP->inOutStruct = myExecCmdOut;
            mP->type = strdup( ExecCmdOut_MS_T );
        }
    }

    /***** Jun 27, 2007
           i  = replaceVariablesAndMsParams("",writeStr, rei->msParamArray, rei);
           if (i < 0)
           return i;
    ****/

    if ( writeId != NULL ) {
        if ( !strcmp( writeId, "stdout" ) ) {
            appendToByteBuf( &( myExecCmdOut->stdoutBuf ), ( char * ) writeStr );
        }
        else if ( !strcmp( writeId, "stderr" ) ) {
            appendToByteBuf( &( myExecCmdOut->stderrBuf ), ( char * ) writeStr );
        }
    }

    return 0;
}
Пример #7
0
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);
}
Пример #8
0
static int process_single_obj( rsComm_t *conn, char *parColl, char *fileName,
                               int required_num_replicas, char *grpRescForReplication, char *emailToNotify ) {
    genQueryInp_t genQueryInp;
    int i;
    genQueryOut_t *genQueryOut = NULL;
    sqlResult_t *replNumStruct, *rescStruct, *dataPathStruct, *chkSumStruct;
    char *replNum, *rescName, *dataPathName, *chkSum;
    int t;

    int i1a[10];
    int i1b[10];
    int i2a[10];
    char *condVal[2];
    char v1[200], v2[200];
    char vault_path[2048];

    char *chksum_str = NULL;
    dataObjInp_t myDataObjInp;
    dataObjInfo_t *myDataObjInfo = NULL;
    unregDataObj_t myUnregDataObjInp;
    transferStat_t *transStat = NULL;

    ReplicaCheckStatusStruct *pReplicaStatus;
    int nReplicas;

    char tmpstr[1024];

    int at_least_one_copy_is_good = 0;
    int newN;
    int rn;

    int validKwFlags;
    char *outBadKeyWd;
    msParam_t msGrpRescStr;   /* it can be a single resc name or a paired values. */

    /* fprintf(stderr,"msiAutoReplicateService():process_single_obj()\n");  */

    memset( &genQueryInp, 0, sizeof( genQueryInp_t ) );
    i1a[0] = COL_DATA_REPL_NUM;
    i1b[0] = 0;
    i1a[1] = COL_D_RESC_NAME;
    i1b[1] = 0;
    i1a[2] = COL_D_RESC_GROUP_NAME;
    i1b[2] = 0;
    i1a[3] = COL_D_DATA_PATH;
    i1b[3] = 0;
    i1a[4] = COL_D_DATA_CHECKSUM;
    i1b[4] = 0;
    genQueryInp.selectInp.inx = i1a;
    genQueryInp.selectInp.value = i1b;
    genQueryInp.selectInp.len = 5;

    i2a[0] = COL_COLL_NAME;
    i2a[1] = COL_DATA_NAME;
    genQueryInp.sqlCondInp.inx = i2a;
    sprintf( v1, "='%s'", parColl );
    condVal[0] = v1;
    sprintf( v2, "='%s'", fileName );
    condVal[1] = v2;
    genQueryInp.sqlCondInp.value = condVal;
    genQueryInp.sqlCondInp.len = 2;

    genQueryInp.maxRows = 10;
    genQueryInp.continueInx = 0;
    t = rsGenQuery( conn, &genQueryInp, &genQueryOut );
    if ( t < 0 ) {
        rodsLog( LOG_NOTICE, "msiAutoReplicateService():process_single_obj(): rsGenQuery failed errocode=%d", t );
        if ( t == CAT_NO_ROWS_FOUND ) { /* no data is found */
            return 0;
        }

        return( t );
    }

    if ( genQueryOut->rowCnt <= 0 ) {
        rodsLog( LOG_ERROR, "msiAutoReplicateService():process_single_obj(): return 0 record from calling rsGenQuery() for objid=%s/%s", parColl, fileName );
        return 0;
    }

    nReplicas = genQueryOut->rowCnt;
    pReplicaStatus = ( ReplicaCheckStatusStruct * )calloc( nReplicas, sizeof( ReplicaCheckStatusStruct ) );

    for ( i = 0; i < nReplicas; i++ ) {
        pReplicaStatus[i].registered = 0;
        pReplicaStatus[i].checksum[0] = '\0';
    }

    for ( i = 0; i < genQueryOut->rowCnt; i++ ) {
        replNumStruct = getSqlResultByInx( genQueryOut, COL_DATA_REPL_NUM );
        replNum = &replNumStruct->value[replNumStruct->len * i];
        pReplicaStatus[i].repl_num = atoi( replNum );

        rescStruct = getSqlResultByInx( genQueryOut, COL_D_RESC_NAME );
        rescName = &rescStruct->value[rescStruct->len * i];

        getSqlResultByInx( genQueryOut, COL_D_RESC_GROUP_NAME );

        dataPathStruct = getSqlResultByInx( genQueryOut, COL_D_DATA_PATH );
        dataPathName = &dataPathStruct->value[dataPathStruct->len * i];

        chkSumStruct = getSqlResultByInx( genQueryOut, COL_D_DATA_CHECKSUM );
        chkSum = &chkSumStruct->value[chkSumStruct->len * i];

        vault_path[0] = '\0';
        t = get_resource_path( conn, rescName, vault_path );
        if ( t < 0 ) {
            rodsLog( LOG_NOTICE, "msiAutoReplicateService():process_single_obj():get_resource_path failed, status=%d", t );
            free( pReplicaStatus ); // JMc cppcheck - leak
            return t;
        }

        if ( strncmp( dataPathName, vault_path, strlen( vault_path ) ) != 0 ) {
            /* fprintf(stderr,"AB1-> %s/%s, v=%s, is a registered copy.\n", parColl,fileName, replNum); */
            pReplicaStatus[i].registered = 1;
        }
        else {
            pReplicaStatus[i].registered = 0;
        }

        if ( ( chkSum != NULL ) && ( strlen( chkSum ) > 0 ) ) {
            strcpy( pReplicaStatus[i].checksum, chkSum );
        }
    }
    freeGenQueryOut( &genQueryOut );

    /* check replica status */
    at_least_one_copy_is_good = 0;
    for ( i = 0; i < nReplicas; i++ ) {
        /* check the file existence first */
        memset( &myDataObjInp, 0, sizeof( dataObjInp_t ) );
        snprintf( myDataObjInp.objPath, MAX_NAME_LEN, "%s/%s", parColl, fileName );
        myDataObjInp.openFlags = O_RDONLY;
        sprintf( tmpstr, "%d", pReplicaStatus[i].repl_num );
        addKeyVal( &myDataObjInp.condInput, REPL_NUM_KW, tmpstr );
        rn = pReplicaStatus[i].repl_num;
        t = rsDataObjOpen( conn, &myDataObjInp );
        if ( t < 0 ) {
            /* fprintf(stderr,"%d. %s/%s, %d failed to open and has checksum status=%d\n", i, parColl, fileName, rn, t); */
            if ( t == SYS_OUT_OF_FILE_DESC ) {
                free( pReplicaStatus ); // JMc cppcheck - leak
                return t;
            }
            else {
                pReplicaStatus[i].chksum_status = t;
            }
        }
        else {
            openedDataObjInp_t myDataObjCloseInp;
            memset( &myDataObjCloseInp, 0, sizeof( openedDataObjInp_t ) );
            myDataObjCloseInp.l1descInx = t;
            t = rsDataObjClose( conn, &myDataObjCloseInp );

            chksum_str =  NULL;
            /* compute checksum rsDataObjChksum() */
            memset( &myDataObjInp, 0, sizeof( dataObjInp_t ) );
            sprintf( myDataObjInp.objPath, "%s/%s", parColl, fileName );
            addKeyVal( &myDataObjInp.condInput, FORCE_CHKSUM_KW, "" );
            sprintf( tmpstr, "%d", pReplicaStatus[i].repl_num );
            addKeyVal( &myDataObjInp.condInput, REPL_NUM_KW, tmpstr );
            t = rsDataObjChksum( conn, &myDataObjInp, &chksum_str );
            pReplicaStatus[i].chksum_status = t;     /* t == USER_CHKSUM_MISMATCH means a bad copy */
            /* fprintf(stderr,"%d. %s/%s, %d has checksum status=%d\n", i, parColl, fileName, rn, t); */
            if ( t >= 0 ) {
                if ( strlen( pReplicaStatus[i].checksum ) > 0 ) {
                    if ( strcmp( pReplicaStatus[i].checksum, chksum_str ) != 0 ) { /* mismatch */
                        pReplicaStatus[i].chksum_status = USER_CHKSUM_MISMATCH;
                    }
                    else {
                        at_least_one_copy_is_good = 1;
                    }
                }
                else {
                    at_least_one_copy_is_good = 1;
                }
            }
        }
    }

    /* if there is none good copies left. In some casee, the checksum failed due
       to the fact that the server is down. We leave this case to be taken care of next time. */
    if ( at_least_one_copy_is_good == 0 ) {
        rodsLog( LOG_ERROR, "msiAutoReplicateService():process_single_obj(): Obj='%s/%s': Warning: The system detects that all copies might be corrupted.", parColl, fileName );

#ifndef windows_platform
        if ( ( emailToNotify != NULL ) && ( strlen( emailToNotify ) > 0 ) ) {
            char msg_sub[1024], msg_body[1024];
            strcpy( msg_sub, "iRODS msiAutoReplicateService() error" );
            sprintf( msg_body, "msiAutoReplicateService():process_single_obj(): Obj='%s/%s': at least one storage server is down or all copies are corrupted.",
                     parColl, fileName );
            UnixSendEmail( emailToNotify, msg_sub, msg_body );
        }
#endif

        free( pReplicaStatus ); // JMc cppcheck - leak
        return 0;
    }

    /* since we have at least one copy is good. We delete those bad copies (USER_CHKSUM_MISMATCH). */
    newN = nReplicas;
    for ( i = 0; i < nReplicas; i++ ) {
        memset( &myDataObjInp, 0, sizeof( dataObjInp_t ) );
        sprintf( myDataObjInp.objPath, "%s/%s", parColl, fileName );
        sprintf( tmpstr, "%d", pReplicaStatus[i].repl_num );
        addKeyVal( &myDataObjInp.condInput, REPL_NUM_KW, tmpstr );
        rn = pReplicaStatus[i].repl_num;
        if ( pReplicaStatus[i].registered == 1 ) {
            /* here is the catch. iRODS. */
            int adchksum;
            /* fprintf(stderr,"CD->%s/%s, v=%d, is a registered copy.\n", parColl, fileName, rn); */
            adchksum = ( ( int )( pReplicaStatus[i].chksum_status / 1000 ) ) * 1000;
            if ( ( pReplicaStatus[i].chksum_status == USER_CHKSUM_MISMATCH ) || ( pReplicaStatus[i].chksum_status == UNIX_FILE_OPEN_ERR ) || ( adchksum == UNIX_FILE_OPEN_ERR ) )
                /* USER_CHKSUM_MISMATCH  -> indicates the registered file is changed.
                 * UNIX_FILE_OPEN_ERR --> indicates the registered file is removed by original owner.
                 * -510002 is transformed from UNIX open error.
                 */
            {
                rodsLog( LOG_NOTICE, "msiAutoReplicateService():process_single_obj(): registered copy will be removed: %s, repl=%d", myDataObjInp.objPath, rn );
                t = getDataObjInfo( conn, &myDataObjInp, &myDataObjInfo, NULL, 0 );
                if ( t >= 0 ) {
                    myUnregDataObjInp.dataObjInfo = myDataObjInfo;
                    myUnregDataObjInp.condInput = &myDataObjInp.condInput;
                    t = rsUnregDataObj( conn, &myUnregDataObjInp );
                    if ( t >= 0 ) {
                        newN = newN - 1;
                    }
                    else  {
                        rodsLog( LOG_ERROR, "msiAutoReplicateService():rsUnregDataObj(): failed for %s/%s:%d. erStat=%d", parColl, fileName, rn, t );
                        return t;
                    }
                }
                else {
                    rodsLog( LOG_ERROR, "msiAutoReplicateService():getDataObjInfo(): failed for %s/%s:%d. erStat=%d", parColl, fileName, rn, t );
                    return t;
                }
            }
            else {
                rodsLog( LOG_ERROR, "%s:%d, the registered copy has errored checksum status=%d.", myDataObjInp.objPath, rn, pReplicaStatus[i].chksum_status );
                return t;
            }
        }
        else { /* the data file is in vault */
            if ( pReplicaStatus[i].chksum_status == USER_CHKSUM_MISMATCH ) {
                t = rsDataObjUnlink( conn, &myDataObjInp );
                if ( t >= 0 ) {
                    newN = newN - 1;
                }
                else  {
                    rodsLog( LOG_ERROR, "msiAutoReplicateService():rsDataObjUnlink() for %s:%d failed. errStat=%d", myDataObjInp.objPath, rn, t );
                    free( pReplicaStatus ); // JMc cppcheck - leak
                    return t;
                }
            }
        }
    }

    fillStrInMsParam( &msGrpRescStr, grpRescForReplication );

    /* make necessary copies based on the required number of copies */
    if ( newN < required_num_replicas ) {
        rodsLog( LOG_NOTICE, "msiAutoReplicateService():process_single_obj(): making necessary %d copies as required.", ( required_num_replicas - newN ) );
        for ( i = 0; i < ( required_num_replicas - newN ); i++ ) {
            memset( &myDataObjInp, 0, sizeof( dataObjInp_t ) );
            snprintf( myDataObjInp.objPath, MAX_NAME_LEN, "%s/%s", parColl, fileName );
            /* addKeyVal(&myDataObjInp.condInput, DEST_RESC_NAME_KW, grpRescForReplication); */
            validKwFlags = OBJ_PATH_FLAG | DEST_RESC_NAME_FLAG | NUM_THREADS_FLAG |
                           BACKUP_RESC_NAME_FLAG | RESC_NAME_FLAG | UPDATE_REPL_FLAG |
                           REPL_NUM_FLAG | ALL_FLAG | ADMIN_FLAG | VERIFY_CHKSUM_FLAG |
                           RBUDP_TRANSFER_FLAG | RBUDP_SEND_RATE_FLAG | RBUDP_PACK_SIZE_FLAG;
            t = parseMsKeyValStrForDataObjInp( &msGrpRescStr, &myDataObjInp, DEST_RESC_NAME_KW, validKwFlags, &outBadKeyWd );
            if ( t < 0 ) {
                if ( outBadKeyWd != NULL ) {
                    rodsLog( LOG_ERROR, "msiAutoReplicateService():rsDataObjRepl(): input keyWd - %s error. status = %d", outBadKeyWd, t );
                    free( outBadKeyWd );
                }
                else {
                    rodsLog( LOG_ERROR, "msiAutoReplicateService():rsDataObjRepl(): input msKeyValStr error. status = %d", t );
                }

                free( pReplicaStatus ); // JMc cppcheck - leak
                return t;
            }

            t = rsDataObjRepl( conn, &myDataObjInp, &transStat );
            if ( t < 0 ) {
                rodsLog( LOG_ERROR, "msiAutoReplicateService():rsDataObjRepl() failed for %s/%s:%d into '%s'. err code=%d.", parColl, fileName, rn, grpRescForReplication, t );
                repl_storage_error = 1;
                free( pReplicaStatus ); // JMc cppcheck - leak
                return t;
            }
            if ( transStat != NULL ) {
                free( transStat );
            }
        }
    }

    free( pReplicaStatus ); // JMC cppcheck - leak
    return 0;
}