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

Reply via email to