diff options
author | Andrew Tridgell <tridge@samba.org> | 2004-04-10 20:18:22 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:51:11 -0500 |
commit | ac193579e7db00c7a2ea0aadaaf0d34c10dcf1a5 (patch) | |
tree | bcd9a0afdc2996df4a56479932b7d36d32c50f8d /source4/lib | |
parent | 91b30df39bfaec8bfa32be40a13fd62008f66b9e (diff) | |
download | samba-ac193579e7db00c7a2ea0aadaaf0d34c10dcf1a5.tar.gz samba-ac193579e7db00c7a2ea0aadaaf0d34c10dcf1a5.tar.bz2 samba-ac193579e7db00c7a2ea0aadaaf0d34c10dcf1a5.zip |
r152: a quick airport commit ....
added ldbedit, a _really_ useful command
added ldbadd, ldbdel, ldbsearch and ldbmodify to build
solved lots of timezone issues, we now pass the torture tests with
client and server in different zones
fixed several build issues
I know this breaks the no-LDAP build. Wait till I arrive in San Jose for that
fix.
(This used to be commit af34710d4da1841653624fe304b1c8d812c0fdd9)
Diffstat (limited to 'source4/lib')
-rw-r--r-- | source4/lib/ldb/Makefile.ldb | 8 | ||||
-rw-r--r-- | source4/lib/ldb/common/ldb.c | 2 | ||||
-rw-r--r-- | source4/lib/ldb/common/ldb_ldif.c | 22 | ||||
-rw-r--r-- | source4/lib/ldb/common/ldb_msg.c | 133 | ||||
-rw-r--r-- | source4/lib/ldb/common/util.c | 6 | ||||
-rw-r--r-- | source4/lib/ldb/config.m4 | 46 | ||||
-rw-r--r-- | source4/lib/ldb/include/includes.h | 3 | ||||
-rw-r--r-- | source4/lib/ldb/include/ldb.h | 2 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_ldap/ldb_ldap.c | 5 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_tdb/ldb_pack.c | 2 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_tdb/ldb_search.c | 36 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_tdb/ldb_tdb.c | 2 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_tdb/ldb_tdb.h | 4 | ||||
-rw-r--r-- | source4/lib/ldb/tools/ldbadd.c | 99 | ||||
-rw-r--r-- | source4/lib/ldb/tools/ldbdel.c | 41 | ||||
-rw-r--r-- | source4/lib/ldb/tools/ldbedit.c | 365 | ||||
-rw-r--r-- | source4/lib/ldb/tools/ldbmodify.c | 100 | ||||
-rw-r--r-- | source4/lib/ldb/tools/ldbsearch.c | 32 | ||||
-rw-r--r-- | source4/lib/replace.c | 2 | ||||
-rw-r--r-- | source4/lib/time.c | 593 |
20 files changed, 927 insertions, 576 deletions
diff --git a/source4/lib/ldb/Makefile.ldb b/source4/lib/ldb/Makefile.ldb index 0610ccf19b..2a41629852 100644 --- a/source4/lib/ldb/Makefile.ldb +++ b/source4/lib/ldb/Makefile.ldb @@ -12,13 +12,14 @@ LDB_TDB_OBJ=ldb_tdb/ldb_match.o ldb_tdb/ldb_tdb.o \ LDB_LDAP_OBJ=ldb_ldap/ldb_ldap.o -COMMON_OBJ=common/ldb.o common/ldb_ldif.o common/util.o common/ldb_parse.o +COMMON_OBJ=common/ldb.o common/ldb_ldif.o common/util.o \ + common/ldb_parse.o common/ldb_msg.o OBJS = $(COMMON_OBJ) $(LDB_TDB_OBJ) $(TDB_OBJ) $(LDB_LDAP_OBJ) LDB_LIB = lib/libldb.a -BINS = bin/ldbadd bin/ldbsearch bin/ldbdel bin/ldbmodify +BINS = bin/ldbadd bin/ldbsearch bin/ldbdel bin/ldbmodify bin/ldbedit LIBS = $(LDB_LIB)($(OBJS)) @@ -46,6 +47,9 @@ bin/ldbdel: tools/ldbdel.o $(LIBS) bin/ldbmodify: tools/ldbmodify.o $(LIBS) $(CC) -o bin/ldbmodify tools/ldbmodify.o $(LIB_FLAGS) +bin/ldbedit: tools/ldbedit.o $(LIBS) + $(CC) -o bin/ldbedit tools/ldbedit.o $(LIB_FLAGS) + clean: rm -f */*.o *~ */*~ $(BINS) $(LDB_LIB) diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 3ba4434e07..146745043f 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -80,7 +80,7 @@ int ldb_search(struct ldb_context *ldb, const char *base, enum ldb_scope scope, const char *expression, - const char *attrs[], struct ldb_message ***res) + char * const attrs[], struct ldb_message ***res) { return ldb->ops->search(ldb, base, scope, expression, attrs, res); } diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c index b4c27c3369..5f2fccfebc 100644 --- a/source4/lib/ldb/common/ldb_ldif.c +++ b/source4/lib/ldb/common/ldb_ldif.c @@ -90,7 +90,7 @@ char *ldb_base64_encode(const char *buf, int len) { const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; int bit_offset, byte_offset, idx, i; - unsigned char *d = (unsigned char *)buf; + const unsigned char *d = (const unsigned char *)buf; int bytes = (len*8 + 5)/6; char *out; @@ -222,6 +222,23 @@ int ldif_write(int (*fprintf_fn)(void *, const char *, ...), } for (i=0;i<msg->num_elements;i++) { + if (ldif->changetype == LDB_CHANGETYPE_MODIFY) { + switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) { + case LDB_FLAG_MOD_ADD: + fprintf_fn(private, "add: %s\n", + msg->elements[i].name); + break; + case LDB_FLAG_MOD_DELETE: + fprintf_fn(private, "delete: %s\n", + msg->elements[i].name); + break; + case LDB_FLAG_MOD_REPLACE: + fprintf_fn(private, "replace: %s\n", + msg->elements[i].name); + break; + } + } + for (j=0;j<msg->elements[i].num_values;j++) { if (ldb_should_b64_encode(&msg->elements[i].values[j])) { ret = fprintf_fn(private, "%s:: ", @@ -246,6 +263,9 @@ int ldif_write(int (*fprintf_fn)(void *, const char *, ...), CHECK_RET; } } + if (ldif->changetype == LDB_CHANGETYPE_MODIFY) { + fprintf_fn(private, "-\n"); + } } ret = fprintf_fn(private,"\n"); CHECK_RET; diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c new file mode 100644 index 0000000000..633cc91f2c --- /dev/null +++ b/source4/lib/ldb/common/ldb_msg.c @@ -0,0 +1,133 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb message component utility functions + * + * Description: functions for manipulating ldb_message structures + * + * Author: Andrew Tridgell + */ + +#include "includes.h" + + +/* + find an element in a message by attribute name +*/ +struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg, + const char *attr_name) +{ + int i; + for (i=0;i<msg->num_elements;i++) { + if (strcmp(msg->elements[i].name, attr_name) == 0) { + return &msg->elements[i]; + } + } + return NULL; +} + + +/* + find a value in an element +*/ +struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el, + struct ldb_val *val) +{ + int i; + for (i=0;i<el->num_values;i++) { + if (ldb_val_equal(val, &el->values[i])) { + return &el->values[i]; + } + } + return NULL; +} + + +/* + add an empty element to a message +*/ +int ldb_msg_add_empty(struct ldb_message *msg, const char *attr_name, int flags) +{ + struct ldb_message_element *els; + + els = realloc_p(msg->elements, struct ldb_message_element, msg->num_elements+1); + if (!els) { + errno = ENOMEM; + return -1; + } + + els[msg->num_elements].values = NULL; + els[msg->num_elements].num_values = 0; + els[msg->num_elements].flags = flags; + els[msg->num_elements].name = strdup(attr_name); + if (!els[msg->num_elements].name) { + return -1; + } + + msg->elements = els; + msg->num_elements++; + + return 0; +} + +/* + add an empty element to a message +*/ +int ldb_msg_add(struct ldb_message *msg, + const struct ldb_message_element *el, + int flags) +{ + if (ldb_msg_add_empty(msg, el->name, flags) != 0) { + return -1; + } + + msg->elements[msg->num_elements-1] = *el; + msg->elements[msg->num_elements-1].flags = flags; + + return 0; +} + +/* + compare two ldb_message_element structures +*/ +int ldb_msg_element_compare(struct ldb_message_element *el1, + struct ldb_message_element *el2) +{ + int i; + + if (el1->num_values != el2->num_values) { + return el1->num_values - el2->num_values; + } + + for (i=0;i<el1->num_values;i++) { + if (!ldb_msg_find_val(el2, &el1->values[i])) { + return -1; + } + } + + return 0; +} diff --git a/source4/lib/ldb/common/util.c b/source4/lib/ldb/common/util.c index d198a1ad92..e1a7ada1c6 100644 --- a/source4/lib/ldb/common/util.c +++ b/source4/lib/ldb/common/util.c @@ -77,11 +77,11 @@ int list_find(const void *needle, int r; test_i = (min_i + max_i) / 2; - r = comp_fn(needle, *(void **)(base_p + (size * test_i))); + r = comp_fn(needle, *(void * const *)(base_p + (size * test_i))); if (r == 0) { /* scan back for first element */ while (test_t > 0 && - comp_fn(needle, *(void **)(base_p + (size * (test_i-1)))) == 0) { + comp_fn(needle, *(void * const *)(base_p + (size * (test_i-1)))) == 0) { test_i--; } return test_i; @@ -94,7 +94,7 @@ int list_find(const void *needle, } } - if (comp_fn(needle, *(void **)(base_p + (size * min_i))) == 0) { + if (comp_fn(needle, *(void * const *)(base_p + (size * min_i))) == 0) { return min_i; } diff --git a/source4/lib/ldb/config.m4 b/source4/lib/ldb/config.m4 index 6fdfcf526a..7c4749ab02 100644 --- a/source4/lib/ldb/config.m4 +++ b/source4/lib/ldb/config.m4 @@ -1,17 +1,37 @@ - -SMB_MODULE(libldb_tdb,LIBLDB,STATIC, - [lib/ldb/ldb_tdb/ldb_tdb.o \ - lib/ldb/ldb_tdb/ldb_pack.o \ +SMB_SUBSYSTEM(LIBLDB,[lib/ldb/common/ldb.o], + [lib/ldb/common/ldb_ldif.o \ + lib/ldb/common/ldb_parse.o \ + lib/ldb/common/ldb_msg.o \ + lib/ldb/common/util.o \ lib/ldb/ldb_tdb/ldb_search.o \ + lib/ldb/ldb_tdb/ldb_tdb.o \ + lib/ldb/ldb_tdb/ldb_pack.o \ lib/ldb/ldb_tdb/ldb_index.o \ - lib/ldb/ldb_tdb/ldb_match.o]) + lib/ldb/ldb_tdb/ldb_match.o \ + lib/ldb/ldb_ldap/ldb_ldap.o], + lib/ldb/include/ldb.h) -if test x"$with_ldap_support" = x"yes"; then - SMB_MODULE_DEFAULT(libldb_ldap,STATIC) -fi -SMB_MODULE(libldb_ldap,LIBLDB,NOT,[lib/ldb/ldb_ldap/ldb_ldap.o]) +SMB_SUBSYSTEM(LDBADD,[], + [lib/ldb/tools/ldbadd.o \ + \$(LIBBASIC_OBJS) \$(LIBSMB_OBJS) \$(CONFIG_OBJS) \$(LIBLDB_OBJS)], + lib/ldb/include/proto.h) -SMB_SUBSYSTEM(LIBLDB,[lib/ldb/common/ldb.o], - [lib/ldb/common/ldb_ldif.o \ - lib/ldb/common/ldb_parse.o \ - lib/ldb/common/util.o]) +SMB_SUBSYSTEM(LDBDEL,[], + [lib/ldb/tools/ldbdel.o \ + \$(LIBBASIC_OBJS) \$(LIBSMB_OBJS) \$(CONFIG_OBJS) \$(LIBLDB_OBJS)], + lib/ldb/include/proto.h) + +SMB_SUBSYSTEM(LDBMODIFY,[], + [lib/ldb/tools/ldbmodify.o \ + \$(LIBBASIC_OBJS) \$(LIBSMB_OBJS) \$(CONFIG_OBJS) \$(LIBLDB_OBJS)], + lib/ldb/include/proto.h) + +SMB_SUBSYSTEM(LDBSEARCH,[], + [lib/ldb/tools/ldbsearch.o \ + \$(LIBBASIC_OBJS) \$(LIBSMB_OBJS) \$(CONFIG_OBJS) \$(LIBLDB_OBJS)], + lib/ldb/include/proto.h) + +SMB_SUBSYSTEM(LDBEDIT,[], + [lib/ldb/tools/ldbedit.o \ + \$(LIBBASIC_OBJS) \$(LIBSMB_OBJS) \$(CONFIG_OBJS) \$(LIBLDB_OBJS)], + lib/ldb/include/proto.h) diff --git a/source4/lib/ldb/include/includes.h b/source4/lib/ldb/include/includes.h index ea8540d330..70ad1f3588 100644 --- a/source4/lib/ldb/include/includes.h +++ b/source4/lib/ldb/include/includes.h @@ -2,7 +2,9 @@ a temporary includes file until I work on the ldb build system */ +#ifndef _GNU_SOURCE #define _GNU_SOURCE +#endif #include <stdio.h> #include <string.h> #include <stdlib.h> @@ -11,6 +13,7 @@ #include <fcntl.h> #include <stdarg.h> #include <signal.h> +#include <unistd.h> #include "ldb.h" #include "ldb_parse.h" diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 12064bbf75..dc1b1d7732 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -174,7 +174,7 @@ int ldb_search(struct ldb_context *ldb, const char *base, enum ldb_scope scope, const char *expression, - const char *attrs[], struct ldb_message ***res); + char * const attrs[], struct ldb_message ***res); /* free a set of messages returned by ldb_search diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index 25dad914da..25af43c569 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -33,8 +33,7 @@ */ #include "includes.h" -#if HAVE_LDAP -#include "ldb_ldap.h" +#include "ldb/ldb_ldap/ldb_ldap.h" #if 0 /* @@ -519,4 +518,4 @@ failed: if (ldb) free(ldb); return NULL; } -#endif /*HAVE_LDAP*/ + diff --git a/source4/lib/ldb/ldb_tdb/ldb_pack.c b/source4/lib/ldb/ldb_tdb/ldb_pack.c index 5964e0751d..1196e561a2 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_pack.c +++ b/source4/lib/ldb/ldb_tdb/ldb_pack.c @@ -33,7 +33,7 @@ */ #include "includes.h" -#include "ldb_tdb.h" +#include "ldb/ldb_tdb/ldb_tdb.h" /* change this if the data format ever changes */ #define LTDB_PACKING_FORMAT 0x26011966 diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 5905231b32..9cb5853c94 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -33,7 +33,7 @@ */ #include "includes.h" -#include "ldb_tdb.h" +#include "ldb/ldb_tdb/ldb_tdb.h" /* free a message that has all parts separately allocated @@ -56,22 +56,6 @@ static void msg_free_all_parts(struct ldb_message *msg) /* - TODO: this should take advantage of the sorted nature of the message - - return index of the attribute, or -1 if not found -*/ -int ldb_msg_find_attr(const struct ldb_message *msg, const char *attr) -{ - int i; - for (i=0;i<msg->num_elements;i++) { - if (strcmp(msg->elements[i].name, attr) == 0) { - return i; - } - } - return -1; -} - -/* duplicate a ldb_val structure */ struct ldb_val ldb_val_dup(const struct ldb_val *v) @@ -193,7 +177,7 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_context *ldb, } for (i=0;attrs[i];i++) { - int j; + struct ldb_message_element *el; if (strcmp(attrs[i], "*") == 0) { if (msg_add_all_elements(ret, msg) != 0) { @@ -202,17 +186,15 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_context *ldb, } continue; } - j = ldb_msg_find_attr(msg, attrs[i]); - if (j == -1) { + + el = ldb_msg_find_element(msg, attrs[i]); + if (!el) { continue; } - do { - if (msg_add_element(ret, &msg->elements[j]) != 0) { - msg_free_all_parts(ret); - return NULL; - } - } while (++j < msg->num_elements && - strcmp(attrs[i], msg->elements[j].name) == 0); + if (msg_add_element(ret, el) != 0) { + msg_free_all_parts(ret); + return NULL; + } } return ret; diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index ec90eec03f..b28d73cbea 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -33,7 +33,7 @@ */ #include "includes.h" -#include "ldb_tdb.h" +#include "ldb/ldb_tdb/ldb_tdb.h" /* form a TDB_DATA for a record key diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index 30afe223ea..efb0af1c9c 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -5,7 +5,9 @@ struct ltdb_private { unsigned int connect_flags; }; -#ifdef STANDALONE +#ifndef IVAL #define IVAL(p, ofs) (((unsigned *)((char *)(p) + (ofs)))[0]) +#endif +#ifndef SIVAL #define SIVAL(p, ofs, v) do { IVAL(p, ofs) = (v); } while (0) #endif diff --git a/source4/lib/ldb/tools/ldbadd.c b/source4/lib/ldb/tools/ldbadd.c index 92ed29e6b8..446c0d80f9 100644 --- a/source4/lib/ldb/tools/ldbadd.c +++ b/source4/lib/ldb/tools/ldbadd.c @@ -34,28 +34,28 @@ #include "includes.h" - int main(void) -{ - static struct ldb_context *ldb; - struct ldb_ldif *ldif; - int ret; - int count=0, failures=0; - const char *ldb_url; - - ldb_url = getenv("LDB_URL"); - if (!ldb_url) { - ldb_url = "tdb://test.ldb"; - } +static int failures; - ldb = ldb_connect(ldb_url, 0, NULL); +static void usage(void) +{ + printf("Usage: ldbadd <options> <ldif...>\n"); + printf("Options:\n"); + printf(" -H ldb_url choose the database (or $LDB_URL)\n"); + printf("\n"); + printf("Adds records to a ldb, reading ldif the specified list of files\n\n"); + exit(1); +} - if (!ldb) { - perror("ldb_connect"); - exit(1); - } - while ((ldif = ldif_read_file(stdin))) { +/* + add records from an opened file +*/ +static int process_file(struct ldb_context *ldb, FILE *f) +{ + struct ldb_ldif *ldif; + int ret, count=0; + while ((ldif = ldif_read_file(f))) { if (ldif->changetype != LDB_CHANGETYPE_ADD && ldif->changetype != LDB_CHANGETYPE_NONE) { fprintf(stderr, "Only CHANGETYPE_ADD records allowed\n"); @@ -73,6 +73,69 @@ ldif_read_free(ldif); } + return count; +} + + + + int main(int argc, char * const argv[]) +{ + struct ldb_context *ldb; + int count=0; + const char *ldb_url; + int opt, i; + + ldb_url = getenv("LDB_URL"); + + while ((opt = getopt(argc, argv, "hH:")) != EOF) { + switch (opt) { + case 'H': + ldb_url = optarg; + break; + + case 'h': + default: + usage(); + break; + } + } + + if (!ldb_url) { + fprintf(stderr, "You must specify a ldb URL\n"); + exit(1); + } + + argc -= optind; + argv += optind; + + ldb = ldb_connect(ldb_url, 0, NULL); + + if (!ldb) { + perror("ldb_connect"); + exit(1); + } + + if (argc == 0) { + usage(); + } + + for (i=0;i<argc;i++) { + FILE *f; + if (strcmp(argv[i],"-") == 0) { + f = stdin; + } else { + f = fopen(argv[i], "r"); + } + if (!f) { + perror(argv[i]); + exit(1); + } + count += process_file(ldb, f); + if (f != stdin) { + fclose(f); + } + } + ldb_close(ldb); printf("Added %d records with %d failures\n", count, failures); diff --git a/source4/lib/ldb/tools/ldbdel.c b/source4/lib/ldb/tools/ldbdel.c index 177279d47a..0e50a68532 100644 --- a/source4/lib/ldb/tools/ldbdel.c +++ b/source4/lib/ldb/tools/ldbdel.c @@ -34,20 +34,48 @@ #include "includes.h" - int main(int argc, const char *argv[]) +static void usage(void) { - static struct ldb_context *ldb; + printf("Usage: ldbdel <options> <DN...>\n"); + printf("Options:\n"); + printf(" -H ldb_url choose the database (or $LDB_URL)\n"); + printf("\n"); + printf("Deletes records from a ldb\n\n"); + exit(1); +} + + int main(int argc, char * const argv[]) +{ + struct ldb_context *ldb; int ret, i; const char *ldb_url; + int opt; ldb_url = getenv("LDB_URL"); + + while ((opt = getopt(argc, argv, "hH:")) != EOF) { + switch (opt) { + case 'H': + ldb_url = optarg; + break; + + case 'h': + default: + usage(); + break; + } + } + if (!ldb_url) { - ldb_url = "tdb://test.ldb"; + fprintf(stderr, "You must specify a ldb URL\n"); + exit(1); } + argc -= optind; + argv += optind; - if (argc < 2) { - printf("Usage: ldbdel <dn...>\n"); + if (argc < 1) { + usage(); exit(1); } @@ -57,7 +85,7 @@ exit(1); } - for (i=1;i<argc;i++) { + for (i=0;i<argc;i++) { ret = ldb_delete(ldb, argv[i]); if (ret != 0) { printf("delete of '%s' failed\n", argv[i]); @@ -65,5 +93,6 @@ } ldb_close(ldb); + return 0; } diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c new file mode 100644 index 0000000000..c5eb1349dd --- /dev/null +++ b/source4/lib/ldb/tools/ldbedit.c @@ -0,0 +1,365 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldbedit + * + * Description: utility for ldb editing + * + * Author: Andrew Tridgell + */ + +#include "includes.h" + +/* + modify a database record so msg1 becomes msg2 +*/ +static int modify_record(struct ldb_context *ldb, + struct ldb_message *msg1, + struct ldb_message *msg2) +{ + struct ldb_message mod; + struct ldb_message_element *el; + int i; + + mod.dn = msg1->dn; + mod.num_elements = 0; + mod.elements = NULL; + + /* look in msg2 to find elements that need to be added + or modified */ + for (i=0;i<msg2->num_elements;i++) { + el = ldb_msg_find_element(msg1, msg2->elements[i].name); + + if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) { + continue; + } + + if (ldb_msg_add(&mod, + &msg2->elements[i], + el?LDB_FLAG_MOD_REPLACE:LDB_FLAG_MOD_ADD) != 0) { + return -1; + } + } + + /* look in msg1 to find elements that need to be deleted */ + for (i=0;i<msg1->num_elements;i++) { + el = ldb_msg_find_element(msg2, msg1->elements[i].name); + if (!el) { + if (ldb_msg_add_empty(&mod, + msg1->elements[i].name, + LDB_FLAG_MOD_DELETE) != 0) { + return -1; + } + } + } + + if (mod.num_elements == 0) { + return 0; + } + + if (ldb_modify(ldb, &mod) != 0) { + fprintf(stderr, "failed to modify %s\n", msg1->dn); + return -1; + } + + return 0; +} + +/* + find dn in msgs[] +*/ +static struct ldb_message *msg_find(struct ldb_message **msgs, int count, + const char *dn) +{ + int i; + for (i=0;i<count;i++) { + if (strcmp(dn, msgs[i]->dn) == 0) { + return msgs[i]; + } + } + return NULL; +} + +/* + merge the changes in msgs2 into the messages from msgs1 +*/ +static int merge_edits(struct ldb_context *ldb, + struct ldb_message **msgs1, int count1, + struct ldb_message **msgs2, int count2) +{ + int i; + struct ldb_message *msg; + int ret = 0; + + /* do the adds and modifies */ + for (i=0;i<count2;i++) { + msg = msg_find(msgs1, count1, msgs2[i]->dn); + if (!msg) { + if (ldb_add(ldb, msgs2[i]) != 0) { + fprintf(stderr, "failed to add %s\n", + msgs2[i]->dn); + return -1; + } + } else { + modify_record(ldb, msg, msgs2[i]); + } + } + + /* do the deletes */ + for (i=0;i<count1;i++) { + msg = msg_find(msgs2, count2, msgs1[i]->dn); + if (!msg) { + if (ldb_delete(ldb, msgs1[i]->dn) != 0) { + fprintf(stderr, "failed to delete %s\n", + msgs1[i]->dn); + return -1; + } + } + } + + return ret; +} + +/* + save a set of messages as ldif to a file +*/ +static int save_ldif(FILE *f, struct ldb_message **msgs, int count) +{ + int i; + + fprintf(f, "# returned %d records\n", count); + + for (i=0;i<count;i++) { + struct ldb_ldif ldif; + fprintf(f, "# record %d\n", i+1); + + ldif.changetype = LDB_CHANGETYPE_NONE; + ldif.msg = *msgs[i]; + + ldif_write_file(f, &ldif); + } + + return 0; +} + + +/* + edit the ldb search results in msgs using the user selected editor +*/ +static int do_edit(struct ldb_context *ldb, struct ldb_message **msgs1, int count1, + const char *editor) +{ + int fd, ret; + FILE *f; + char template[] = "/tmp/ldbedit.XXXXXX"; + char *cmd; + struct ldb_ldif *ldif; + struct ldb_message **msgs2 = NULL; + int count2 = 0; + + /* write out the original set of messages to a temporary + file */ + fd = mkstemp(template); + + if (fd == -1) { + perror(template); + return -1; + } + + f = fdopen(fd, "r+"); + + if (!f) { + perror("fopen"); + close(fd); + unlink(template); + return -1; + } + + if (save_ldif(f, msgs1, count1) != 0) { + return -1; + } + + fclose(f); + + asprintf(&cmd, "%s %s", editor, template); + + if (!cmd) { + unlink(template); + fprintf(stderr, "out of memory\n"); + return -1; + } + + /* run the editor */ + ret = system(cmd); + free(cmd); + + if (ret != 0) { + unlink(template); + fprintf(stderr, "edit with %s failed\n", editor); + return -1; + } + + /* read the resulting ldif into msgs2 */ + f = fopen(template, "r"); + if (!f) { + perror(template); + return -1; + } + + while ((ldif = ldif_read_file(f))) { + msgs2 = realloc_p(msgs2, struct ldb_message *, count2+1); + if (!msgs2) { + fprintf(stderr, "out of memory"); + return -1; + } + msgs2[count2++] = &ldif->msg; + } + + fclose(f); + unlink(template); + + return merge_edits(ldb, msgs1, count1, msgs2, count2); +} + +static void usage(void) +{ + printf("Usage: ldbedit <options> <expression>\n"); + printf("Options:\n"); + printf(" -H ldb_url choose the database (or $LDB_URL)\n"); + printf(" -s base|sub|one choose search scope\n"); + printf(" -b basedn choose baseDN\n"); + printf(" -a edit all records (expression 'dn=*')\n"); + printf(" -e editor choose editor (or $VISUAL or $EDITOR)\n"); + exit(1); +} + + int main(int argc, char * const argv[]) +{ + struct ldb_context *ldb; + struct ldb_message **msgs; + int ret; + const char *expression = NULL; + const char *ldb_url; + const char *basedn = NULL; + int opt; + enum ldb_scope scope = LDB_SCOPE_SUBTREE; + const char *editor; + + ldb_url = getenv("LDB_URL"); + + /* build the editor command to run - + use the same editor priorities as vipw */ + editor = getenv("VISUAL"); + if (!editor) { + editor = getenv("EDITOR"); + } + if (!editor) { + editor = "vi"; + } + + while ((opt = getopt(argc, argv, "ab:e:H:s:")) != EOF) { + switch (opt) { + case 'b': + basedn = optarg; + break; + + case 'H': + ldb_url = optarg; + break; + + case 's': + if (strcmp(optarg, "base") == 0) { + scope = LDB_SCOPE_BASE; + } else if (strcmp(optarg, "sub") == 0) { + scope = LDB_SCOPE_SUBTREE; + } else if (strcmp(optarg, "one") == 0) { + scope = LDB_SCOPE_ONELEVEL; + } + break; + + case 'e': + editor = optarg; + break; + + case 'a': + expression = "dn=*"; + break; + + case 'h': + default: + usage(); + break; + } + } + + if (!ldb_url) { + fprintf(stderr, "You must specify a ldb URL\n"); + exit(1); + } + + argc -= optind; + argv += optind; + + if (!expression) { + if (argc == 0) { + usage(); + } + expression = argv[0]; + } + + ldb = ldb_connect(ldb_url, 0, NULL); + + if (!ldb) { + perror("ldb_connect"); + exit(1); + } + + ret = ldb_search(ldb, basedn, scope, expression, NULL, &msgs); + + if (ret == -1) { + printf("search failed - %s\n", ldb_errstring(ldb)); + exit(1); + } + + if (ret == 0) { + printf("no matching records - cannot edit\n"); + return 0; + } + + do_edit(ldb, msgs, ret, editor); + + if (ret > 0) { + ret = ldb_search_free(ldb, msgs); + if (ret == -1) { + fprintf(stderr, "search_free failed\n"); + exit(1); + } + } + + ldb_close(ldb); + return 0; +} diff --git a/source4/lib/ldb/tools/ldbmodify.c b/source4/lib/ldb/tools/ldbmodify.c index e1cff655db..a93c710a7a 100644 --- a/source4/lib/ldb/tools/ldbmodify.c +++ b/source4/lib/ldb/tools/ldbmodify.c @@ -34,27 +34,27 @@ #include "includes.h" - int main(void) -{ - static struct ldb_context *ldb; - struct ldb_ldif *ldif; - int ret; - int count=0, failures=0; - const char *ldb_url; - - ldb_url = getenv("LDB_URL"); - if (!ldb_url) { - ldb_url = "tdb://test.ldb"; - } +static int failures; - ldb = ldb_connect(ldb_url, 0, NULL); - - if (!ldb) { - perror("ldb_connect"); - exit(1); - } +static void usage(void) +{ + printf("Usage: ldbmodify <options> <ldif...>\n"); + printf("Options:\n"); + printf(" -H ldb_url choose the database (or $LDB_URL)\n"); + printf("\n"); + printf("Modifies a ldb based upon ldif change records\n\n"); + exit(1); +} - while ((ldif = ldif_read_file(stdin))) { +/* + process modifies for one file +*/ +static int process_file(struct ldb_context *ldb, FILE *f) +{ + struct ldb_ldif *ldif; + int ret, count = 0; + + while ((ldif = ldif_read_file(f))) { switch (ldif->changetype) { case LDB_CHANGETYPE_NONE: case LDB_CHANGETYPE_ADD: @@ -77,6 +77,68 @@ ldif_read_free(ldif); } + return count; +} + + int main(int argc, char * const argv[]) +{ + struct ldb_context *ldb; + int count=0; + const char *ldb_url; + int opt, i; + + ldb_url = getenv("LDB_URL"); + + while ((opt = getopt(argc, argv, "hH:")) != EOF) { + switch (opt) { + case 'H': + ldb_url = optarg; + break; + + case 'h': + default: + usage(); + break; + } + } + + if (!ldb_url) { + fprintf(stderr, "You must specify a ldb URL\n"); + exit(1); + } + + argc -= optind; + argv += optind; + + ldb = ldb_connect(ldb_url, 0, NULL); + + if (!ldb) { + perror("ldb_connect"); + exit(1); + } + + if (argc == 0) { + usage(); + exit(1); + } + + for (i=0;i<argc;i++) { + FILE *f; + if (strcmp(argv[i],"-") == 0) { + f = stdin; + } else { + f = fopen(argv[i], "r"); + } + if (!f) { + perror(argv[i]); + exit(1); + } + count += process_file(ldb, f); + if (f != stdin) { + fclose(f); + } + } + ldb_close(ldb); printf("Modified %d records with %d failures\n", count, failures); diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index f4eb8f00db..327feb28ef 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -33,26 +33,32 @@ */ #include "includes.h" -#include <getopt.h> + +static void usage(void) +{ + printf("Usage: ldbsearch <options> <expression> <attrs...>\n"); + printf("Options:\n"); + printf(" -H ldb_url choose the database (or $LDB_URL)\n"); + printf(" -s base|sub|one choose search scope\n"); + printf(" -b basedn choose baseDN\n"); + exit(1); +} int main(int argc, char * const argv[]) { - static struct ldb_context *ldb; + struct ldb_context *ldb; struct ldb_message **msgs; int ret, i; const char *expression; - const char * const *attrs = NULL; + char * const *attrs = NULL; const char *ldb_url; const char *basedn = NULL; int opt; enum ldb_scope scope = LDB_SCOPE_SUBTREE; ldb_url = getenv("LDB_URL"); - if (!ldb_url) { - ldb_url = "tdb://test.ldb"; - } - while ((opt = getopt(argc, argv, "b:H:s:")) != EOF) { + while ((opt = getopt(argc, argv, "b:H:s:h")) != EOF) { switch (opt) { case 'b': basedn = optarg; @@ -71,14 +77,24 @@ scope = LDB_SCOPE_ONELEVEL; } break; + + case 'h': + default: + usage(); + break; } } + if (!ldb_url) { + fprintf(stderr, "You must specify a ldb URL\n"); + exit(1); + } + argc -= optind; argv += optind; if (argc < 1) { - printf("Usage: ldbsearch <expression> [attrs...]\n"); + usage(); exit(1); } diff --git a/source4/lib/replace.c b/source4/lib/replace.c index a4f3da1a66..cde9ce7a1b 100644 --- a/source4/lib/replace.c +++ b/source4/lib/replace.c @@ -445,7 +445,7 @@ char *rep_inet_ntoa(struct in_addr ip) tm2 = *tm; tm2.tm_isdst = tm3.tm_isdst; t = mktime(&tm2); - t -= TimeDiff(t); + t -= TimeDiff(); return t; } diff --git a/source4/lib/time.c b/source4/lib/time.c index 2844da004d..d6c6396996 100644 --- a/source4/lib/time.c +++ b/source4/lib/time.c @@ -1,8 +1,10 @@ /* Unix SMB/CIFS implementation. time handling functions - Copyright (C) Andrew Tridgell 1992-1998 + + Copyright (C) Andrew Tridgell 1992-2004 Copyright (C) Stefan (metze) Metzmacher 2002 + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -20,36 +22,17 @@ #include "includes.h" -/* - This stuff was largely rewritten by Paul Eggert <eggert@twinsun.com> - in May 1996 - */ - - -int extra_time_offset = 0; - -#ifndef CHAR_BIT -#define CHAR_BIT 8 -#endif - #ifndef TIME_T_MIN #define TIME_T_MIN ((time_t)0 < (time_t) -1 ? (time_t) 0 \ - : ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1)) + : ~ (time_t) 0 << (sizeof (time_t) * 8 - 1)) #endif #ifndef TIME_T_MAX #define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN) #endif -void get_nttime_max(NTTIME *t) -{ - /* FIXME: This is incorrect */ - unix_to_nt_time(t, get_time_t_max()); -} - /******************************************************************* External access to time_t_min and time_t_max. ********************************************************************/ - time_t get_time_t_max(void) { return TIME_T_MAX; @@ -67,225 +50,38 @@ void GetTimeOfDay(struct timeval *tval) #endif } -#define TM_YEAR_BASE 1900 - /******************************************************************* yield the difference between *A and *B, in seconds, ignoring leap seconds ********************************************************************/ static int tm_diff(struct tm *a, struct tm *b) { - int ay = a->tm_year + (TM_YEAR_BASE - 1); - int by = b->tm_year + (TM_YEAR_BASE - 1); - int intervening_leap_days = - (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400); - int years = ay - by; - int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday); - int hours = 24*days + (a->tm_hour - b->tm_hour); - int minutes = 60*hours + (a->tm_min - b->tm_min); - int seconds = 60*minutes + (a->tm_sec - b->tm_sec); - - return seconds; + int ay = a->tm_year + (1900 - 1); + int by = b->tm_year + (1900 - 1); + int intervening_leap_days = + (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400); + int years = ay - by; + int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday); + int hours = 24*days + (a->tm_hour - b->tm_hour); + int minutes = 60*hours + (a->tm_min - b->tm_min); + int seconds = 60*minutes + (a->tm_sec - b->tm_sec); + + return seconds; } /******************************************************************* return the UTC offset in seconds west of UTC, or 0 if it cannot be determined ******************************************************************/ -static int TimeZone(time_t t) -{ - struct tm *tm = gmtime(&t); - struct tm tm_utc; - if (!tm) - return 0; - tm_utc = *tm; - tm = localtime(&t); - if (!tm) - return 0; - return tm_diff(&tm_utc,tm); - -} - -static BOOL done_serverzone_init; - -/* Return the smb serverzone value */ - -static int get_serverzone(void) -{ - static int serverzone; - - if (!done_serverzone_init) { - serverzone = TimeZone(time(NULL)); - - if ((serverzone % 60) != 0) { - DEBUG(1,("WARNING: Your timezone is not a multiple of 1 minute.\n")); - } - - DEBUG(4,("Serverzone is %d\n",serverzone)); - - done_serverzone_init = True; - } - - return serverzone; -} - -/* Re-read the smb serverzone value */ - -static struct timeval start_time_hires; - -void TimeInit(void) -{ - done_serverzone_init = False; - get_serverzone(); - /* Save the start time of this process. */ - if (start_time_hires.tv_sec == 0 && start_time_hires.tv_usec == 0) - GetTimeOfDay(&start_time_hires); -} - -/********************************************************************** - Return a timeval struct of the uptime of this process. As TimeInit is - done before a daemon fork then this is the start time from the parent - daemon start. JRA. -***********************************************************************/ - -void get_process_uptime(struct timeval *ret_time) -{ - struct timeval time_now_hires; - - GetTimeOfDay(&time_now_hires); - ret_time->tv_sec = time_now_hires.tv_sec - start_time_hires.tv_sec; - ret_time->tv_usec = time_now_hires.tv_usec - start_time_hires.tv_usec; - if (time_now_hires.tv_usec < start_time_hires.tv_usec) { - ret_time->tv_sec -= 1; - ret_time->tv_usec = 1000000 + (time_now_hires.tv_usec - start_time_hires.tv_usec); - } else - ret_time->tv_usec = time_now_hires.tv_usec - start_time_hires.tv_usec; -} - -/******************************************************************* -return the same value as TimeZone, but it should be more efficient. - -We keep a table of DST offsets to prevent calling localtime() on each -call of this function. This saves a LOT of time on many unixes. - -Updated by Paul Eggert <eggert@twinsun.com> -********************************************************************/ -static int TimeZoneFaster(time_t t) +int get_time_zone(time_t t) { - static struct dst_table {time_t start,end; int zone;} *tdt, *dst_table = NULL; - static int table_size = 0; - int i; - int zone = 0; - - if (t == 0) t = time(NULL); - - /* Tunis has a 8 day DST region, we need to be careful ... */ -#define MAX_DST_WIDTH (365*24*60*60) -#define MAX_DST_SKIP (7*24*60*60) - - for (i=0;i<table_size;i++) - if (t >= dst_table[i].start && t <= dst_table[i].end) break; - - if (i<table_size) { - zone = dst_table[i].zone; - } else { - time_t low,high; - - zone = TimeZone(t); - tdt = (struct dst_table *)Realloc(dst_table, - sizeof(dst_table[0])*(i+1)); - if (!tdt) { - DEBUG(0,("TimeZoneFaster: out of memory!\n")); - SAFE_FREE(dst_table); - table_size = 0; - } else { - dst_table = tdt; - table_size++; - - dst_table[i].zone = zone; - dst_table[i].start = dst_table[i].end = t; - - /* no entry will cover more than 6 months */ - low = t - MAX_DST_WIDTH/2; - if (t < low) - low = TIME_T_MIN; - - high = t + MAX_DST_WIDTH/2; - if (high < t) - high = TIME_T_MAX; - - /* widen the new entry using two bisection searches */ - while (low+60*60 < dst_table[i].start) { - if (dst_table[i].start - low > MAX_DST_SKIP*2) - t = dst_table[i].start - MAX_DST_SKIP; - else - t = low + (dst_table[i].start-low)/2; - if (TimeZone(t) == zone) - dst_table[i].start = t; - else - low = t; - } - - while (high-60*60 > dst_table[i].end) { - if (high - dst_table[i].end > MAX_DST_SKIP*2) - t = dst_table[i].end + MAX_DST_SKIP; - else - t = high - (high-dst_table[i].end)/2; - if (TimeZone(t) == zone) - dst_table[i].end = t; - else - high = t; - } -#if 0 - DEBUG(1,("Added DST entry from %s ", - asctime(localtime(&dst_table[i].start)))); - DEBUG(1,("to %s (%d)\n",asctime(localtime(&dst_table[i].end)), - dst_table[i].zone)); -#endif - } - } - return zone; -} - -/**************************************************************************** - return the UTC offset in seconds west of UTC, adjusted for extra time offset - **************************************************************************/ -int TimeDiff(time_t t) -{ - return TimeZoneFaster(t) + 60 * lp_time_offset(); -} - - -/**************************************************************************** - return the UTC offset in seconds west of UTC, adjusted for extra time - offset, for a local time value. If ut = lt + LocTimeDiff(lt), then - lt = ut - TimeDiff(ut), but the converse does not necessarily hold near - daylight savings transitions because some local times are ambiguous. - LocTimeDiff(t) equals TimeDiff(t) except near daylight savings transitions. - +**************************************************************************/ -static int LocTimeDiff(time_t lte) -{ - time_t lt = lte - 60 * lp_time_offset(); - int d = TimeZoneFaster(lt); - time_t t = lt + d; - - /* if overflow occurred, ignore all the adjustments so far */ - if (((lte < lt) ^ (lp_time_offset() < 0)) | ((t < lt) ^ (d < 0))) - t = lte; - - /* now t should be close enough to the true UTC to yield the right answer */ - return TimeDiff(t); -} - - -/**************************************************************************** -try to optimise the localtime call, it can be quite expensive on some machines -****************************************************************************/ -struct tm *LocalTime(time_t *t) -{ - time_t t2 = *t; - - t2 -= TimeDiff(t2); - - return(gmtime(&t2)); + struct tm *tm = gmtime(&t); + struct tm tm_utc; + if (!tm) + return 0; + tm_utc = *tm; + tm = localtime(&t); + if (!tm) + return 0; + return tm_diff(&tm_utc,tm); } #define TIME_FIXUP_CONSTANT (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60)) @@ -293,86 +89,36 @@ struct tm *LocalTime(time_t *t) /**************************************************************************** interpret an 8 byte "filetime" structure to a time_t It's originally in "100ns units since jan 1st 1601" - -It appears to be kludge-GMT (at least for file listings). This means -its the GMT you get by taking a localtime and adding the -serverzone. This is NOT the same as GMT in some cases. This routine -converts this to real GMT. ****************************************************************************/ time_t nt_time_to_unix(const NTTIME *nt) { - double d; - time_t ret; - /* The next two lines are a fix needed for the - broken SCO compiler. JRA. */ - time_t l_time_min = TIME_T_MIN; - time_t l_time_max = TIME_T_MAX; - - if (nt->high == 0) return(0); - - d = ((double)nt->high)*4.0*(double)(1<<30); - d += (nt->low&0xFFF00000); - d *= 1.0e-7; - - /* now adjust by 369 years to make the secs since 1970 */ - d -= TIME_FIXUP_CONSTANT; - - if (!(l_time_min <= d && d <= l_time_max)) - return(0); - - ret = (time_t)(d+0.5); - - /* this takes us from kludge-GMT to real GMT */ - ret -= get_serverzone(); - ret += LocTimeDiff(ret); - - return(ret); -} - -/**************************************************************************** - Convert a NTTIME structure to a time_t. - It's originally in "100ns units". - - This is an absolute version of the one above. - By absolute I mean, it doesn't adjust from 1/1/1601 to 1/1/1970 - if the NTTIME was 5 seconds, the time_t is 5 seconds. JFM -****************************************************************************/ - -time_t nt_time_to_unix_abs(NTTIME *nt) -{ double d; time_t ret; - /* The next two lines are a fix needed for the - broken SCO compiler. JRA. */ - time_t l_time_min = TIME_T_MIN; - time_t l_time_max = TIME_T_MAX; - if (nt->high == 0) - return(0); - - if (nt->high==0x80000000 && nt->low==0) - return -1; - - /* reverse the time */ - /* it's a negative value, turn it to positive */ - nt->high=~nt->high; - nt->low=~nt->low; + if (nt->high == 0) { + return 0; + } d = ((double)nt->high)*4.0*(double)(1<<30); d += (nt->low&0xFFF00000); d *= 1.0e-7; - - if (!(l_time_min <= d && d <= l_time_max)) - return(0); + + /* now adjust by 369 years to make the secs since 1970 */ + d -= TIME_FIXUP_CONSTANT; + + if (TIME_T_MIN >= d || d >= TIME_T_MAX) { + return 0; + } ret = (time_t)(d+0.5); - return(ret); + return ret; } + /**************************************************************************** put a 8 byte filetime from a time_t -This takes real GMT as input and converts to kludge-GMT +This takes GMT as input ****************************************************************************/ void unix_to_nt_time(NTTIME *nt, time_t t) { @@ -394,9 +140,6 @@ void unix_to_nt_time(NTTIME *nt, time_t t) return; } - /* this converts GMT to kludge-GMT */ - t -= TimeDiff(t) - get_serverzone(); - d = (double)(t); d += TIME_FIXUP_CONSTANT; d *= 1.0e7; @@ -405,69 +148,15 @@ void unix_to_nt_time(NTTIME *nt, time_t t) nt->low = (uint32)(d - ((double)nt->high)*4.0*(double)(1<<30)); } -/**************************************************************************** - Convert a time_t to a NTTIME structure - - This is an absolute version of the one above. - By absolute I mean, it doesn't adjust from 1/1/1970 to 1/1/1601 - If the nttime_t was 5 seconds, the NTTIME is 5 seconds. JFM -****************************************************************************/ - -void unix_to_nt_time_abs(NTTIME *nt, time_t t) -{ - double d; - - if (t==0) { - nt->low = 0; - nt->high = 0; - return; - } - - if (t == TIME_T_MAX) { - nt->low = 0xffffffff; - nt->high = 0x7fffffff; - return; - } - - if (t == -1) { - /* that's what NT uses for infinite */ - nt->low = 0x0; - nt->high = 0x80000000; - return; - } - - d = (double)(t); - d *= 1.0e7; - - nt->high = (uint32)(d * (1.0/(4.0*(double)(1<<30)))); - nt->low = (uint32)(d - ((double)nt->high)*4.0*(double)(1<<30)); - - /* convert to a negative value */ - nt->high=~nt->high; - nt->low=~nt->low; -} - - -/**************************************************************************** -take an NTTIME structure, containing high / low time. convert to unix time. -lkclXXXX this may need 2 SIVALs not a memcpy. we'll see... -****************************************************************************/ -void put_long_date(char *p,time_t t) -{ - NTTIME nt; - unix_to_nt_time(&nt, t); - SIVAL(p, 0, nt.low); - SIVAL(p, 4, nt.high); -} /**************************************************************************** check if it's a null mtime ****************************************************************************/ BOOL null_mtime(time_t mtime) { - if (mtime == 0 || mtime == (time_t)0xFFFFFFFF || mtime == (time_t)-1) - return True; - return False; + return mtime == 0 || + mtime == (time_t)0xFFFFFFFF || + mtime == (time_t)-1; } /******************************************************************* @@ -496,7 +185,7 @@ static uint16 make_dos_time1(struct tm *t) create a 32 bit dos packed date/time from some parameters This takes a GMT time and returns a packed localtime structure ********************************************************************/ -static uint32 make_dos_date(time_t unixdate) +static uint32 make_dos_date(time_t unixdate, int zone_offset) { struct tm *t; uint32 ret=0; @@ -505,7 +194,9 @@ static uint32 make_dos_date(time_t unixdate) return 0; } - t = LocalTime(&unixdate); + unixdate -= zone_offset; + + t = gmtime(&unixdate); if (!t) { return 0xFFFFFFFF; } @@ -520,9 +211,9 @@ static uint32 make_dos_date(time_t unixdate) put a dos date into a buffer (time/date format) This takes GMT time and puts local time in the buffer ********************************************************************/ -void put_dos_date(char *buf,int offset,time_t unixdate) +void push_dos_date(char *buf, int offset, time_t unixdate, int zone_offset) { - uint32 x = make_dos_date(unixdate); + uint32 x = make_dos_date(unixdate, zone_offset); SIVAL(buf,offset,x); } @@ -530,10 +221,10 @@ void put_dos_date(char *buf,int offset,time_t unixdate) put a dos date into a buffer (date/time format) This takes GMT time and puts local time in the buffer ********************************************************************/ -void put_dos_date2(char *buf,int offset,time_t unixdate) +void push_dos_date2(char *buf,int offset,time_t unixdate, int zone_offset) { uint32 x; - x = make_dos_date(unixdate); + x = make_dos_date(unixdate, zone_offset); x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16); SIVAL(buf,offset,x); } @@ -543,10 +234,11 @@ put a dos 32 bit "unix like" date into a buffer. This routine takes GMT and converts it to LOCAL time before putting it (most SMBs assume localtime for this sort of date) ********************************************************************/ -void put_dos_date3(char *buf,int offset,time_t unixdate) +void push_dos_date3(char *buf,int offset,time_t unixdate, int zone_offset) { - if (!null_mtime(unixdate)) - unixdate -= TimeDiff(unixdate); + if (!null_mtime(unixdate)) { + unixdate -= zone_offset; + } SIVAL(buf,offset,unixdate); } @@ -555,24 +247,24 @@ void put_dos_date3(char *buf,int offset,time_t unixdate) ********************************************************************/ static void interpret_dos_date(uint32 date,int *year,int *month,int *day,int *hour,int *minute,int *second) { - uint32 p0,p1,p2,p3; + uint32 p0,p1,p2,p3; - p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF; - p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF; + p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF; + p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF; - *second = 2*(p0 & 0x1F); - *minute = ((p0>>5)&0xFF) + ((p1&0x7)<<3); - *hour = (p1>>3)&0xFF; - *day = (p2&0x1F); - *month = ((p2>>5)&0xFF) + ((p3&0x1)<<3) - 1; - *year = ((p3>>1)&0xFF) + 80; + *second = 2*(p0 & 0x1F); + *minute = ((p0>>5)&0xFF) + ((p1&0x7)<<3); + *hour = (p1>>3)&0xFF; + *day = (p2&0x1F); + *month = ((p2>>5)&0xFF) + ((p3&0x1)<<3) - 1; + *year = ((p3>>1)&0xFF) + 80; } /******************************************************************* create a unix date (int GMT) from a dos date (which is actually in localtime) ********************************************************************/ -time_t make_unix_date(void *date_ptr) +time_t pull_dos_date(const uint8 *date_ptr, int zone_offset) { uint32 dos_date=0; struct tm t; @@ -586,16 +278,17 @@ time_t make_unix_date(void *date_ptr) &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec); t.tm_isdst = -1; - /* mktime() also does the local to GMT time conversion for us */ - ret = mktime(&t); + ret = timegm(&t); - return(ret); + ret += zone_offset; + + return ret; } /******************************************************************* like make_unix_date() but the words are reversed ********************************************************************/ -time_t make_unix_date2(void *date_ptr) +time_t pull_dos_date2(const uint8 *date_ptr, int zone_offset) { uint32 x,x2; @@ -603,18 +296,19 @@ time_t make_unix_date2(void *date_ptr) x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16); SIVAL(&x,0,x2); - return make_unix_date((void *)&x); + return pull_dos_date((void *)&x, zone_offset); } /******************************************************************* create a unix GMT date from a dos date in 32 bit "unix like" format these generally arrive as localtimes, with corresponding DST ******************************************************************/ -time_t make_unix_date3(void *date_ptr) +time_t pull_dos_date3(const uint8 *date_ptr, int zone_offset) { time_t t = (time_t)IVAL(date_ptr,0); - if (!null_mtime(t)) - t += LocTimeDiff(t); + if (!null_mtime(t)) { + t += zone_offset; + } return t; } @@ -624,22 +318,25 @@ return a HTTP/1.0 time string ***************************************************************************/ char *http_timestring(TALLOC_CTX *mem_ctx, time_t t) { - char *buf; - fstring tempTime; - struct tm *tm = LocalTime(&t); + char *buf; + char tempTime[60]; + struct tm *tm = localtime(&t); + + if (!tm) { + return talloc_asprintf(mem_ctx,"%ld seconds since the Epoch",(long)t); + } - if (!tm) - buf = talloc_asprintf(mem_ctx,"%ld seconds since the Epoch",(long)t); - else #ifndef HAVE_STRFTIME - buf = talloc_strdup(mem_ctx, asctime(tm)); - if(buf[strlen(buf)-1] == '\n') - buf[strlen(buf)-1] = 0; -#else /* !HAVE_STRFTIME */ + buf = talloc_strdup(mem_ctx, asctime(tm)); + if (buf[strlen(buf)-1] == '\n') { + buf[strlen(buf)-1] = 0; + } +#else strftime(tempTime, sizeof(tempTime)-1, "%a, %d %b %Y %H:%M:%S %Z", tm); - buf = talloc_strdup(mem_ctx, tempTime); + buf = talloc_strdup(mem_ctx, tempTime); #endif /* !HAVE_STRFTIME */ - return buf; + + return buf; } @@ -647,90 +344,27 @@ char *http_timestring(TALLOC_CTX *mem_ctx, time_t t) /**************************************************************************** Return the date and time as a string ****************************************************************************/ - -char *timestring(TALLOC_CTX *mem_ctx, BOOL hires) +char *timestring(TALLOC_CTX *mem_ctx, time_t t) { char *TimeBuf; - fstring tempTime; - struct timeval tp; - time_t t; + char tempTime[80]; struct tm *tm; - if (hires) { - GetTimeOfDay(&tp); - t = (time_t)tp.tv_sec; - } else { - t = time(NULL); - } - tm = LocalTime(&t); + tm = localtime(&t); if (!tm) { - if (hires) { - TimeBuf = talloc_asprintf(mem_ctx, - "%ld.%06ld seconds since the Epoch", - (long)tp.tv_sec, - (long)tp.tv_usec); - } else { - TimeBuf = talloc_asprintf(mem_ctx, - "%ld seconds since the Epoch", - (long)t); - } - } else { + return talloc_asprintf(mem_ctx, + "%ld seconds since the Epoch", + (long)t); + } + #ifdef HAVE_STRFTIME - if (hires) { - strftime(tempTime,sizeof(tempTime)-1,"%Y/%m/%d %H:%M:%S",tm); - TimeBuf = talloc_asprintf(mem_ctx, "%s.%06ld", - tempTime, (long)tp.tv_usec); - } else { - strftime(tempTime,100,"%Y/%m/%d %H:%M:%S",tm); - TimeBuf = talloc_strdup(mem_ctx, tempTime); - } + strftime(tempTime,sizeof(tempTime)-1,"%c %Z",tm); + TimeBuf = talloc_strdup(mem_ctx, tempTime); #else - if (hires) { - TimeBuf = talloc_asprintf(mem_ctx, - "%s.%06ld", - asctime(tm), - (long)tp.tv_usec); - } else { - TimeBuf = talloc_strdup(mem_ctx, asctime(tm)); - } + TimeBuf = talloc_strdup(mem_ctx, asctime(tm)); #endif - } - return(TimeBuf); -} - -/**************************************************************************** - return the best approximation to a 'create time' under UNIX from a stat - structure. -****************************************************************************/ - -time_t get_create_time(SMB_STRUCT_STAT *st,BOOL fake_dirs) -{ - time_t ret, ret1; - - if(S_ISDIR(st->st_mode) && fake_dirs) - return (time_t)315493200L; /* 1/1/1980 */ - - ret = MIN(st->st_ctime, st->st_mtime); - ret1 = MIN(ret, st->st_atime); - - if(ret1 != (time_t)0) - return ret1; - - /* - * One of ctime, mtime or atime was zero (probably atime). - * Just return MIN(ctime, mtime). - */ - return ret; -} - -/**************************************************************************** -initialise an NTTIME to -1, which means "unknown" or "don't expire" -****************************************************************************/ -void init_nt_time(NTTIME *nt) -{ - nt->high = 0x7FFFFFFF; - nt->low = 0xFFFFFFFF; + return TimeBuf; } /**************************************************************************** @@ -738,9 +372,7 @@ check if NTTIME is 0 ****************************************************************************/ BOOL nt_time_is_zero(NTTIME *nt) { - if(nt->high==0) - return True; - return False; + return (nt->high==0); } /* @@ -749,6 +381,27 @@ BOOL nt_time_is_zero(NTTIME *nt) const char *nt_time_string(TALLOC_CTX *mem_ctx, const NTTIME *nt) { time_t t = nt_time_to_unix(nt); - return talloc_strdup(mem_ctx, http_timestring(mem_ctx, t)); + return talloc_strdup(mem_ctx, timestring(mem_ctx, t)); +} + + +/* + put a NTTIME into a packet +*/ +void push_nttime(void *base, uint16 offset, NTTIME *t) +{ + SIVAL(base, offset, t->low); + SIVAL(base, offset+4, t->high); +} + +/* + pull a NTTIME from a packet +*/ +NTTIME pull_nttime(void *base, uint16 offset) +{ + NTTIME ret; + ret.low = IVAL(base, offset); + ret.high = IVAL(base, offset+4); + return ret; } |