revised patch
>From 35a59f31cd0897e5ea66ebac5271598cfe97f22a Mon Sep 17 00:00:00 2001
From: Yi Zhang <[email protected]>
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
[email protected]
https://www.redhat.com/mailman/listinfo/fedora-directory-devel