//****************************************************************************** //****************************************************************************** // Code disclaimer information //------------------------------------------------------------------------------ // This file contains programming code examples. // // IBM grants you a nonexclusive copyright license to use all programming // code examples from which you can generate similar functions tailored to // your own specific needs. // // All sample code is provided by IBM for illustrative purposes only. // These examples have not been thoroughly tested under all conditions. IBM, // therefore, cannot guarantee or imply reliability, serviceability, or // function of these programs. // // All programs contained herein are provided to you "AS IS" without any // warranties of any kind. The implied warranties of non-infringement, // merchantability, and fitness for a particular purpose are expressly // disclaimed. //****************************************************************************** //****************************************************************************** //-- START OF SPECIFICATIONS ------------------------------------------------ // // Source File Name : rpl.C // // Module Name : RPL // // Program Name : RPL // // Source File Description: Source file containing the exit program used on // the RCVJRNE on the remote journal residing on // the psuedo-target system. // //****** WARNING ***** PLEASE READ ME ****************************************** // USE OF THIS SOURCE CODE IS AT YOUR OWN RISK. // This code is being used in the IFS Journaling Replication demo that was // first used at COMMON in March 2003. This code is NOT a complete replication // solution, and should not be used to provide object or data replication. // It was written to provide a way to demo replication of a small subset of IFS // journal entries using a remote journal on the SAME system. It is being made // available for public browsing as an example what was really involved in // performing some of the steps required in providing IFS object/data // replication. Therefore, some of the code within this demo takes shortcuts // that would not be available in a normal replication environment involving // separate source and target systems. //****************************************************************************** // // // Change Activity : // // CFD List : // // FLAG REASON RELEASE DATE PGMR CHANGE DESCRIPTION // ---- --------- ---------- ------ --------- ---------------------------------- // $A0= DEMO xxxx 030129 IBMG8PA: New module // // End CFD List. // // Additional notes about the Change Activity // // End Change Activity. // //------------------------------------------------------------------------------ #include "rplcmn.H" #include "fidtbl.H" #include #include #include #include #include #include #include #include #include #include #include #include // Declare the FID table pointer global to this program. This is done for // simplicity here, since many functions in here will be needing access // to it. static FIDTable *FIDTblP = NULL; void getLGfromName(Qp0l_Object_Name_t *nameP, Qlg_Path_Name_T *newP); mode_t getModeFromJournalEntryAuths(Qp0l_Journal_Entry_Auth_t *ownerP, Qp0l_Journal_Entry_Auth_t *groupP, Qp0l_Journal_Entry_Auth_t *publicP); int changeAuths(Qp0l_Journal_Entry_Auth_t &auths, Qlg_Path_Name_T *pathP, char *userName); int getPathFromFileIDIn37(Qp0lFID_t *fid, char *pathBuf); int processAA(Qjo_RJNE0100_JE_Hdr_t *entHdrP); int processB1(Qjo_RJNE0100_JE_Hdr_t *entHdrP); int processB4(Qjo_RJNE0100_JE_Hdr_t *entHdrP); int processWA(Qjo_RJNE0100_JE_Hdr_t *entHdrP); int processTR(Qjo_RJNE0100_JE_Hdr_t *entHdrP); int processJE(Qjo_RJNE0100_JE_Hdr_t *entHdrP); //-- START OF FUNCTION SPECIFICATIONS -------------------------------------- // // Function Name : rpl (main) // // Descriptive Name : Exit program for RCVJRNE. It does the majority // of the work for the replicator demo. // This program is the exit program passed to the // RCVJRNE command, and is called by that command // when a matching journal entry is received. // // // Input : // argv[1] - Contents of journal entry received. Only valid if // argv[2][0] indicates '1'. When passed, it will be in the // Qjo_RJNE0100_JE_Hdr_t format for us. // argv[2] - Status indicator. We will care about the following values: // '0' - No entry passed. No problems. Simply return. // '1' - Got an entry passed in argv[1]. // '3' - Original journal receiver is no longer attached. // '4' - Journal state is inactive. // //-- END OF SPECIFICATIONS ------------------------------------------------- int main(int argc, char *argv[]) { int rc = 0; // Check the status passed to us from the system. switch (argv[2][0]) { case '1': break; case '0': case '3': case '4': default: return -1; } // // We assume if we got here, we got an entry passed. Process it. // // // First, set our global pointer to the FID Table. // _SYSPTR usrspcP; usrspcP = getUsrspcPtr(); if (usrspcP == NULL) { return -1; } // Set our global pointer to the FID table. The object has already been // constructed in the user space by the REPLAY *PGM which did the RCVJRNE. FIDTblP = (FIDTable *)setsppfp(usrspcP); Qjo_RJNE0100_Hdr_t *hdrP = (Qjo_RJNE0100_Hdr_t *)argv[1]; Qjo_RJNE0100_JE_Hdr_t *jeHdrP = (Qjo_RJNE0100_JE_Hdr_t *) ((char *)hdrP + hdrP->Offset_First_Jrn_Entry); // Map the input entry information to the structure definition and // process the entry. rc = processJE(jeHdrP); return(rc); } //-- START OF FUNCTION SPECIFICATION --------------------------------------- // // Function Name : processJE // // Descriptive Name : Process a received journal entry. // // Function Description: Process a received journal entry. // // Prototype Location : None. // // Dependencies : None. // // Restrictions : None. // // Exception Handlers : None. // // Diagnostic Messages : None. // // Escape Messages : None. // // Input : // // entHdrP (input) // Pointer to the journal entry header describing the entry. // // Exit Normal // Return Value : 0 // Outputs : Entry has been replayed. // // Exit Error // Return Value : -1 // Outputs : // //-- END OF FUNCTION SPECIFICATION ----------------------------------------- int processJE(Qjo_RJNE0100_JE_Hdr_t *entHdrP) { int rc = 0; char cmdString[MAX_PATH_LENGTH + 100]; // Buffer used for building command strings. // // Validate journal code. 'B' is only IFS entry. // if (entHdrP->Jrn_Code != 'B') { // Not an IFS entry type. return -1; } // // Determine which entry type we got, and process it appropriately. // switch(*((unsigned short *)entHdrP->Entry_Type)) { case 0xC1C1: // AA rc = processAA(entHdrP); break; case 0xC2F1: // B1 - Create summary rc = processB1(entHdrP); break; case 0xC2F4: // B4 - Unlink (dir) rc = processB4(entHdrP); break; case 0xC2F5: // B5 - Unlink (link) // No-op B5 for this demo. As long as we always use inherit-yes and don't // pick and choose objects, our parent will always be journaled and // therefore we'll always get a B4 which we do support in this demo version. // rc = processB5(entHdrP); break; case 0xE3D9: // TR - Truncate after image rc = processTR(entHdrP); break; case 0xE6C1: // WA - Write after image rc = processWA(entHdrP); break; case 0xC2F2: // B2 - Add hard link // Not demo-able from GUI. break; case 0xC2F3: // B3 - Rename/move // Only do if time permits. break; case 0xC6C1: // FA - Attribute change case 0xD6C1: // OA - Change authority case 0xD6C7: // OG - Change PGP case 0xD6D6: // OO - Change owner case 0xC1D1: // AJ - Start apply. case 0xC1E3: // AT - End apply. case 0XC2C4: // BD - Destroyed case 0xC2F0: // B0 - Begin create case 0xC2F6: // B6 - Reserved case 0xC2F7: // B7 - Reserved case 0xC2F8: // B8 - Reserved case 0xC2F9: // B9 - Reserved case 0xC3E2: // CS - Close case 0xC5E3: // ET - End journaling case 0xC6C3: // FC - Force case 0xC6C6: // FF - Save storage freed case 0xC6D9: // FR - Restored case 0xC6E2: // FS - Save case 0xC6E6: // FW - Checkpoint entry from SWA case 0xD1E3: // JT - Start journaling case 0xD6C6: // OF - Open case 0xD6C9: // OI - In use at abnormal IPL case 0xD9C5: // RE - End of remove case 0xD9C9: // RI - Start of remove case 0xE3C2: // TB - Truncate before image. case 0xE6C2: // WB - Write before image default: break; } // switch of entry type return(rc); } int processAA(Qjo_RJNE0100_JE_Hdr_t *entHdrP) { int rc; char cmdString[MAX_PATH_LENGTH + 100]; // Buffer used for building command strings. // Access the Entry Specific Data structure for this entry type. Qjo_RJNE0100_JE_ESD_t *esdP = (Qjo_RJNE0100_JE_ESD_t *) (((char *)entHdrP) + entHdrP->Dsp_Entry_Specific_Data); Qp0l_AA_Journal_Entry_t *entP = (Qp0l_AA_Journal_Entry_t *) &esdP->ESD; // Build the path to the object. char path[MAX_PATH_LENGTH]; rc = FIDTblP->getTgtPath(path, *(Qp0lFID_t *)&entHdrP->Object); if (rc != 0) { return(-1); } // Build the command string. There isn't an API to change the // auditing value. sprintf(cmdString, "CHGAUD OBJ('%s') OBJAUD(%10.10s", path, entP->AuditingVal); strcat(cmdString,")"); // Do it this way so we dont need to null-term the val. if (system(cmdString) != 0) { return(-1); } return 0; } int processB1(Qjo_RJNE0100_JE_Hdr_t *entHdrP) { int rc; char cmdString[MAX_PATH_LENGTH + 100]; // Buffer used for building command strings. // Access the Entry Specific Data structure for this entry type. Qjo_RJNE0100_JE_ESD_t *esdP = (Qjo_RJNE0100_JE_ESD_t *) (((char *)entHdrP) + entHdrP->Dsp_Entry_Specific_Data); Qp0l_B1_Journal_Entry_t *entP = (Qp0l_B1_Journal_Entry_t *) &esdP->ESD; // Build the path to the directory that caused this entry. // We will later append the new object's name to this path. char path[MAX_PATH_LENGTH]; rc = FIDTblP->getTgtPath(path, *(Qp0lFID_t *)&entHdrP->Object); if (rc != 0) { return(-1); } // Qp0l_Object_Name_t *nameP = (Qp0l_Object_Name_t *) (entP->NameOffset + (char *)entP); // Dir is already in job CCSID. Instead of messing with conversion, // particularly because we keep the entries in the FIDTable in job // CCSID, but the names in ESD's will be in UNICODE, // let's change the CWD of the job to the parent. No other threads // are running in this replay job anyways. rc = chdir(path); if (rc != 0) { return(-1); } // Since we simply changed to CWD, we can use the name directly as // a relative path on a Qlg interface. // Build us a Qlg_Path_Name_t. char newObj[MAX_PATH_LENGTH]; Qlg_Path_Name_T *newObjNameP = (Qlg_Path_Name_T *)newObj; getLGfromName(nameP, newObjNameP); mode_t creationMode; // Set the mode in the vattr structure. creationMode = getModeFromJournalEntryAuths(&entP->OwnerAuthority, &entP->GroupAuthority, &entP->PublicAuthority); if (0 == memcmp(entP->ObjectType, "*STMF ", sizeof(entP->ObjectType))) { rc = QlgCreat(newObjNameP, creationMode); if (rc == -1) { return -1; } // Close it. Creat opens the file. close(rc); } else if (0 == memcmp(entP->ObjectType, "*DIR ", sizeof(entP->ObjectType))) { rc = QlgMkdir(newObjNameP, creationMode); if (rc) { return -1; } } else if (0 == memcmp(entP->ObjectType, "*SYMLNK", sizeof(entP->ObjectType))) { // ContentsHeader is beginning of lg struct for contents. rc = QlgSymlink(&((Qp0l_Symlnk_Contents_t *) ((char *)entP + entP->SymlnkOffset))->ContentsHeader, newObjNameP); if (rc) { return -1; } } // // Set other attrs on new object here. So far, am only setting the // authorities. Should also set the pc/sys flags, but then would need // to code Qp0lSetAttr...only if time. // ALso, only do auths for non-symlnks. THere is no IFS external interface // to bypass trying to follow the link. if ((0 == memcmp(entP->ObjectType, "*DIR ", sizeof(entP->ObjectType))) || (0 == memcmp(entP->ObjectType, "*STMF ", sizeof(entP->ObjectType))) ) { rc = changeAuths(entP->OwnerAuthority, newObjNameP, entP->OwnerName); if (rc) { return -1; } rc = changeAuths(entP->GroupAuthority, newObjNameP, entP->GroupName); if (rc) { return -1; } rc = changeAuths(entP->PublicAuthority, newObjNameP, "*PUBLIC "); if (rc) { return -1; } } // // Start Journaling, if necessary. // // NOTE: We are skipping this since we aren't journaling the target tree. char srcPathBuf[MAX_PATH_LENGTH]; memset(srcPathBuf, 0, sizeof(srcPathBuf)); // Get the source's path in job CCSID, use get path from fileID. rc = getPathFromFileIDIn37(&entP->ObjectFID, srcPathBuf); if (rc) { return(rc); } // Get the FID for the new object. Only need the name again, since still CWD'd. unsigned int numBytesReturned; struct attrStruct { Qp0l_AttrTypes_List_t attrList; uint attrs[1]; } attrTypes; char attrBuf[100]; Qp0l_Attr_Header_t *attrHdrP = (Qp0l_Attr_Header_t *)attrBuf; unsigned int attrBufSizeNeeded; attrTypes.attrList.Number_Of_ReqAttrs = 1; attrTypes.attrs[0] = QP0L_ATTR_FILE_ID; //------------------------------------------------ // Get the source FID from constant source path. //------------------------------------------------ rc = Qp0lGetAttr((Qlg_Path_Name_T *) newObjNameP, (Qp0l_AttrTypes_List_t *) &attrTypes, (char *)attrHdrP, sizeof(attrBuf), &attrBufSizeNeeded, &numBytesReturned, QP0L_DONOT_FOLLOW_SYMLNK); if (rc) { return -1; } char tgtPathBuf[MAX_PATH_LENGTH]; memset(tgtPathBuf, 0, sizeof(tgtPathBuf)); // Get the source's path in job CCSID, use get path from fileID. rc = getPathFromFileIDIn37((Qp0lFID_t *)((char *)attrBuf + sizeof(Qp0l_Attr_Header_t)), tgtPathBuf); if (rc) { return(rc); } Qp0lFID_t tgtFID; // Add the new object to the FID Table FIDTblP->addEntry(entP->ObjectFID, ((char *)attrBuf + sizeof(Qp0l_Attr_Header_t)), srcPathBuf, tgtPathBuf); chdir("/"); return 0; } int processB4(Qjo_RJNE0100_JE_Hdr_t *entHdrP) { // Access the Entry Specific Data structure for this entry type. Qjo_RJNE0100_JE_ESD_t *esdP = (Qjo_RJNE0100_JE_ESD_t *) (((char *)entHdrP) + entHdrP->Dsp_Entry_Specific_Data); Qp0l_B4_Journal_Entry_t *entP = (Qp0l_B4_Journal_Entry_t *) &esdP->ESD; Qp0l_Object_Name_t *nameP = (Qp0l_Object_Name_t *) (entP->LinkOffset + (char *)entP); // Build the path to the directory that caused this entry. // We will later append the new object's name to this path. char path[MAX_PATH_LENGTH]; int rc = FIDTblP->getTgtPath(path, *(Qp0lFID_t *)&entHdrP->Object); if (rc != 0) { return(-1); } // Dir is already in job CCSID. Instead of messing with conversion, // particularly because we keep the entries in the FIDTable in job // CCSID, but the names in ESD's will be in UNICODE, // let's change the CWD of the job to the parent. No other threads // are running in this replay job anyways. rc = chdir(path); if (rc != 0) { return(-1); } // Since we simply changed to CWD, we can use the name directly as // a relative path on a Qlg interface. // Build us a Qlg_Path_Name_t. char dltObj[MAX_PATH_LENGTH]; Qlg_Path_Name_T *dltObjNameP = (Qlg_Path_Name_T *)dltObj; getLGfromName(nameP, dltObjNameP); if ((0 == memcmp(entP->ObjectType, "*SYMLNK", sizeof(entP->ObjectType))) || (0 == memcmp(entP->ObjectType, "*STMF ", sizeof(entP->ObjectType))) ) { // Use unlink if (-1 == QlgUnlink(dltObjNameP)) { return -1; } } else if (0 == memcmp(entP->ObjectType, "*DIR ", sizeof(entP->ObjectType))) { // Use rmdir if (-1 == QlgRmdir(dltObjNameP)) { return -1; } } // Remove the new object to the FID Table FIDTblP->rmvEntry(entP->ObjectFID); chdir("/"); return 0; } int processTR(Qjo_RJNE0100_JE_Hdr_t *entHdrP) { int fd; int i; int rc; // Access the Entry Specific Data structure for this entry type. Qjo_RJNE0100_JE_ESD_t *esdP = (Qjo_RJNE0100_JE_ESD_t *) (((char *)entHdrP) + entHdrP->Dsp_Entry_Specific_Data); Qp0l_TR_Journal_Entry_t *entP = (Qp0l_TR_Journal_Entry_t *) &esdP->ESD; // Build the path to the directory that caused this entry. // We will later append the new object's name to this path. char path[MAX_PATH_LENGTH]; rc = FIDTblP->getTgtPath(path, *(Qp0lFID_t *)&entHdrP->Object); if (rc != 0) { return(-1); } if (-1 == (fd = open(path, O_WRONLY, 0, 0))) { return(-1); } if (-1 == (rc = ftruncate(fd,entP->NewSize))) { return(-1); } if (-1 == close(fd)) { return(-1); } return 0; } int processWA(Qjo_RJNE0100_JE_Hdr_t *entHdrP) { int fd; int i; int rc; ssize_t bytes_written; // Access the Entry Specific Data structure for this entry type. Qjo_RJNE0100_JE_ESD_t *esdP = (Qjo_RJNE0100_JE_ESD_t *) (((char *)entHdrP) + entHdrP->Dsp_Entry_Specific_Data); Qp0l_WA_Journal_Entry_t *entP = (Qp0l_WA_Journal_Entry_t *) &esdP->ESD; // Build the path to the directory that caused this entry. // We will later append the new object's name to this path. char path[MAX_PATH_LENGTH]; rc = FIDTblP->getTgtPath(path, *(Qp0lFID_t *)&entHdrP->Object); if (rc != 0) { return(-1); } if (-1 == (fd = open(path, O_WRONLY, 0, 0))) { return(-1); } if (entHdrP->Incomplete_Data == '1') { if (-1 == (bytes_written = pwrite(fd, entP->WriteData.DataP, (size_t)entP->DataLength, (off_t)entP->Offset))) { return(-1); } } else { if (-1 == (bytes_written = pwrite(fd, entP->WriteData.Data, (size_t)entP->DataLength, (off_t)entP->Offset))) { return(-1); } } if (-1 == close(fd)) { return(-1); } return(0); } void getLGfromName(Qp0l_Object_Name_t *nameP, Qlg_Path_Name_T *newP) { memset(newP,0, sizeof(Qlg_Path_Name_T)); newP->CCSID = nameP->NLSinfo.ccsid; memcpy(newP->Country_ID,"US",2); memcpy(newP->Language_ID,"ENU",3); newP->Path_Type = QLG_CHAR_SINGLE; newP->Path_Length = nameP->Length; newP->Path_Name_Delimiter[0] = '/'; memcpy((char *)newP + sizeof(Qlg_Path_Name_T), nameP->Name, newP->Path_Length); } /********************************************************************/ /* Define a bunch of macros that help perform mapping for the data */ /* authorities contained within the IFS journal entries. See the */ /* getModeFromJournalEntryAuths function below for an example of */ /* use of these macros. */ /********************************************************************/ #define IFSAUTH_ISREAD(aut) /* Check for *R in aut mask */ \ ( ((aut) & (_AUTH_POINTER | _AUTH_SPACE | _AUTH_RETRIEVE)) == \ (_AUTH_POINTER | _AUTH_SPACE | _AUTH_RETRIEVE) ) #define IFSAUTH_ISWRITE(aut) /* Check for *W in aut mask */ \ ( ((aut) & (_AUTH_INSERT | \ _AUTH_DELETE | \ _AUTH_UPDATE | \ _AUTH_POINTER | \ _AUTH_SPACE)) == \ (_AUTH_INSERT | \ _AUTH_DELETE | \ _AUTH_UPDATE | \ _AUTH_POINTER | \ _AUTH_SPACE) ) #define IFSAUTH_ISEXECUTE(aut) /* Check for *X in aut mask */ \ ( ((aut) & (_AUTH_POINTER | _AUTH_SPACE | _AUTH_EXECUTE)) == \ (_AUTH_POINTER | _AUTH_SPACE | _AUTH_EXECUTE) ) #define IFSAUTH_URMODE(aut) \ ( (IFSAUTH_ISREAD(aut)) ? /* If *R ? */ \ S_IRUSR : /* then user r-bit */ \ 0x0000 ) /* else, bitmask 0 */ #define IFSAUTH_UWMODE(aut) \ ( (IFSAUTH_ISWRITE(aut)) ? /* If *W ? */ \ S_IWUSR : /* then user w-bit */ \ 0x0000 ) /* else, bitmask 0 */ #define IFSAUTH_UXMODE(aut) \ ( (IFSAUTH_ISEXECUTE(aut)) ? /* If *X ? */ \ S_IXUSR : /* then user x-bit */ \ 0x0000 ) /* else, bitmask 0 */ #define IFSAUTH_GRMODE(aut) \ ( (IFSAUTH_ISREAD(aut)) ? /* If *R ? */ \ S_IRGRP : /* then user r-bit */ \ 0x0000 ) /* else, bitmask 0 */ #define IFSAUTH_GWMODE(aut) \ ( (IFSAUTH_ISWRITE(aut)) ? /* If *W ? */ \ S_IWGRP : /* then user w-bit */ \ 0x0000 ) /* else, bitmask 0 */ #define IFSAUTH_GXMODE(aut) \ ( (IFSAUTH_ISEXECUTE(aut)) ? /* If *X ? */ \ S_IXGRP : /* then user x-bit */ \ 0x0000 ) /* else, bitmask 0 */ #define IFSAUTH_ORMODE(aut) \ ( (IFSAUTH_ISREAD(aut)) ? /* If *R ? */ \ S_IROTH : /* then user r-bit */ \ 0x0000 ) /* else, bitmask 0 */ #define IFSAUTH_OWMODE(aut) \ ( (IFSAUTH_ISWRITE(aut)) ? /* If *W ? */ \ S_IWOTH : /* then user w-bit */ \ 0x0000 ) /* else, bitmask 0 */ #define IFSAUTH_OXMODE(aut) \ ( (IFSAUTH_ISEXECUTE(aut)) ? /* If *X ? */ \ S_IXOTH : /* then user x-bit */ \ 0x0000 ) /* else, bitmask 0 */ /*** END OF SPECIFICATIONS ***************************************/ /* */ /* Function Name : getModeFromJournalEntryAuths */ /* */ /* Descriptive Name : Get a permissions mode from a journal */ /* entry authority structure. */ /* */ /* Function Description : Get a permissions mode from a journal */ /* entry authority structure. This will */ /* be created by first extracting the data */ /* authorities from the structure and */ /* setting the appropriate bits in a security*/ /* authority bitmask. Then we will convert */ /* the bitmask for each user (owner, group, */ /* and public) into the mode_t type. */ /* */ /* Prototype Location : None. Local to this module. */ /* */ /* Dependencies : None. */ /* */ /* Restrictions : This function should only be called */ /* from a function in Qp0fApyJChg.C. */ /* */ /* Exception Handlers : None. */ /* */ /* Diagnostic Messages : None */ /* */ /* Escape Messages : None */ /* */ /* Input : */ /* 1) Qp0l_Journal_Entry_Auth_t * */ /* Pointer to the owner's authorities as */ /* specified in a journal entry authority */ /* structure. */ /* */ /* 2) Qp0l_Journal_Entry_Auth_t * */ /* Pointer to the group's authorities as */ /* specified in a journal entry authority */ /* structure. */ /* */ /* 3) Qp0l_Journal_Entry_Auth_t * */ /* Pointer to the public's authorities as */ /* specified in a journal entry authority */ /* structure. */ /* */ /* Exit Normal */ /* Return Value : The mode. */ /* Outputs : None. */ /* */ /* Exit Error */ /* Return Value : None. */ /* Outputs : Unexpected exception. Caller should */ /* consider it an APAR condition. */ /* */ /*** END OF SPECIFICATIONS ***************************************/ mode_t getModeFromJournalEntryAuths(Qp0l_Journal_Entry_Auth_t *ownerP, Qp0l_Journal_Entry_Auth_t *groupP, Qp0l_Journal_Entry_Auth_t *publicP) { int i; /* Loop control. */ _REQ_AUTH authBits[3]; /* Owner, group, and public authority bitmasks. */ mode_t authModeBits; /* Mode format of authorities. */ Qp0l_Journal_Entry_Auth_t *authP[3]; /* Owner, group, and public authority bitmasks. */ /* Clear each authority bitmask. */ authBits[0] = 0; authBits[1] = 0; authBits[2] = 0; /* Set array elements to input parameters. */ authP[0] = ownerP; authP[1] = groupP; authP[2] = publicP; /* Set the data authorities for each user. */ for (i = 0; i < 3; ++i) { if (authP[i]->Objopr == 'Y') { authBits[i] |= _AUTH_POINTER | _AUTH_SPACE; } if (authP[i]->Read == 'Y') { authBits[i] |= _AUTH_RETRIEVE; } if (authP[i]->Add == 'Y') { authBits[i] |= _AUTH_INSERT; } if (authP[i]->Upd == 'Y') { authBits[i] |= _AUTH_UPDATE; } if (authP[i]->Dlt == 'Y') { authBits[i] |= _AUTH_DELETE; } if (authP[i]->Execute == 'Y') { authBits[i] |= _AUTH_EXECUTE; } if (authP[i]->Exclude == 'Y') { authBits[i] |= _AUTH_EXCLUDED; } } authModeBits = IFSAUTH_URMODE(authBits[0]) | /* Returns user read mode bit. */ IFSAUTH_UWMODE(authBits[0]) | /* Returns user write mode bit. */ IFSAUTH_UXMODE(authBits[0]) | /* Returns user execute mode bit. */ IFSAUTH_GRMODE(authBits[1]) | /* Returns group read mode bit. */ IFSAUTH_GWMODE(authBits[1]) | /* Returns group write mode bit. */ IFSAUTH_GXMODE(authBits[1]) | /* Returns group execute mode bit.*/ IFSAUTH_ORMODE(authBits[2]) | /* Returns other read mode bit. */ IFSAUTH_OWMODE(authBits[2]) | /* Returns other write mode bit. */ IFSAUTH_OXMODE(authBits[2]); /* Returns other execute mode bit.*/ /* Return the mode based on the authority bit masks. */ return(authModeBits); } int changeAuths(Qp0l_Journal_Entry_Auth_t &auths, Qlg_Path_Name_T *pathP, char *userName) { // return this as a no-op for now...need to add conversion of name to getLGname return 0; char cmdString[MAX_PATH_LENGTH + 100]; // Buffer used for building command strings. // // Data auths // char dataAuths[300]; memset(dataAuths,0,sizeof(dataAuths)); if (auths.Read == 'Y' || auths.Add == 'Y' || auths.Execute == 'Y') { // at least one. strcat(dataAuths, "*"); } if (auths.Read == 'Y') { strcat(dataAuths, "R"); } if (auths.Add == 'Y') // assume write if at least add. IFS not granular on write { strcat(dataAuths, "W"); } if (auths.Execute == 'Y') { strcat(dataAuths, "X"); } // // Object auths // char objAuths[300]; memset(objAuths,0,sizeof(objAuths)); if (auths.Objexist == 'Y') { strcat(objAuths, "*OBJEXIST"); } if (auths.Objmgt == 'Y') { strcat(objAuths, "*OBJMGT"); } if (auths.Objalter == 'Y') { strcat(objAuths, "*OBJALTER"); } if (auths.Objref == 'Y') { strcat(objAuths, "*OBJREF"); } // OBJOPR always for IFS unless exclude. ignore for demo. char userNameNull[11]; memcpy(userNameNull, userName, 10); userNameNull[10] = 0; // AUTL name left off explicitly. //// // Need to convert the name (pathP) here from an LG to a // job CCSID path. //// sprintf(cmdString, "CHGAUT OBJ('%s') USER(%s) DTAAUT(%s) \ OBJAUT(%s)", pathP, userNameNull, dataAuths, objAuths); if (system(cmdString) != 0) { return(-1); } return 0; } int getPathFromFileIDIn37(Qp0lFID_t *fid, char *pathBuf) { typedef struct pnstruct { Qlg_Path_Name_T qlg_struct; char pn[1024]; /* This size must be large enough */ /* to contain the path name. */ }; struct pnstruct path; memset((void*)&path, 0x00, sizeof(struct pnstruct)); if (QlgGetPathFromFileID((Qlg_Path_Name_T *)&path, sizeof(struct pnstruct), *fid) == NULL) { return -1; } #define PATH_TYPE_POINTER 0x00000001 /* If flag is on, */ /* input structure contains a pointer */ /* to the path name, else the path */ /* name is in contiguous storage */ /* within the qlg structure. */ typedef union pn_input_type /* Format of input path name. */ { char pn_char_type[256]; /* in contiguous storage */ char *pn_ptr_type; /* a pointer */ }; typedef struct pnstruct2 { Qlg_Path_Name_T qlg_struct; union pn_input_type pn; }; struct pnstruct2 *pns; char *path_ptr; size_t insz; size_t outsz = 1000; char outbuf[1000]; char *outbuf_ptr; iconv_t cd; size_t ret_iconv; /* Indicates to convert from ccsid 13488 to 37. */ QtqCode_T toCode = {37,0,0,0,0,0}; QtqCode_T fromCode = {path.qlg_struct.CCSID,0,0,1,0,0}; /***********************************************************/ /* Point to and get the size of the path name. */ /***********************************************************/ pns = (struct pnstruct2 *)&path; if (pns->qlg_struct.Path_Type & PATH_TYPE_POINTER) path_ptr = pns->pn.pn_ptr_type; else path_ptr = (char *)(pns->pn.pn_char_type); insz = pns->qlg_struct.Path_Length; /* Get path length.*/ /***********************************************************/ /* Initialize the print buffer. */ /***********************************************************/ outbuf_ptr = (char *)pathBuf; memset(outbuf_ptr, 0x00, insz); /***********************************************************/ /* Use iconv to convert the CCSID. */ /***********************************************************/ cd = QtqIconvOpen(&toCode, &fromCode); /* Open a descriptor*/ if (cd.return_value == -1) { return -1; } if (0 != ((iconv(cd, (char **)&(path_ptr), &insz, (char **)&(pathBuf), &outsz)))) { ret_iconv= iconv_close(cd);/* Close conversion descriptor*/ return -1; } /***********************************************************/ /* Print the name and close the conversion descriptior. */ /***********************************************************/ ret_iconv = iconv_close(cd); return 0; }