root/source4/lib/ldb/common/ldb_ldif.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ldb_read_data_file
  2. ldb_base64_decode
  3. ldb_base64_encode
  4. ldb_should_b64_encode
  5. fold_string
  6. base64_encode_f
  7. ldb_ldif_write
  8. next_chunk
  9. next_attr
  10. ldb_ldif_read_free
  11. ldb_ldif_read
  12. fgetc_file
  13. ldb_ldif_read_file
  14. fgetc_string
  15. ldb_ldif_read_string
  16. fprintf_file
  17. ldb_ldif_write_file

   1 /* 
   2    ldb database library
   3 
   4    Copyright (C) Andrew Tridgell  2004
   5 
   6      ** NOTE! The following LGPL license applies to the ldb
   7      ** library. This does NOT imply that all of Samba is released
   8      ** under the LGPL
   9    
  10    This library is free software; you can redistribute it and/or
  11    modify it under the terms of the GNU Lesser General Public
  12    License as published by the Free Software Foundation; either
  13    version 3 of the License, or (at your option) any later version.
  14 
  15    This library is distributed in the hope that it will be useful,
  16    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18    Lesser General Public License for more details.
  19 
  20    You should have received a copy of the GNU Lesser General Public
  21    License along with this library; if not, see <http://www.gnu.org/licenses/>.
  22 */
  23 
  24 /*
  25  *  Name: ldb
  26  *
  27  *  Component: ldif routines
  28  *
  29  *  Description: ldif pack/unpack routines
  30  *
  31  *  Author: Andrew Tridgell
  32  */
  33 
  34 /*
  35   see RFC2849 for the LDIF format definition
  36 */
  37 
  38 #include "ldb_private.h"
  39 #include "system/locale.h"
  40 
  41 /*
  42   
  43 */
  44 static int ldb_read_data_file(void *mem_ctx, struct ldb_val *value)
     /* [<][>][^][v][top][bottom][index][help] */
  45 {
  46         struct stat statbuf;
  47         char *buf;
  48         int count, size, bytes;
  49         int ret;
  50         int f;
  51         const char *fname = (const char *)value->data;
  52 
  53         if (strncmp(fname, "file://", 7) != 0) {
  54                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
  55         }
  56         fname += 7;
  57 
  58         f = open(fname, O_RDONLY);
  59         if (f == -1) {
  60                 return -1;
  61         }
  62 
  63         if (fstat(f, &statbuf) != 0) {
  64                 ret = -1;
  65                 goto done;
  66         }
  67 
  68         if (statbuf.st_size == 0) {
  69                 ret = -1;
  70                 goto done;
  71         }
  72 
  73         value->data = (uint8_t *)talloc_size(mem_ctx, statbuf.st_size + 1);
  74         if (value->data == NULL) {
  75                 ret = -1;
  76                 goto done;
  77         }
  78         value->data[statbuf.st_size] = 0;
  79 
  80         count = 0;
  81         size = statbuf.st_size;
  82         buf = (char *)value->data;
  83         while (count < statbuf.st_size) {
  84                 bytes = read(f, buf, size);
  85                 if (bytes == -1) {
  86                         talloc_free(value->data);
  87                         ret = -1;
  88                         goto done;
  89                 }
  90                 count += bytes;
  91                 buf += bytes;
  92                 size -= bytes;
  93         }
  94 
  95         value->length = statbuf.st_size;
  96         ret = statbuf.st_size;
  97 
  98 done:
  99         close(f);
 100         return ret;
 101 }
 102 
 103 /*
 104   this base64 decoder was taken from jitterbug (written by tridge).
 105   we might need to replace it with a new version
 106 */
 107 int ldb_base64_decode(char *s)
     /* [<][>][^][v][top][bottom][index][help] */
 108 {
 109         const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 110         int bit_offset=0, byte_offset, idx, i, n;
 111         uint8_t *d = (uint8_t *)s;
 112         char *p=NULL;
 113 
 114         n=i=0;
 115 
 116         while (*s && (p=strchr(b64,*s))) {
 117                 idx = (int)(p - b64);
 118                 byte_offset = (i*6)/8;
 119                 bit_offset = (i*6)%8;
 120                 d[byte_offset] &= ~((1<<(8-bit_offset))-1);
 121                 if (bit_offset < 3) {
 122                         d[byte_offset] |= (idx << (2-bit_offset));
 123                         n = byte_offset+1;
 124                 } else {
 125                         d[byte_offset] |= (idx >> (bit_offset-2));
 126                         d[byte_offset+1] = 0;
 127                         d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
 128                         n = byte_offset+2;
 129                 }
 130                 s++; i++;
 131         }
 132         if (bit_offset >= 3) {
 133                 n--;
 134         }
 135 
 136         if (*s && !p) {
 137                 /* the only termination allowed */
 138                 if (*s != '=') {
 139                         return -1;
 140                 }
 141         }
 142 
 143         /* null terminate */
 144         d[n] = 0;
 145         return n;
 146 }
 147 
 148 
 149 /*
 150   encode as base64
 151   caller frees
 152 */
 153 char *ldb_base64_encode(void *mem_ctx, const char *buf, int len)
     /* [<][>][^][v][top][bottom][index][help] */
 154 {
 155         const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 156         int bit_offset, byte_offset, idx, i;
 157         const uint8_t *d = (const uint8_t *)buf;
 158         int bytes = (len*8 + 5)/6, pad_bytes = (bytes % 4) ? 4 - (bytes % 4) : 0;
 159         char *out;
 160 
 161         out = talloc_array(mem_ctx, char, bytes+pad_bytes+1);
 162         if (!out) return NULL;
 163 
 164         for (i=0;i<bytes;i++) {
 165                 byte_offset = (i*6)/8;
 166                 bit_offset = (i*6)%8;
 167                 if (bit_offset < 3) {
 168                         idx = (d[byte_offset] >> (2-bit_offset)) & 0x3F;
 169                 } else {
 170                         idx = (d[byte_offset] << (bit_offset-2)) & 0x3F;
 171                         if (byte_offset+1 < len) {
 172                                 idx |= (d[byte_offset+1] >> (8-(bit_offset-2)));
 173                         }
 174                 }
 175                 out[i] = b64[idx];
 176         }
 177 
 178         for (;i<bytes+pad_bytes;i++)
 179                 out[i] = '=';
 180         out[i] = 0;
 181 
 182         return out;
 183 }
 184 
 185 /*
 186   see if a buffer should be base64 encoded
 187 */
 188 int ldb_should_b64_encode(const struct ldb_val *val)
     /* [<][>][^][v][top][bottom][index][help] */
 189 {
 190         unsigned int i;
 191         uint8_t *p = val->data;
 192 
 193         if (val->length == 0) {
 194                 return 0;
 195         }
 196 
 197         if (p[0] == ' ' || p[0] == ':') {
 198                 return 1;
 199         }
 200 
 201         for (i=0; i<val->length; i++) {
 202                 if (!isprint(p[i]) || p[i] == '\n') {
 203                         return 1;
 204                 }
 205         }
 206         return 0;
 207 }
 208 
 209 /* this macro is used to handle the return checking on fprintf_fn() */
 210 #define CHECK_RET do { if (ret < 0) return ret; total += ret; } while (0)
 211 
 212 /*
 213   write a line folded string onto a file
 214 */
 215 static int fold_string(int (*fprintf_fn)(void *, const char *, ...), void *private_data,
     /* [<][>][^][v][top][bottom][index][help] */
 216                         const char *buf, size_t length, int start_pos)
 217 {
 218         unsigned int i;
 219         int total=0, ret;
 220 
 221         for (i=0;i<length;i++) {
 222                 ret = fprintf_fn(private_data, "%c", buf[i]);
 223                 CHECK_RET;
 224                 if (i != (length-1) && (i + start_pos) % 77 == 0) {
 225                         ret = fprintf_fn(private_data, "\n ");
 226                         CHECK_RET;
 227                 }
 228         }
 229 
 230         return total;
 231 }
 232 
 233 #undef CHECK_RET
 234 
 235 /*
 236   encode as base64 to a file
 237 */
 238 static int base64_encode_f(struct ldb_context *ldb,
     /* [<][>][^][v][top][bottom][index][help] */
 239                            int (*fprintf_fn)(void *, const char *, ...), 
 240                            void *private_data,
 241                            const char *buf, int len, int start_pos)
 242 {
 243         char *b = ldb_base64_encode(ldb, buf, len);
 244         int ret;
 245 
 246         if (!b) {
 247                 return -1;
 248         }
 249 
 250         ret = fold_string(fprintf_fn, private_data, b, strlen(b), start_pos);
 251 
 252         talloc_free(b);
 253         return ret;
 254 }
 255 
 256 
 257 static const struct {
 258         const char *name;
 259         enum ldb_changetype changetype;
 260 } ldb_changetypes[] = {
 261         {"add",    LDB_CHANGETYPE_ADD},
 262         {"delete", LDB_CHANGETYPE_DELETE},
 263         {"modify", LDB_CHANGETYPE_MODIFY},
 264         {NULL, 0}
 265 };
 266 
 267 /* this macro is used to handle the return checking on fprintf_fn() */
 268 #define CHECK_RET do { if (ret < 0) { talloc_free(mem_ctx); return ret; } total += ret; } while (0)
 269 
 270 /*
 271   write to ldif, using a caller supplied write method
 272 */
 273 int ldb_ldif_write(struct ldb_context *ldb,
     /* [<][>][^][v][top][bottom][index][help] */
 274                    int (*fprintf_fn)(void *, const char *, ...), 
 275                    void *private_data,
 276                    const struct ldb_ldif *ldif)
 277 {
 278         TALLOC_CTX *mem_ctx;
 279         unsigned int i, j;
 280         int total=0, ret;
 281         char *p;
 282         const struct ldb_message *msg;
 283 
 284         mem_ctx = talloc_named_const(NULL, 0, "ldb_ldif_write");
 285 
 286         msg = ldif->msg;
 287         p = ldb_dn_get_extended_linearized(mem_ctx, msg->dn, 1);
 288         ret = fprintf_fn(private_data, "dn: %s\n", p);
 289         talloc_free(p);
 290         CHECK_RET;
 291 
 292         if (ldif->changetype != LDB_CHANGETYPE_NONE) {
 293                 for (i=0;ldb_changetypes[i].name;i++) {
 294                         if (ldb_changetypes[i].changetype == ldif->changetype) {
 295                                 break;
 296                         }
 297                 }
 298                 if (!ldb_changetypes[i].name) {
 299                         ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: Invalid ldif changetype %d\n",
 300                                   ldif->changetype);
 301                         talloc_free(mem_ctx);
 302                         return -1;
 303                 }
 304                 ret = fprintf_fn(private_data, "changetype: %s\n", ldb_changetypes[i].name);
 305                 CHECK_RET;
 306         }
 307 
 308         for (i=0;i<msg->num_elements;i++) {
 309                 const struct ldb_schema_attribute *a;
 310 
 311                 a = ldb_schema_attribute_by_name(ldb, msg->elements[i].name);
 312 
 313                 if (ldif->changetype == LDB_CHANGETYPE_MODIFY) {
 314                         switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
 315                         case LDB_FLAG_MOD_ADD:
 316                                 fprintf_fn(private_data, "add: %s\n", 
 317                                            msg->elements[i].name);
 318                                 break;
 319                         case LDB_FLAG_MOD_DELETE:
 320                                 fprintf_fn(private_data, "delete: %s\n", 
 321                                            msg->elements[i].name);
 322                                 break;
 323                         case LDB_FLAG_MOD_REPLACE:
 324                                 fprintf_fn(private_data, "replace: %s\n", 
 325                                            msg->elements[i].name);
 326                                 break;
 327                         }
 328                 }
 329 
 330                 for (j=0;j<msg->elements[i].num_values;j++) {
 331                         struct ldb_val v;
 332                         ret = a->syntax->ldif_write_fn(ldb, mem_ctx, &msg->elements[i].values[j], &v);
 333                         if (ret != LDB_SUCCESS) {
 334                                 v = msg->elements[i].values[j];
 335                         }
 336                         if (ret != LDB_SUCCESS || ldb_should_b64_encode(&v)) {
 337                                 ret = fprintf_fn(private_data, "%s:: ", 
 338                                                  msg->elements[i].name);
 339                                 CHECK_RET;
 340                                 ret = base64_encode_f(ldb, fprintf_fn, private_data, 
 341                                                       (char *)v.data, v.length,
 342                                                       strlen(msg->elements[i].name)+3);
 343                                 CHECK_RET;
 344                                 ret = fprintf_fn(private_data, "\n");
 345                                 CHECK_RET;
 346                         } else {
 347                                 ret = fprintf_fn(private_data, "%s: ", msg->elements[i].name);
 348                                 CHECK_RET;
 349                                 ret = fold_string(fprintf_fn, private_data,
 350                                                   (char *)v.data, v.length,
 351                                                   strlen(msg->elements[i].name)+2);
 352                                 CHECK_RET;
 353                                 ret = fprintf_fn(private_data, "\n");
 354                                 CHECK_RET;
 355                         }
 356                         if (v.data != msg->elements[i].values[j].data) {
 357                                 talloc_free(v.data);
 358                         }
 359                 }
 360                 if (ldif->changetype == LDB_CHANGETYPE_MODIFY) {
 361                         fprintf_fn(private_data, "-\n");
 362                 }
 363         }
 364         ret = fprintf_fn(private_data,"\n");
 365         CHECK_RET;
 366 
 367         return total;
 368 }
 369 
 370 #undef CHECK_RET
 371 
 372 
 373 /*
 374   pull a ldif chunk, which is defined as a piece of data ending in \n\n or EOF
 375   this routine removes any RFC2849 continuations and comments
 376 
 377   caller frees
 378 */
 379 static char *next_chunk(struct ldb_context *ldb, 
     /* [<][>][^][v][top][bottom][index][help] */
 380                         int (*fgetc_fn)(void *), void *private_data)
 381 {
 382         size_t alloc_size=0, chunk_size = 0;
 383         char *chunk = NULL;
 384         int c;
 385         int in_comment = 0;
 386 
 387         while ((c = fgetc_fn(private_data)) != EOF) {
 388                 if (chunk_size+1 >= alloc_size) {
 389                         char *c2;
 390                         alloc_size += 1024;
 391                         c2 = talloc_realloc(ldb, chunk, char, alloc_size);
 392                         if (!c2) {
 393                                 talloc_free(chunk);
 394                                 errno = ENOMEM;
 395                                 return NULL;
 396                         }
 397                         chunk = c2;
 398                 }
 399 
 400                 if (in_comment) {
 401                         if (c == '\n') {
 402                                 in_comment = 0;
 403                         }
 404                         continue;                       
 405                 }
 406                 
 407                 /* handle continuation lines - see RFC2849 */
 408                 if (c == ' ' && chunk_size > 1 && chunk[chunk_size-1] == '\n') {
 409                         chunk_size--;
 410                         continue;
 411                 }
 412                 
 413                 /* chunks are terminated by a double line-feed */
 414                 if (c == '\n' && chunk_size > 0 && chunk[chunk_size-1] == '\n') {
 415                         chunk[chunk_size-1] = 0;
 416                         return chunk;
 417                 }
 418 
 419                 if (c == '#' && (chunk_size == 0 || chunk[chunk_size-1] == '\n')) {
 420                         in_comment = 1;
 421                         continue;
 422                 }
 423 
 424                 /* ignore leading blank lines */
 425                 if (chunk_size == 0 && c == '\n') {
 426                         continue;
 427                 }
 428 
 429                 chunk[chunk_size++] = c;
 430         }
 431 
 432         if (chunk) {
 433                 chunk[chunk_size] = 0;
 434         }
 435 
 436         return chunk;
 437 }
 438 
 439 
 440 /* simple ldif attribute parser */
 441 static int next_attr(void *mem_ctx, char **s, const char **attr, struct ldb_val *value)
     /* [<][>][^][v][top][bottom][index][help] */
 442 {
 443         char *p;
 444         int base64_encoded = 0;
 445         int binary_file = 0;
 446 
 447         if (strncmp(*s, "-\n", 2) == 0) {
 448                 value->length = 0;
 449                 *attr = "-";
 450                 *s += 2;
 451                 return 0;
 452         }
 453 
 454         p = strchr(*s, ':');
 455         if (!p) {
 456                 return -1;
 457         }
 458 
 459         *p++ = 0;
 460 
 461         if (*p == ':') {
 462                 base64_encoded = 1;
 463                 p++;
 464         }
 465 
 466         if (*p == '<') {
 467                 binary_file = 1;
 468                 p++;
 469         }
 470 
 471         *attr = *s;
 472 
 473         while (*p == ' ' || *p == '\t') {
 474                 p++;
 475         }
 476 
 477         value->data = (uint8_t *)p;
 478 
 479         p = strchr(p, '\n');
 480 
 481         if (!p) {
 482                 value->length = strlen((char *)value->data);
 483                 *s = ((char *)value->data) + value->length;
 484         } else {
 485                 value->length = p - (char *)value->data;
 486                 *s = p+1;
 487                 *p = 0;
 488         }
 489 
 490         if (base64_encoded) {
 491                 int len = ldb_base64_decode((char *)value->data);
 492                 if (len == -1) {
 493                         /* it wasn't valid base64 data */
 494                         return -1;
 495                 }
 496                 value->length = len;
 497         }
 498 
 499         if (binary_file) {
 500                 int len = ldb_read_data_file(mem_ctx, value);
 501                 if (len == -1) {
 502                         /* an error occured hile trying to retrieve the file */
 503                         return -1;
 504                 }
 505         }
 506 
 507         return 0;
 508 }
 509 
 510 
 511 /*
 512   free a message from a ldif_read
 513 */
 514 void ldb_ldif_read_free(struct ldb_context *ldb, struct ldb_ldif *ldif)
     /* [<][>][^][v][top][bottom][index][help] */
 515 {
 516         talloc_free(ldif);
 517 }
 518 
 519 /*
 520  read from a LDIF source, creating a ldb_message
 521 */
 522 struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb,
     /* [<][>][^][v][top][bottom][index][help] */
 523                                int (*fgetc_fn)(void *), void *private_data)
 524 {
 525         struct ldb_ldif *ldif;
 526         struct ldb_message *msg;
 527         const char *attr=NULL;
 528         char *chunk=NULL, *s;
 529         struct ldb_val value;
 530         unsigned flags = 0;
 531 
 532         value.data = NULL;
 533 
 534         ldif = talloc(ldb, struct ldb_ldif);
 535         if (!ldif) return NULL;
 536 
 537         ldif->msg = talloc(ldif, struct ldb_message);
 538         if (ldif->msg == NULL) {
 539                 talloc_free(ldif);
 540                 return NULL;
 541         }
 542 
 543         ldif->changetype = LDB_CHANGETYPE_NONE;
 544         msg = ldif->msg;
 545 
 546         msg->dn = NULL;
 547         msg->elements = NULL;
 548         msg->num_elements = 0;
 549 
 550         chunk = next_chunk(ldb, fgetc_fn, private_data);
 551         if (!chunk) {
 552                 goto failed;
 553         }
 554         talloc_steal(ldif, chunk);
 555 
 556         s = chunk;
 557 
 558         if (next_attr(ldif, &s, &attr, &value) != 0) {
 559                 goto failed;
 560         }
 561         
 562         /* first line must be a dn */
 563         if (ldb_attr_cmp(attr, "dn") != 0) {
 564                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: First line of ldif must be a dn not '%s'\n", 
 565                           attr);
 566                 goto failed;
 567         }
 568 
 569         msg->dn = ldb_dn_from_ldb_val(msg, ldb, &value);
 570 
 571         if ( ! ldb_dn_validate(msg->dn)) {
 572                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: Unable to parse dn '%s'\n", 
 573                           (char *)value.data);
 574                 goto failed;
 575         }
 576 
 577         while (next_attr(ldif, &s, &attr, &value) == 0) {
 578                 const struct ldb_schema_attribute *a;
 579                 struct ldb_message_element *el;
 580                 int ret, empty = 0;
 581 
 582                 if (ldb_attr_cmp(attr, "changetype") == 0) {
 583                         int i;
 584                         for (i=0;ldb_changetypes[i].name;i++) {
 585                                 if (ldb_attr_cmp((char *)value.data, ldb_changetypes[i].name) == 0) {
 586                                         ldif->changetype = ldb_changetypes[i].changetype;
 587                                         break;
 588                                 }
 589                         }
 590                         if (!ldb_changetypes[i].name) {
 591                                 ldb_debug(ldb, LDB_DEBUG_ERROR, 
 592                                           "Error: Bad ldif changetype '%s'\n",(char *)value.data);
 593                         }
 594                         flags = 0;
 595                         continue;
 596                 }
 597 
 598                 if (ldb_attr_cmp(attr, "add") == 0) {
 599                         flags = LDB_FLAG_MOD_ADD;
 600                         empty = 1;
 601                 }
 602                 if (ldb_attr_cmp(attr, "delete") == 0) {
 603                         flags = LDB_FLAG_MOD_DELETE;
 604                         empty = 1;
 605                 }
 606                 if (ldb_attr_cmp(attr, "replace") == 0) {
 607                         flags = LDB_FLAG_MOD_REPLACE;
 608                         empty = 1;
 609                 }
 610                 if (ldb_attr_cmp(attr, "-") == 0) {
 611                         flags = 0;
 612                         continue;
 613                 }
 614 
 615                 if (empty) {
 616                         if (ldb_msg_add_empty(msg, (char *)value.data, flags, NULL) != 0) {
 617                                 goto failed;
 618                         }
 619                         continue;
 620                 }
 621                 
 622                 el = &msg->elements[msg->num_elements-1];
 623 
 624                 a = ldb_schema_attribute_by_name(ldb, attr);
 625 
 626                 if (msg->num_elements > 0 && ldb_attr_cmp(attr, el->name) == 0 &&
 627                     flags == el->flags) {
 628                         /* its a continuation */
 629                         el->values = 
 630                                 talloc_realloc(msg->elements, el->values, 
 631                                                  struct ldb_val, el->num_values+1);
 632                         if (!el->values) {
 633                                 goto failed;
 634                         }
 635                         ret = a->syntax->ldif_read_fn(ldb, ldif, &value, &el->values[el->num_values]);
 636                         if (ret != 0) {
 637                                 goto failed;
 638                         }
 639                         if (value.length == 0) {
 640                                 ldb_debug(ldb, LDB_DEBUG_ERROR,
 641                                           "Error: Attribute value cannot be empty for attribute '%s'\n", el->name);
 642                                 goto failed;
 643                         }
 644                         if (value.data != el->values[el->num_values].data) {
 645                                 talloc_steal(el->values, el->values[el->num_values].data);
 646                         }
 647                         el->num_values++;
 648                 } else {
 649                         /* its a new attribute */
 650                         msg->elements = talloc_realloc(ldif, msg->elements, 
 651                                                          struct ldb_message_element, 
 652                                                          msg->num_elements+1);
 653                         if (!msg->elements) {
 654                                 goto failed;
 655                         }
 656                         el = &msg->elements[msg->num_elements];
 657                         el->flags = flags;
 658                         el->name = talloc_strdup(msg->elements, attr);
 659                         el->values = talloc(msg->elements, struct ldb_val);
 660                         if (!el->values || !el->name) {
 661                                 goto failed;
 662                         }
 663                         el->num_values = 1;
 664                         ret = a->syntax->ldif_read_fn(ldb, ldif, &value, &el->values[0]);
 665                         if (ret != 0) {
 666                                 goto failed;
 667                         }
 668                         if (value.data != el->values[0].data) {
 669                                 talloc_steal(el->values, el->values[0].data);
 670                         }
 671                         msg->num_elements++;
 672                 }
 673         }
 674 
 675         return ldif;
 676 
 677 failed:
 678         talloc_free(ldif);
 679         return NULL;
 680 }
 681 
 682 
 683 
 684 /*
 685   a wrapper around ldif_read() for reading from FILE*
 686 */
 687 struct ldif_read_file_state {
 688         FILE *f;
 689 };
 690 
 691 static int fgetc_file(void *private_data)
     /* [<][>][^][v][top][bottom][index][help] */
 692 {
 693         struct ldif_read_file_state *state =
 694                 (struct ldif_read_file_state *)private_data;
 695         return fgetc(state->f);
 696 }
 697 
 698 struct ldb_ldif *ldb_ldif_read_file(struct ldb_context *ldb, FILE *f)
     /* [<][>][^][v][top][bottom][index][help] */
 699 {
 700         struct ldif_read_file_state state;
 701         state.f = f;
 702         return ldb_ldif_read(ldb, fgetc_file, &state);
 703 }
 704 
 705 
 706 /*
 707   a wrapper around ldif_read() for reading from const char*
 708 */
 709 struct ldif_read_string_state {
 710         const char *s;
 711 };
 712 
 713 static int fgetc_string(void *private_data)
     /* [<][>][^][v][top][bottom][index][help] */
 714 {
 715         struct ldif_read_string_state *state =
 716                 (struct ldif_read_string_state *)private_data;
 717         if (state->s[0] != 0) {
 718                 return *state->s++;
 719         }
 720         return EOF;
 721 }
 722 
 723 struct ldb_ldif *ldb_ldif_read_string(struct ldb_context *ldb, const char **s)
     /* [<][>][^][v][top][bottom][index][help] */
 724 {
 725         struct ldif_read_string_state state;
 726         struct ldb_ldif *ldif;
 727         state.s = *s;
 728         ldif = ldb_ldif_read(ldb, fgetc_string, &state);
 729         *s = state.s;
 730         return ldif;
 731 }
 732 
 733 
 734 /*
 735   wrapper around ldif_write() for a file
 736 */
 737 struct ldif_write_file_state {
 738         FILE *f;
 739 };
 740 
 741 static int fprintf_file(void *private_data, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
     /* [<][>][^][v][top][bottom][index][help] */
 742 
 743 static int fprintf_file(void *private_data, const char *fmt, ...)
 744 {
 745         struct ldif_write_file_state *state =
 746                 (struct ldif_write_file_state *)private_data;
 747         int ret;
 748         va_list ap;
 749 
 750         va_start(ap, fmt);
 751         ret = vfprintf(state->f, fmt, ap);
 752         va_end(ap);
 753         return ret;
 754 }
 755 
 756 int ldb_ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif *ldif)
     /* [<][>][^][v][top][bottom][index][help] */
 757 {
 758         struct ldif_write_file_state state;
 759         state.f = f;
 760         return ldb_ldif_write(ldb, fprintf_file, &state, ldif);
 761 }

/* [<][>][^][v][top][bottom][index][help] */