>From 35a59f31cd0897e5ea66ebac5271598cfe97f22a Mon Sep 17 00:00:00 2001 From: Yi Zhang 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 : 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