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

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