revised patch
>From 35a59f31cd0897e5ea66ebac5271598cfe97f22a Mon Sep 17 00:00:00 2001 From: Yi Zhang <yzhang@xxxxxxxxxx> Date: Mon, 2 Nov 2009 15:09:40 -0800 Subject: [PATCH] 459181 - Add attreplacefile option to ldclt This option will accept format like "-e attreplacefile=jpegPhoto:/some/binary.file" to ldclt. The content of the given file will be used to replace the attribute "jpegPhoto" (in this case). The given file could be plain text or binary file. --- ldap/servers/slapd/tools/ldclt/ldapfct.c | 240 +++++++++++++++++++++++++- ldap/servers/slapd/tools/ldclt/ldclt.c | 100 +++++++++++ ldap/servers/slapd/tools/ldclt/ldclt.h | 8 +- ldap/servers/slapd/tools/ldclt/ldcltU.c | 1 + ldap/servers/slapd/tools/ldclt/threadMain.c | 25 +++ 5 files changed, 362 insertions(+), 12 deletions(-) diff --git a/ldap/servers/slapd/tools/ldclt/ldapfct.c b/ldap/servers/slapd/tools/ldclt/ldapfct.c index 74b1812..c067f26 100644 --- a/ldap/servers/slapd/tools/ldclt/ldapfct.c +++ b/ldap/servers/slapd/tools/ldclt/ldapfct.c @@ -1349,18 +1349,22 @@ int freeAttrib ( LDAPMod **attrs) { - int i; - for (i=0 ; attrs[i]!=NULL ; i++) - { - if (attrs[i]->mod_op & LDAP_MOD_BVALUES) - { - free (attrs[i]->mod_bvalues[0]); + int i; + int j; + + for (i=0 ; attrs[i]!=NULL ; i++) { + if (attrs[i]->mod_op & LDAP_MOD_BVALUES) { + for (j=0; attrs[i]->mod_bvalues[j] != NULL; j++) { + free (attrs[i]->mod_bvalues[j]); + } free (attrs[i]->mod_bvalues); - } - else + } else { free (attrs[i]->mod_values); + } + free (attrs[i]); } + return (0); } @@ -1478,7 +1482,70 @@ printErrorFromLdap ( - /* New function */ /*JLS 21-11-00*/ + + + + +/* **************************************************************************** + FUNCTION : buildNewModAttribFile + PURPOSE : Build a new (random or incremental) target DN and the + corresponding LDAPMod for attribute modification. + INPUT : tttctx = thread context + OUTPUT : newDN = DN of the new entry + attrs = attributes for the ldap_modify + RETURN : -1 if error, 0 else. + *****************************************************************************/ +int +buildNewModAttribFile ( + thread_context *tttctx, + char *newDn, + LDAPMod **attrs) +{ + int nbAttribs; /* Nb of attributes */ + LDAPMod attribute; /* To build the attributes */ + struct berval *bv = malloc(sizeof(struct berval *)); + attribute.mod_bvalues = (struct berval **)malloc(2 * sizeof(struct berval *)); + + if ((bv == NULL) || (attribute.mod_bvalues == NULL)) { + return -1; + } + + /* + * Build the new DN + * We will assume that the filter (-f argument) is set to use it + * to build the rdn of the new entry. + * Note that the random new attribute is also build by this function. + */ + if (buildRandomRdnOrFilter (tttctx) < 0) + return (-1); + strcpy (newDn, tttctx->bufFilter); + strcat (newDn, ","); + strcat (newDn, tttctx->bufBaseDN); + + /* + * Build the attributes modification + */ + bv->bv_len = mctx.attrplFileSize; + bv->bv_val = mctx.attrplFileContent; + attrs[0] = NULL; /* No attributes yet */ + nbAttribs = 0; /* No attributes yet */ + attribute.mod_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES; + attribute.mod_type = mctx.attrplName; + attribute.mod_bvalues[0] = bv; + attribute.mod_bvalues[1] = NULL; + + if (addAttrib (attrs, nbAttribs++, &attribute) < 0) + return (-1); + + /* + * Normal end + */ + return (0); +} + + + +/* New function */ /*JLS 21-11-00*/ /* **************************************************************************** FUNCTION : buildNewModAttrib PURPOSE : Build a new (random or incremental) target DN and the @@ -3050,7 +3117,6 @@ doAddEntry ( - /* **************************************************************************** FUNCTION : doAttrReplace PURPOSE : Perform an ldap_modify() operation, to replace an @@ -3207,7 +3273,161 @@ doAttrReplace ( +/* **************************************************************************** + FUNCTION : doAttrFileReplace + PURPOSE : Perform an ldap_modify() operation, to replace an + attribute of the entry with content read from file . + INPUT : tttctx = thread context + OUTPUT : None. + RETURN : -1 if error, 0 else. + DESCRIPTION : + *****************************************************************************/ +int +doAttrFileReplace ( + thread_context *tttctx) +{ + char newDn[MAX_DN_LENGTH]; /* DN of the new entry */ + LDAPMod *attrs[MAX_ATTRIBS]; /* Attributes of this entry */ + int ret; /* Return values */ + int msgid; /* For asynchronous mode */ + + /* + * Connection to the server + * The function connectToServer() will take care of the various connection/ + * disconnection, bind/unbind/close etc... requested by the user. + * The cost is one more function call in this application, but the + * resulting source code will be much more easiest to maintain. + */ + if (connectToServer (tttctx) < 0) /* if connection is being established, */ + return (-1); /* then tttctx->ldapCtx would exist and holds connection */ + if (!(tttctx->binded)) + return (0); + + /* + * Do the modify + * Maybe we are in synchronous mode ? + */ + if (!(mctx.mode & ASYNC)) + { + /* + * Build the new entry + */ + if (buildNewModAttribFile (tttctx, newDn, attrs) < 0) + return (-1); + /* + * We will modify this entry + */ + ret = ldap_modify_ext_s (tttctx->ldapCtx, newDn, attrs, NULL, NULL); + if (ret != LDAP_SUCCESS) + { + if (!((mctx.mode & QUIET) && ignoreError (ret))) + { + printf ("ldclt[%d]: T%03d: AttriFileReplace Error Cannot modify (%s), error=%d (%s)\n", + mctx.pid, tttctx->thrdNum, newDn, ret, my_ldap_err2string (ret)); + fflush (stdout); + } + if (addErrorStat (ret) < 0) + return (-1); + } + else + { + printf ("ldclt[%d]: T%03d: AttriFileReplace modify (%s) success ,\n", + mctx.pid, tttctx->thrdNum, newDn); + if (incrementNbOpers (tttctx) < 0) /* Memorize operation */ + return (-1); + } + + /* + * Free the attributes + */ + if (freeAttrib (attrs) < 0) + return (-1); + + /* + * End of synchronous operations + */ + return (0); + } + + /* + * Here, we are in asynchronous mode... + * Too bad, lot of things to do here. + * First, let's see if we are above the reading threshold. + */ + if (getPending (tttctx, &(mctx.timeval)) < 0) + return (-1); + + /* + * Maybe we may send another request ? + * Well... there is no proper way to retrieve the error number for + * this, so I guess I may use direct access to the ldap context + * to read the field ld_errno. + */ + if (tttctx->pendingNb > mctx.asyncMax) + { + if ((mctx.mode & VERBOSE) && + (tttctx->asyncHit == 1) && + (!(mctx.mode & SUPER_QUIET))) + { + tttctx->asyncHit = 1; + printf ("ldclt[%d]: T%03d: Max pending request hit.\n", + mctx.pid, tttctx->thrdNum); + fflush (stdout); + } + } + else + { + if ((mctx.mode & VERBOSE) && + (tttctx->asyncHit == 1) && + (!(mctx.mode & SUPER_QUIET))) + { + tttctx->asyncHit = 0; + printf ("ldclt[%d]: T%03d: Restart sending.\n", + mctx.pid, tttctx->thrdNum); + fflush (stdout); + } + + /* + * Build the new entry + */ + if (buildNewModAttrib (tttctx, newDn, attrs) < 0) + return (-1); + + ret = ldap_modify_ext (tttctx->ldapCtx, newDn, attrs, NULL, NULL, &msgid); + if (ret != LDAP_SUCCESS) + { + if (!((mctx.mode & QUIET) && ignoreError (ret))) + { + printf ("ldclt[%d]: T%03d: Cannot modify(%s), error=%d (%s)\n", + mctx.pid, tttctx->thrdNum, newDn, ret, my_ldap_err2string (ret)); + fflush (stdout); + } + if (addErrorStat (ret) < 0) + return (-1); + } + else + { + /* + * Memorize the operation + */ + if (msgIdAdd (tttctx, msgid, newDn, newDn, attrs) < 0) + return (-1); + if (incrementNbOpers (tttctx) < 0) + return (-1); + tttctx->pendingNb++; + } + } + + if (mctx.mode & VERY_VERBOSE) + printf ("ldclt[%d]: T%03d: pendingNb=%d\n", + mctx.pid, tttctx->thrdNum, tttctx->pendingNb); + + /* + * End of asynchronous operation... and also end of function. + */ + return (0); +} /* **************************************************************************** diff --git a/ldap/servers/slapd/tools/ldclt/ldclt.c b/ldap/servers/slapd/tools/ldclt/ldclt.c index 753b214..05774c0 100644 --- a/ldap/servers/slapd/tools/ldclt/ldclt.c +++ b/ldap/servers/slapd/tools/ldclt/ldclt.c @@ -1267,6 +1267,10 @@ basicInit (void) int i; /* For the loops */ /*JLS 21-11-00*/ int ret; /* Return value */ int oflags;/* open() flags */ /*JLS 05-04-01*/ + struct stat file_st ; /* file status checker for attreplacefile option */ + FILE *attrF; /* file pointer for attreplacefile option */ + int buffersize=1024; /* buffer size for buffer */ + char buffer[buffersize]; /* buffer used to read attreplacefile content */ /* * Misc inits @@ -1471,6 +1475,86 @@ basicInit (void) } /*JLS 21-11-00*/ } /*JLS 21-11-00*/ + /* + * Parse attreplacefile subvalue + */ + if (mctx.mod2 & M2_ATTR_REPLACE_FILE) + { + printf ("debug: parse attreplacefile subvalue\n"); + /* + * Find the attribute name + */ + for (i=0 ; (i<strlen(mctx.attrpl)) && + (mctx.attrpl[i]!=':') ; i++); + mctx.attrplName = (char *)malloc(i+1); + strncpy (mctx.attrplName, mctx.attrpl, i); + mctx.attrplName[i] = '\0'; + + /* + * Parse the attribute value + */ + mctx.attrplFile = (char *)malloc(strlen(mctx.attrpl+i+1) + 1); + if (mctx.attrplFile == NULL) { + printf ("Error: unable to allocate memory for attreplfile\n"); + return (-1); + } + + strncpy(mctx.attrplFile, mctx.attrpl+i+1, strlen(mctx.attrpl+i+1)); + mctx.attrplFile[strlen(mctx.attrpl+i+1)] = '\0'; + + /* + * start working on file verification here + (1) check whether file exist + (2) check whether we have permission to read it + (3) save the content into mctx.attrplFileContent + */ + + /* determine file size here */ + if (stat(mctx.attrplFile, &file_st) < 0){ + printf ("attr replace file [%s] does not exist, exit\n", mctx.attrplFile); + return (-1); + }else{ + mctx.attrplFileSize = file_st.st_size; + printf ("file has size [%d] bytes\n", mctx.attrplFileSize ); + } + + /* open file to read */ + if ((attrF = fopen(mctx.attrplFile, "r")) == NULL ) + { + printf("ERROR reading attr file [%s]\n",mctx.attrplFile); + return (-1); + }else{ + printf("file opened for reading\n"); + } + + /* start to read file content */ + mctx.attrplFileContent = (char *)malloc(mctx.attrplFileSize + 1); + i=0; + while ( fread(buffer, buffersize , 1, attrF) ) + { + memcpy(mctx.attrplFileContent+i, buffer , buffersize ); + memset(buffer ,'\0', buffersize ); + i = i + buffersize; + } + /* copy remainding content into mctx.attrplFileContent */ + if (i<mctx.attrplFileSize) + { + memcpy(mctx.attrplFileContent+i, buffer , (mctx.attrplFileSize - 1 - i)); + memset(buffer ,'\0', buffersize ); /* clear the buffer */ + } + + mctx.attrplFileContent[mctx.attrplFileSize]='\0'; // append the close bit + + if ((fclose(attrF)) == EOF ) + { + printf("ERROR closing attr file [%s]\n",mctx.attrplFile); + return (-1); + }else{ + printf("file closed\n"); + } + + } + /* * Initiates statistics fields @@ -2123,6 +2207,8 @@ char *execParams[] = { "abandon", #define EP_DEREF 50 "deref", +#define EP_ATT_REPLACE_FILE 51 + "attreplacefile", NULL }; @@ -2165,6 +2251,15 @@ decodeExecParams ( } /*JLS 21-11-00*/ mctx.attrpl = strdup (subvalue); /*JLS 21-11-00*/ break; /*JLS 21-11-00*/ + case EP_ATT_REPLACE_FILE: + mctx.mod2 |= M2_ATTR_REPLACE_FILE; + if (subvalue == NULL) + { + fprintf (stderr, "Error: missing arg attreplacefile\n"); + return (-1); + } + mctx.attrpl = strdup (subvalue); + break; case EP_ATTRLIST: /*JLS 15-03-01*/ return (addAttrToList (subvalue)); /*JLS 15-03-01*/ break; /*JLS 15-03-01*/ @@ -3094,6 +3189,11 @@ main ( printf ("Attribute's head = \"%s\"\n", mctx.attrplHead);/*JLS 21-11-00*/ printf ("Attribute's tail = \"%s\"\n", mctx.attrplTail);/*JLS 21-11-00*/ } /*JLS 21-11-00*/ + if (mctx.mod2 & M2_ATTR_REPLACE_FILE) + { + printf ("Attribute to replace = \"%s\"\n", mctx.attrplName); + printf ("Attribute value file = \"%s\"\n", mctx.attrplFile); + } if (mctx.mode & ASYNC) { printf ("Async max pending = %d\n", mctx.asyncMax); diff --git a/ldap/servers/slapd/tools/ldclt/ldclt.h b/ldap/servers/slapd/tools/ldclt/ldclt.h index ee774f5..09e35b1 100644 --- a/ldap/servers/slapd/tools/ldclt/ldclt.h +++ b/ldap/servers/slapd/tools/ldclt/ldclt.h @@ -279,6 +279,7 @@ dd/mm/yy | Author | Comments #define M2_RANDOM_SASLAUTHID 0x00000080 /* -e randomauthid */ #define M2_ABANDON 0x00000100 /* -e abandon */ #define M2_DEREF 0x00000200 /* -e deref */ +#define M2_ATTR_REPLACE_FILE 0x00000400 /* -e attreplacefile */ /* * Combinatory defines @@ -288,11 +289,11 @@ dd/mm/yy | Author | Comments * - VALID_OPERS : valid operations */ #define NEED_FILTER (ADD_ENTRIES|DELETE_ENTRIES|EXACT_SEARCH|RENAME_ENTRIES|ATTR_REPLACE|SCALAB01) -#define M2_NEED_FILTER (M2_ABANDON) +#define M2_NEED_FILTER (M2_ABANDON|M2_ATTR_REPLACE_FILE) #define NEED_RANGE (INCREMENTAL|RANDOM) #define NEED_RND_INCR (ADD_ENTRIES|DELETE_ENTRIES|RENAME_ENTRIES) #define VALID_OPERS (ADD_ENTRIES|DELETE_ENTRIES|EXACT_SEARCH|RENAME_ENTRIES|ATTR_REPLACE|SCALAB01) -#define M2_VALID_OPERS (M2_GENLDIF|M2_BINDONLY|M2_ABANDON) +#define M2_VALID_OPERS (M2_GENLDIF|M2_BINDONLY|M2_ABANDON|M2_ATTR_REPLACE_FILE) #define NEED_CLASSES (ADD_ENTRIES) #define THE_CLASSES (OC_PERSON|OC_EMAILPERSON|OC_INETORGPRSON) @@ -506,6 +507,9 @@ typedef struct main_context { char *attrlist[MAX_ATTRIBS]; /*JLS 15-03-01*/ int attrlistNb; /* Nb attrib in list */ /*JLS 15-03-01*/ char *attrpl; /* Attrib argument */ /*JLS 21-11-00*/ + char *attrplFile; /* Attrib file to get value from */ + char *attrplFileContent; /* Attrib file content */ + int attrplFileSize; /* Attrib file size*/ char *attrplHead; /* Attrib value head */ /*JLS 21-11-00*/ char *attrplName; /* Attrib name */ /*JLS 21-11-00*/ int attrplNbDigit; /* Attrib nb digits */ /*JLS 21-11-00*/ diff --git a/ldap/servers/slapd/tools/ldclt/ldcltU.c b/ldap/servers/slapd/tools/ldclt/ldcltU.c index b002310..7540c5f 100644 --- a/ldap/servers/slapd/tools/ldclt/ldcltU.c +++ b/ldap/servers/slapd/tools/ldclt/ldcltU.c @@ -163,6 +163,7 @@ void usage () (void) printf (" add : ldap_add() entries.\n"); (void) printf (" append : append entries to the genldif file.\n"); (void) printf (" ascii : ascii 7-bits strings.\n"); + (void) printf (" attreplacefile=attrname:<file name> : replace attribute with given file content.\n"); (void) printf (" attreplace=name:mask : replace attribute of existing entry.\n"); (void) printf (" attrlist=name:name:name : specify list of attribs to retrieve\n"); (void) printf (" attrsonly=0|1 : ldap_search() parameter. Set 0 to read values.\n"); diff --git a/ldap/servers/slapd/tools/ldclt/threadMain.c b/ldap/servers/slapd/tools/ldclt/threadMain.c index 32df9b7..46b1b63 100644 --- a/ldap/servers/slapd/tools/ldclt/threadMain.c +++ b/ldap/servers/slapd/tools/ldclt/threadMain.c @@ -1114,6 +1114,23 @@ threadMain ( mctx.attrplTail); } + + /* + * Initiates the attribute replace buffers attrplName + */ + if ( mctx.mod2 & M2_ATTR_REPLACE_FILE ) + { + /* bufAttrpl should point to the same memory location that mctx.attrplFileContent points to */ + tttctx->bufAttrpl = mctx.attrplFileContent; + if (tttctx->bufAttrpl == NULL) + { + printf ("ldclt[%d]: T%03d: cannot malloc(tttctx->bufAttrpl), error=%d (%s), can we read file [%s]\n", + mctx.pid, tttctx->thrdNum, errno, strerror (errno), mctx.attrplFile); + ldcltExit (EXIT_INIT); /*JLS 18-12-00*/ + } + } + + /* * We are ready to go ! */ @@ -1154,6 +1171,14 @@ threadMain ( go = 0; /*JLS 21-11-00*/ continue; /*JLS 21-11-00*/ } /*JLS 21-11-00*/ + + if (mctx.mod2 & M2_ATTR_REPLACE_FILE ) + if (doAttrFileReplace (tttctx) < 0) + { + go = 0; + continue; + } + if (tttctx->mode & DELETE_ENTRIES) if (doDeleteEntry (tttctx) < 0) { -- 1.6.2.5
-- 389-devel mailing list 389-devel@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/fedora-directory-devel