summaryrefslogtreecommitdiffstats
path: root/ldap/servers/slapd/tools
diff options
context:
space:
mode:
authorYi Zhang <yzhang@redhat.com>2009-11-02 15:09:40 -0800
committerNathan Kinder <nkinder@redhat.com>2009-11-02 20:05:16 -0800
commit1484974a30910c927f1ee17b52443186fffc3df0 (patch)
tree637a8ad8ea1dcfc872fa786bdf6ca1666b64975c /ldap/servers/slapd/tools
parent027e8a4fbd4761a5c7ae4a9cc82befe4741e2dd5 (diff)
downloadds-1484974a30910c927f1ee17b52443186fffc3df0.tar.gz
ds-1484974a30910c927f1ee17b52443186fffc3df0.tar.xz
ds-1484974a30910c927f1ee17b52443186fffc3df0.zip
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.
Diffstat (limited to 'ldap/servers/slapd/tools')
-rw-r--r--ldap/servers/slapd/tools/ldclt/ldapfct.c240
-rw-r--r--ldap/servers/slapd/tools/ldclt/ldclt.c100
-rw-r--r--ldap/servers/slapd/tools/ldclt/ldclt.h8
-rw-r--r--ldap/servers/slapd/tools/ldclt/ldcltU.c1
-rw-r--r--ldap/servers/slapd/tools/ldclt/threadMain.c25
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 74b1812b..c067f26a 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 753b2148..05774c05 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 ee774f58..09e35b1e 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 b002310f..7540c5f4 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 32df9b70..46b1b631 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)
{