From caa4e428604780bb098060f7286c69d30c8b4007 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 11 Oct 2008 21:05:38 +0200 Subject: Move lib/util from source4 to top-level libutil. Conflicts: source4/Makefile --- .gitignore | 10 +- lib/util/Doxyfile | 24 + lib/util/asn1.c | 770 +++++++++++++++++++++++++++++++ lib/util/asn1.h | 54 +++ lib/util/attr.h | 90 ++++ lib/util/become_daemon.c | 93 ++++ lib/util/byteorder.h | 231 ++++++++++ lib/util/capability.c | 103 +++++ lib/util/capability.m4 | 17 + lib/util/config.mk | 71 +++ lib/util/data_blob.c | 232 ++++++++++ lib/util/data_blob.h | 123 +++++ lib/util/debug.c | 248 ++++++++++ lib/util/debug.h | 129 ++++++ lib/util/dlinklist.h | 113 +++++ lib/util/dprintf.c | 111 +++++ lib/util/fault.c | 226 +++++++++ lib/util/fault.m4 | 5 + lib/util/fsusage.c | 154 +++++++ lib/util/fsusage.m4 | 190 ++++++++ lib/util/genrand.c | 361 +++++++++++++++ lib/util/idtree.c | 403 ++++++++++++++++ lib/util/mainpage.dox | 11 + lib/util/ms_fnmatch.c | 223 +++++++++ lib/util/mutex.c | 56 +++ lib/util/mutex.h | 75 +++ lib/util/params.c | 587 ++++++++++++++++++++++++ lib/util/safe_string.h | 44 ++ lib/util/signal.c | 144 ++++++ lib/util/signal.m4 | 1 + lib/util/system.c | 90 ++++ lib/util/tests/file.c | 97 ++++ lib/util/tests/genrand.c | 65 +++ lib/util/tests/idtree.c | 121 +++++ lib/util/tests/str.c | 121 +++++ lib/util/tests/strlist.c | 103 +++++ lib/util/time.c | 622 +++++++++++++++++++++++++ lib/util/time.h | 232 ++++++++++ lib/util/time.m4 | 9 + lib/util/unix_privs.c | 77 ++++ lib/util/util.c | 608 ++++++++++++++++++++++++ lib/util/util.h | 813 +++++++++++++++++++++++++++++++++ lib/util/util.m4 | 1 + lib/util/util_file.c | 404 ++++++++++++++++ lib/util/util_getent.c | 283 ++++++++++++ lib/util/util_ldb.c | 134 ++++++ lib/util/util_ldb.h | 27 ++ lib/util/util_pw.c | 77 ++++ lib/util/util_str.c | 790 ++++++++++++++++++++++++++++++++ lib/util/util_strlist.c | 308 +++++++++++++ lib/util/util_tdb.c | 546 ++++++++++++++++++++++ lib/util/wrap_xattr.c | 120 +++++ lib/util/wrap_xattr.h | 12 + lib/util/xattr.m4 | 32 ++ lib/util/xfile.c | 389 ++++++++++++++++ lib/util/xfile.h | 99 ++++ source4/Makefile | 4 +- source4/auth/credentials/credentials.h | 2 +- source4/configure.ac | 14 +- source4/include/includes.h | 4 +- source4/lib/util/Doxyfile | 24 - source4/lib/util/asn1.c | 770 ------------------------------- source4/lib/util/asn1.h | 54 --- source4/lib/util/attr.h | 90 ---- source4/lib/util/become_daemon.c | 93 ---- source4/lib/util/byteorder.h | 231 ---------- source4/lib/util/capability.c | 103 ----- source4/lib/util/capability.m4 | 17 - source4/lib/util/config.mk | 71 --- source4/lib/util/data_blob.c | 232 ---------- source4/lib/util/data_blob.h | 123 ----- source4/lib/util/debug.c | 248 ---------- source4/lib/util/debug.h | 129 ------ source4/lib/util/dlinklist.h | 113 ----- source4/lib/util/dprintf.c | 111 ----- source4/lib/util/fault.c | 226 --------- source4/lib/util/fault.m4 | 5 - source4/lib/util/fsusage.c | 154 ------- source4/lib/util/fsusage.m4 | 190 -------- source4/lib/util/genrand.c | 361 --------------- source4/lib/util/idtree.c | 403 ---------------- source4/lib/util/mainpage.dox | 11 - source4/lib/util/ms_fnmatch.c | 223 --------- source4/lib/util/mutex.c | 56 --- source4/lib/util/mutex.h | 75 --- source4/lib/util/params.c | 587 ------------------------ source4/lib/util/safe_string.h | 44 -- source4/lib/util/signal.c | 144 ------ source4/lib/util/signal.m4 | 1 - source4/lib/util/system.c | 90 ---- source4/lib/util/tests/file.c | 97 ---- source4/lib/util/tests/genrand.c | 65 --- source4/lib/util/tests/idtree.c | 121 ----- source4/lib/util/tests/str.c | 121 ----- source4/lib/util/tests/strlist.c | 103 ----- source4/lib/util/time.c | 622 ------------------------- source4/lib/util/time.h | 232 ---------- source4/lib/util/time.m4 | 9 - source4/lib/util/unix_privs.c | 77 ---- source4/lib/util/util.c | 608 ------------------------ source4/lib/util/util.h | 813 --------------------------------- source4/lib/util/util.m4 | 1 - source4/lib/util/util_file.c | 404 ---------------- source4/lib/util/util_getent.c | 283 ------------ source4/lib/util/util_ldb.c | 134 ------ source4/lib/util/util_ldb.h | 27 -- source4/lib/util/util_pw.c | 77 ---- source4/lib/util/util_str.c | 790 -------------------------------- source4/lib/util/util_strlist.c | 308 ------------- source4/lib/util/util_tdb.c | 546 ---------------------- source4/lib/util/wrap_xattr.c | 120 ----- source4/lib/util/wrap_xattr.h | 12 - source4/lib/util/xattr.m4 | 32 -- source4/lib/util/xfile.c | 389 ---------------- source4/lib/util/xfile.h | 99 ---- source4/librpc/ndr/libndr.h | 2 +- source4/librpc/rpc/dcerpc.h | 2 +- source4/main.mk | 2 +- source4/torture/local/config.mk | 10 +- source4/utils/getntacl.c | 2 +- 120 files changed, 11095 insertions(+), 11095 deletions(-) create mode 100644 lib/util/Doxyfile create mode 100644 lib/util/asn1.c create mode 100644 lib/util/asn1.h create mode 100644 lib/util/attr.h create mode 100644 lib/util/become_daemon.c create mode 100644 lib/util/byteorder.h create mode 100644 lib/util/capability.c create mode 100644 lib/util/capability.m4 create mode 100644 lib/util/config.mk create mode 100644 lib/util/data_blob.c create mode 100644 lib/util/data_blob.h create mode 100644 lib/util/debug.c create mode 100644 lib/util/debug.h create mode 100644 lib/util/dlinklist.h create mode 100644 lib/util/dprintf.c create mode 100644 lib/util/fault.c create mode 100644 lib/util/fault.m4 create mode 100644 lib/util/fsusage.c create mode 100644 lib/util/fsusage.m4 create mode 100644 lib/util/genrand.c create mode 100644 lib/util/idtree.c create mode 100644 lib/util/mainpage.dox create mode 100644 lib/util/ms_fnmatch.c create mode 100644 lib/util/mutex.c create mode 100644 lib/util/mutex.h create mode 100644 lib/util/params.c create mode 100644 lib/util/safe_string.h create mode 100644 lib/util/signal.c create mode 100644 lib/util/signal.m4 create mode 100644 lib/util/system.c create mode 100644 lib/util/tests/file.c create mode 100644 lib/util/tests/genrand.c create mode 100644 lib/util/tests/idtree.c create mode 100644 lib/util/tests/str.c create mode 100644 lib/util/tests/strlist.c create mode 100644 lib/util/time.c create mode 100644 lib/util/time.h create mode 100644 lib/util/time.m4 create mode 100644 lib/util/unix_privs.c create mode 100644 lib/util/util.c create mode 100644 lib/util/util.h create mode 100644 lib/util/util.m4 create mode 100644 lib/util/util_file.c create mode 100644 lib/util/util_getent.c create mode 100644 lib/util/util_ldb.c create mode 100644 lib/util/util_ldb.h create mode 100644 lib/util/util_pw.c create mode 100644 lib/util/util_str.c create mode 100644 lib/util/util_strlist.c create mode 100644 lib/util/util_tdb.c create mode 100644 lib/util/wrap_xattr.c create mode 100644 lib/util/wrap_xattr.h create mode 100644 lib/util/xattr.m4 create mode 100644 lib/util/xfile.c create mode 100644 lib/util/xfile.h delete mode 100644 source4/lib/util/Doxyfile delete mode 100644 source4/lib/util/asn1.c delete mode 100644 source4/lib/util/asn1.h delete mode 100644 source4/lib/util/attr.h delete mode 100644 source4/lib/util/become_daemon.c delete mode 100644 source4/lib/util/byteorder.h delete mode 100644 source4/lib/util/capability.c delete mode 100644 source4/lib/util/capability.m4 delete mode 100644 source4/lib/util/config.mk delete mode 100644 source4/lib/util/data_blob.c delete mode 100644 source4/lib/util/data_blob.h delete mode 100644 source4/lib/util/debug.c delete mode 100644 source4/lib/util/debug.h delete mode 100644 source4/lib/util/dlinklist.h delete mode 100644 source4/lib/util/dprintf.c delete mode 100644 source4/lib/util/fault.c delete mode 100644 source4/lib/util/fault.m4 delete mode 100644 source4/lib/util/fsusage.c delete mode 100644 source4/lib/util/fsusage.m4 delete mode 100644 source4/lib/util/genrand.c delete mode 100644 source4/lib/util/idtree.c delete mode 100644 source4/lib/util/mainpage.dox delete mode 100644 source4/lib/util/ms_fnmatch.c delete mode 100644 source4/lib/util/mutex.c delete mode 100644 source4/lib/util/mutex.h delete mode 100644 source4/lib/util/params.c delete mode 100644 source4/lib/util/safe_string.h delete mode 100644 source4/lib/util/signal.c delete mode 100644 source4/lib/util/signal.m4 delete mode 100644 source4/lib/util/system.c delete mode 100644 source4/lib/util/tests/file.c delete mode 100644 source4/lib/util/tests/genrand.c delete mode 100644 source4/lib/util/tests/idtree.c delete mode 100644 source4/lib/util/tests/str.c delete mode 100644 source4/lib/util/tests/strlist.c delete mode 100644 source4/lib/util/time.c delete mode 100644 source4/lib/util/time.h delete mode 100644 source4/lib/util/time.m4 delete mode 100644 source4/lib/util/unix_privs.c delete mode 100644 source4/lib/util/util.c delete mode 100644 source4/lib/util/util.h delete mode 100644 source4/lib/util/util.m4 delete mode 100644 source4/lib/util/util_file.c delete mode 100644 source4/lib/util/util_getent.c delete mode 100644 source4/lib/util/util_ldb.c delete mode 100644 source4/lib/util/util_ldb.h delete mode 100644 source4/lib/util/util_pw.c delete mode 100644 source4/lib/util/util_str.c delete mode 100644 source4/lib/util/util_strlist.c delete mode 100644 source4/lib/util/util_tdb.c delete mode 100644 source4/lib/util/wrap_xattr.c delete mode 100644 source4/lib/util/wrap_xattr.h delete mode 100644 source4/lib/util/xattr.m4 delete mode 100644 source4/lib/util/xfile.c delete mode 100644 source4/lib/util/xfile.h diff --git a/.gitignore b/.gitignore index e585504ce5..fa4fc5f377 100644 --- a/.gitignore +++ b/.gitignore @@ -231,11 +231,11 @@ source4/lib/tdb/bin/tdbtool source4/lib/tdb/bin/tdbtorture source4/lib/tdr/tdr_proto.h source4/lib/util/apidocs -source4/lib/util/asn1_proto.h -source4/lib/util/pidfile.h -source4/lib/util/unix_privs.h -source4/lib/util/util_proto.h -source4/lib/util/util_tdb.h +lib/util/asn1_proto.h +lib/util/pidfile.h +lib/util/unix_privs.h +lib/util/util_proto.h +lib/util/util_tdb.h source4/mkconfig.mk source4/nbt_server/dgram/proto.h source4/nbt_server/nbt_server_proto.h diff --git a/lib/util/Doxyfile b/lib/util/Doxyfile new file mode 100644 index 0000000000..02e36a7af9 --- /dev/null +++ b/lib/util/Doxyfile @@ -0,0 +1,24 @@ +PROJECT_NAME = SAMBA_UTIL +OUTPUT_DIRECTORY = apidocs +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +OPTIMIZE_OUTPUT_FOR_C = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +GENERATE_TODOLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +SHOW_USED_FILES = NO +SHOW_DIRECTORIES = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +INPUT = . +FILE_PATTERNS = *.c *.h *.dox +GENERATE_HTML = YES +HTML_OUTPUT = html +GENERATE_MAN = YES +ALWAYS_DETAILED_SEC = YES +JAVADOC_AUTOBRIEF = YES diff --git a/lib/util/asn1.c b/lib/util/asn1.c new file mode 100644 index 0000000000..4756c0640d --- /dev/null +++ b/lib/util/asn1.c @@ -0,0 +1,770 @@ +/* + Unix SMB/CIFS implementation. + simple ASN1 routines + Copyright (C) Andrew Tridgell 2001 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "lib/util/asn1.h" + +/* allocate an asn1 structure */ +struct asn1_data *asn1_init(TALLOC_CTX *mem_ctx) +{ + struct asn1_data *ret = talloc_zero(mem_ctx, struct asn1_data); + if (ret == NULL) { + DEBUG(0,("asn1_init failed! out of memory\n")); + } + return ret; +} + +/* free an asn1 structure */ +void asn1_free(struct asn1_data *data) +{ + talloc_free(data); +} + +/* write to the ASN1 buffer, advancing the buffer pointer */ +bool asn1_write(struct asn1_data *data, const void *p, int len) +{ + if (data->has_error) return false; + if (data->length < data->ofs+len) { + uint8_t *newp; + newp = talloc_realloc(data, data->data, uint8_t, data->ofs+len); + if (!newp) { + asn1_free(data); + data->has_error = true; + return false; + } + data->data = newp; + data->length = data->ofs+len; + } + memcpy(data->data + data->ofs, p, len); + data->ofs += len; + return true; +} + +/* useful fn for writing a uint8_t */ +bool asn1_write_uint8(struct asn1_data *data, uint8_t v) +{ + return asn1_write(data, &v, 1); +} + +/* push a tag onto the asn1 data buffer. Used for nested structures */ +bool asn1_push_tag(struct asn1_data *data, uint8_t tag) +{ + struct nesting *nesting; + + asn1_write_uint8(data, tag); + nesting = talloc(data, struct nesting); + if (!nesting) { + data->has_error = true; + return false; + } + + nesting->start = data->ofs; + nesting->next = data->nesting; + data->nesting = nesting; + return asn1_write_uint8(data, 0xff); +} + +/* pop a tag */ +bool asn1_pop_tag(struct asn1_data *data) +{ + struct nesting *nesting; + size_t len; + + nesting = data->nesting; + + if (!nesting) { + data->has_error = true; + return false; + } + len = data->ofs - (nesting->start+1); + /* yes, this is ugly. We don't know in advance how many bytes the length + of a tag will take, so we assumed 1 byte. If we were wrong then we + need to correct our mistake */ + if (len > 0xFFFFFF) { + data->data[nesting->start] = 0x84; + if (!asn1_write_uint8(data, 0)) return false; + if (!asn1_write_uint8(data, 0)) return false; + if (!asn1_write_uint8(data, 0)) return false; + if (!asn1_write_uint8(data, 0)) return false; + memmove(data->data+nesting->start+5, data->data+nesting->start+1, len); + data->data[nesting->start+1] = (len>>24) & 0xFF; + data->data[nesting->start+2] = (len>>16) & 0xFF; + data->data[nesting->start+3] = (len>>8) & 0xFF; + data->data[nesting->start+4] = len&0xff; + } else if (len > 0xFFFF) { + data->data[nesting->start] = 0x83; + if (!asn1_write_uint8(data, 0)) return false; + if (!asn1_write_uint8(data, 0)) return false; + if (!asn1_write_uint8(data, 0)) return false; + memmove(data->data+nesting->start+4, data->data+nesting->start+1, len); + data->data[nesting->start+1] = (len>>16) & 0xFF; + data->data[nesting->start+2] = (len>>8) & 0xFF; + data->data[nesting->start+3] = len&0xff; + } else if (len > 255) { + data->data[nesting->start] = 0x82; + if (!asn1_write_uint8(data, 0)) return false; + if (!asn1_write_uint8(data, 0)) return false; + memmove(data->data+nesting->start+3, data->data+nesting->start+1, len); + data->data[nesting->start+1] = len>>8; + data->data[nesting->start+2] = len&0xff; + } else if (len > 127) { + data->data[nesting->start] = 0x81; + if (!asn1_write_uint8(data, 0)) return false; + memmove(data->data+nesting->start+2, data->data+nesting->start+1, len); + data->data[nesting->start+1] = len; + } else { + data->data[nesting->start] = len; + } + + data->nesting = nesting->next; + talloc_free(nesting); + return true; +} + +/* "i" is the one's complement representation, as is the normal result of an + * implicit signed->unsigned conversion */ + +static bool push_int_bigendian(struct asn1_data *data, unsigned int i, bool negative) +{ + uint8_t lowest = i & 0xFF; + + i = i >> 8; + if (i != 0) + if (!push_int_bigendian(data, i, negative)) + return false; + + if (data->nesting->start+1 == data->ofs) { + + /* We did not write anything yet, looking at the highest + * valued byte */ + + if (negative) { + /* Don't write leading 0xff's */ + if (lowest == 0xFF) + return true; + + if ((lowest & 0x80) == 0) { + /* The only exception for a leading 0xff is if + * the highest bit is 0, which would indicate + * a positive value */ + if (!asn1_write_uint8(data, 0xff)) + return false; + } + } else { + if (lowest & 0x80) { + /* The highest bit of a positive integer is 1, + * this would indicate a negative number. Push + * a 0 to indicate a positive one */ + if (!asn1_write_uint8(data, 0)) + return false; + } + } + } + + return asn1_write_uint8(data, lowest); +} + +/* write an Integer without the tag framing. Needed for example for the LDAP + * Abandon Operation */ + +bool asn1_write_implicit_Integer(struct asn1_data *data, int i) +{ + if (i == -1) { + /* -1 is special as it consists of all-0xff bytes. In + push_int_bigendian this is the only case that is not + properly handled, as all 0xff bytes would be handled as + leading ones to be ignored. */ + return asn1_write_uint8(data, 0xff); + } else { + return push_int_bigendian(data, i, i<0); + } +} + + +/* write an integer */ +bool asn1_write_Integer(struct asn1_data *data, int i) +{ + if (!asn1_push_tag(data, ASN1_INTEGER)) return false; + if (!asn1_write_implicit_Integer(data, i)) return false; + return asn1_pop_tag(data); +} + +bool ber_write_OID_String(DATA_BLOB *blob, const char *OID) +{ + uint_t v, v2; + const char *p = (const char *)OID; + char *newp; + int i; + + v = strtoul(p, &newp, 10); + if (newp[0] != '.') return false; + p = newp + 1; + + v2 = strtoul(p, &newp, 10); + if (newp[0] != '.') return false; + p = newp + 1; + + /*the ber representation can't use more space then the string one */ + *blob = data_blob(NULL, strlen(OID)); + if (!blob->data) return false; + + blob->data[0] = 40*v + v2; + + i = 1; + while (*p) { + v = strtoul(p, &newp, 10); + if (newp[0] == '.') { + p = newp + 1; + } else if (newp[0] == '\0') { + p = newp; + } else { + data_blob_free(blob); + return false; + } + if (v >= (1<<28)) blob->data[i++] = (0x80 | ((v>>28)&0x7f)); + if (v >= (1<<21)) blob->data[i++] = (0x80 | ((v>>21)&0x7f)); + if (v >= (1<<14)) blob->data[i++] = (0x80 | ((v>>14)&0x7f)); + if (v >= (1<<7)) blob->data[i++] = (0x80 | ((v>>7)&0x7f)); + blob->data[i++] = (v&0x7f); + } + + blob->length = i; + + return true; +} + +/* write an object ID to a ASN1 buffer */ +bool asn1_write_OID(struct asn1_data *data, const char *OID) +{ + DATA_BLOB blob; + + if (!asn1_push_tag(data, ASN1_OID)) return false; + + if (!ber_write_OID_String(&blob, OID)) { + data->has_error = true; + return false; + } + + if (!asn1_write(data, blob.data, blob.length)) { + data->has_error = true; + return false; + } + data_blob_free(&blob); + return asn1_pop_tag(data); +} + +/* write an octet string */ +bool asn1_write_OctetString(struct asn1_data *data, const void *p, size_t length) +{ + asn1_push_tag(data, ASN1_OCTET_STRING); + asn1_write(data, p, length); + asn1_pop_tag(data); + return !data->has_error; +} + +/* write a LDAP string */ +bool asn1_write_LDAPString(struct asn1_data *data, const char *s) +{ + asn1_write(data, s, strlen(s)); + return !data->has_error; +} + +/* write a LDAP string from a DATA_BLOB */ +bool asn1_write_DATA_BLOB_LDAPString(struct asn1_data *data, const DATA_BLOB *s) +{ + asn1_write(data, s->data, s->length); + return !data->has_error; +} + +/* write a general string */ +bool asn1_write_GeneralString(struct asn1_data *data, const char *s) +{ + asn1_push_tag(data, ASN1_GENERAL_STRING); + asn1_write_LDAPString(data, s); + asn1_pop_tag(data); + return !data->has_error; +} + +bool asn1_write_ContextSimple(struct asn1_data *data, uint8_t num, DATA_BLOB *blob) +{ + asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(num)); + asn1_write(data, blob->data, blob->length); + asn1_pop_tag(data); + return !data->has_error; +} + +/* write a BOOLEAN */ +bool asn1_write_BOOLEAN(struct asn1_data *data, bool v) +{ + asn1_push_tag(data, ASN1_BOOLEAN); + asn1_write_uint8(data, v ? 0xFF : 0); + asn1_pop_tag(data); + return !data->has_error; +} + +bool asn1_read_BOOLEAN(struct asn1_data *data, bool *v) +{ + uint8_t tmp = 0; + asn1_start_tag(data, ASN1_BOOLEAN); + asn1_read_uint8(data, &tmp); + if (tmp == 0xFF) { + *v = true; + } else { + *v = false; + } + asn1_end_tag(data); + return !data->has_error; +} + +/* check a BOOLEAN */ +bool asn1_check_BOOLEAN(struct asn1_data *data, bool v) +{ + uint8_t b = 0; + + asn1_read_uint8(data, &b); + if (b != ASN1_BOOLEAN) { + data->has_error = true; + return false; + } + asn1_read_uint8(data, &b); + if (b != v) { + data->has_error = true; + return false; + } + return !data->has_error; +} + + +/* load a struct asn1_data structure with a lump of data, ready to be parsed */ +bool asn1_load(struct asn1_data *data, DATA_BLOB blob) +{ + ZERO_STRUCTP(data); + data->data = talloc_memdup(data, blob.data, blob.length); + if (!data->data) { + data->has_error = true; + return false; + } + data->length = blob.length; + return true; +} + +/* Peek into an ASN1 buffer, not advancing the pointer */ +bool asn1_peek(struct asn1_data *data, void *p, int len) +{ + if (data->has_error) + return false; + + if (len < 0 || data->ofs + len < data->ofs || data->ofs + len < len) + return false; + + if (data->ofs + len > data->length) { + /* we need to mark the buffer as consumed, so the caller knows + this was an out of data error, and not a decode error */ + data->ofs = data->length; + return false; + } + + memcpy(p, data->data + data->ofs, len); + return true; +} + +/* read from a ASN1 buffer, advancing the buffer pointer */ +bool asn1_read(struct asn1_data *data, void *p, int len) +{ + if (!asn1_peek(data, p, len)) { + data->has_error = true; + return false; + } + + data->ofs += len; + return true; +} + +/* read a uint8_t from a ASN1 buffer */ +bool asn1_read_uint8(struct asn1_data *data, uint8_t *v) +{ + return asn1_read(data, v, 1); +} + +bool asn1_peek_uint8(struct asn1_data *data, uint8_t *v) +{ + return asn1_peek(data, v, 1); +} + +bool asn1_peek_tag(struct asn1_data *data, uint8_t tag) +{ + uint8_t b; + + if (asn1_tag_remaining(data) <= 0) { + return false; + } + + if (!asn1_peek_uint8(data, &b)) + return false; + + return (b == tag); +} + +/* start reading a nested asn1 structure */ +bool asn1_start_tag(struct asn1_data *data, uint8_t tag) +{ + uint8_t b; + struct nesting *nesting; + + if (!asn1_read_uint8(data, &b)) + return false; + + if (b != tag) { + data->has_error = true; + return false; + } + nesting = talloc(data, struct nesting); + if (!nesting) { + data->has_error = true; + return false; + } + + if (!asn1_read_uint8(data, &b)) { + return false; + } + + if (b & 0x80) { + int n = b & 0x7f; + if (!asn1_read_uint8(data, &b)) + return false; + nesting->taglen = b; + while (n > 1) { + if (!asn1_read_uint8(data, &b)) + return false; + nesting->taglen = (nesting->taglen << 8) | b; + n--; + } + } else { + nesting->taglen = b; + } + nesting->start = data->ofs; + nesting->next = data->nesting; + data->nesting = nesting; + if (asn1_tag_remaining(data) == -1) { + return false; + } + return !data->has_error; +} + +/* stop reading a tag */ +bool asn1_end_tag(struct asn1_data *data) +{ + struct nesting *nesting; + + /* make sure we read it all */ + if (asn1_tag_remaining(data) != 0) { + data->has_error = true; + return false; + } + + nesting = data->nesting; + + if (!nesting) { + data->has_error = true; + return false; + } + + data->nesting = nesting->next; + talloc_free(nesting); + return true; +} + +/* work out how many bytes are left in this nested tag */ +int asn1_tag_remaining(struct asn1_data *data) +{ + int remaining; + if (data->has_error) { + return -1; + } + + if (!data->nesting) { + data->has_error = true; + return -1; + } + remaining = data->nesting->taglen - (data->ofs - data->nesting->start); + if (remaining > (data->length - data->ofs)) { + data->has_error = true; + return -1; + } + return remaining; +} + +/* read an object ID from a data blob */ +bool ber_read_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, const char **OID) +{ + int i; + uint8_t *b; + uint_t v; + char *tmp_oid = NULL; + + if (blob.length < 2) return false; + + b = blob.data; + + tmp_oid = talloc_asprintf(mem_ctx, "%u", b[0]/40); + if (!tmp_oid) goto nomem; + tmp_oid = talloc_asprintf_append_buffer(tmp_oid, ".%u", b[0]%40); + if (!tmp_oid) goto nomem; + + for(i = 1, v = 0; i < blob.length; i++) { + v = (v<<7) | (b[i]&0x7f); + if ( ! (b[i] & 0x80)) { + tmp_oid = talloc_asprintf_append_buffer(tmp_oid, ".%u", v); + v = 0; + } + if (!tmp_oid) goto nomem; + } + + if (v != 0) { + talloc_free(tmp_oid); + return false; + } + + *OID = tmp_oid; + return true; + +nomem: + return false; +} + +/* read an object ID from a ASN1 buffer */ +bool asn1_read_OID(struct asn1_data *data, TALLOC_CTX *mem_ctx, const char **OID) +{ + DATA_BLOB blob; + int len; + + if (!asn1_start_tag(data, ASN1_OID)) return false; + + len = asn1_tag_remaining(data); + if (len < 0) { + data->has_error = true; + return false; + } + + blob = data_blob(NULL, len); + if (!blob.data) { + data->has_error = true; + return false; + } + + asn1_read(data, blob.data, len); + asn1_end_tag(data); + if (data->has_error) { + data_blob_free(&blob); + return false; + } + + if (!ber_read_OID_String(mem_ctx, blob, OID)) { + data->has_error = true; + data_blob_free(&blob); + return false; + } + + data_blob_free(&blob); + return true; +} + +/* check that the next object ID is correct */ +bool asn1_check_OID(struct asn1_data *data, const char *OID) +{ + const char *id; + + if (!asn1_read_OID(data, data, &id)) return false; + + if (strcmp(id, OID) != 0) { + talloc_free(discard_const(id)); + data->has_error = true; + return false; + } + talloc_free(discard_const(id)); + return true; +} + +/* read a LDAPString from a ASN1 buffer */ +bool asn1_read_LDAPString(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **s) +{ + int len; + len = asn1_tag_remaining(data); + if (len < 0) { + data->has_error = true; + return false; + } + *s = talloc_array(mem_ctx, char, len+1); + if (! *s) { + data->has_error = true; + return false; + } + asn1_read(data, *s, len); + (*s)[len] = 0; + return !data->has_error; +} + + +/* read a GeneralString from a ASN1 buffer */ +bool asn1_read_GeneralString(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **s) +{ + if (!asn1_start_tag(data, ASN1_GENERAL_STRING)) return false; + if (!asn1_read_LDAPString(data, mem_ctx, s)) return false; + return asn1_end_tag(data); +} + + +/* read a octet string blob */ +bool asn1_read_OctetString(struct asn1_data *data, TALLOC_CTX *mem_ctx, DATA_BLOB *blob) +{ + int len; + ZERO_STRUCTP(blob); + if (!asn1_start_tag(data, ASN1_OCTET_STRING)) return false; + len = asn1_tag_remaining(data); + if (len < 0) { + data->has_error = true; + return false; + } + *blob = data_blob_talloc(mem_ctx, NULL, len+1); + if (!blob->data) { + data->has_error = true; + return false; + } + asn1_read(data, blob->data, len); + asn1_end_tag(data); + blob->length--; + blob->data[len] = 0; + + if (data->has_error) { + data_blob_free(blob); + *blob = data_blob(NULL, 0); + return false; + } + return true; +} + +bool asn1_read_ContextSimple(struct asn1_data *data, uint8_t num, DATA_BLOB *blob) +{ + int len; + ZERO_STRUCTP(blob); + if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(num))) return false; + len = asn1_tag_remaining(data); + if (len < 0) { + data->has_error = true; + return false; + } + *blob = data_blob(NULL, len); + if ((len != 0) && (!blob->data)) { + data->has_error = true; + return false; + } + asn1_read(data, blob->data, len); + asn1_end_tag(data); + return !data->has_error; +} + +/* read an integer without tag*/ +bool asn1_read_implicit_Integer(struct asn1_data *data, int *i) +{ + uint8_t b; + *i = 0; + + while (!data->has_error && asn1_tag_remaining(data)>0) { + if (!asn1_read_uint8(data, &b)) return false; + *i = (*i << 8) + b; + } + return !data->has_error; + +} + +/* read an integer */ +bool asn1_read_Integer(struct asn1_data *data, int *i) +{ + *i = 0; + + if (!asn1_start_tag(data, ASN1_INTEGER)) return false; + if (!asn1_read_implicit_Integer(data, i)) return false; + return asn1_end_tag(data); +} + +/* read an integer */ +bool asn1_read_enumerated(struct asn1_data *data, int *v) +{ + *v = 0; + + if (!asn1_start_tag(data, ASN1_ENUMERATED)) return false; + while (!data->has_error && asn1_tag_remaining(data)>0) { + uint8_t b; + asn1_read_uint8(data, &b); + *v = (*v << 8) + b; + } + return asn1_end_tag(data); +} + +/* check a enumerated value is correct */ +bool asn1_check_enumerated(struct asn1_data *data, int v) +{ + uint8_t b; + if (!asn1_start_tag(data, ASN1_ENUMERATED)) return false; + asn1_read_uint8(data, &b); + asn1_end_tag(data); + + if (v != b) + data->has_error = false; + + return !data->has_error; +} + +/* write an enumerated value to the stream */ +bool asn1_write_enumerated(struct asn1_data *data, uint8_t v) +{ + if (!asn1_push_tag(data, ASN1_ENUMERATED)) return false; + asn1_write_uint8(data, v); + asn1_pop_tag(data); + return !data->has_error; +} + +/* + check if a ASN.1 blob is a full tag +*/ +NTSTATUS asn1_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size) +{ + struct asn1_data *asn1 = asn1_init(NULL); + int size; + + NT_STATUS_HAVE_NO_MEMORY(asn1); + + asn1->data = blob.data; + asn1->length = blob.length; + asn1_start_tag(asn1, tag); + if (asn1->has_error) { + talloc_free(asn1); + return STATUS_MORE_ENTRIES; + } + size = asn1_tag_remaining(asn1) + asn1->ofs; + + talloc_free(asn1); + + if (size > blob.length) { + return STATUS_MORE_ENTRIES; + } + + *packet_size = size; + return NT_STATUS_OK; +} diff --git a/lib/util/asn1.h b/lib/util/asn1.h new file mode 100644 index 0000000000..34aa1e2cb9 --- /dev/null +++ b/lib/util/asn1.h @@ -0,0 +1,54 @@ +/* + Unix SMB/CIFS implementation. + simple ASN1 code + Copyright (C) Andrew Tridgell 2001 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _ASN_1_H +#define _ASN_1_H + +struct nesting { + off_t start; + size_t taglen; /* for parsing */ + struct nesting *next; +}; + +struct asn1_data { + uint8_t *data; + size_t length; + off_t ofs; + struct nesting *nesting; + bool has_error; +}; + +#define ASN1_APPLICATION(x) ((x)+0x60) +#define ASN1_APPLICATION_SIMPLE(x) ((x)+0x40) +#define ASN1_SEQUENCE(x) ((x)+0x30) +#define ASN1_CONTEXT(x) ((x)+0xa0) +#define ASN1_CONTEXT_SIMPLE(x) ((x)+0x80) +#define ASN1_GENERAL_STRING 0x1b +#define ASN1_OCTET_STRING 0x4 +#define ASN1_OID 0x6 +#define ASN1_BOOLEAN 0x1 +#define ASN1_INTEGER 0x2 +#define ASN1_ENUMERATED 0xa +#define ASN1_SET 0x31 + +#define ASN1_MAX_OIDS 20 + +#include "lib/util/asn1_proto.h" + +#endif /* _ASN_1_H */ diff --git a/lib/util/attr.h b/lib/util/attr.h new file mode 100644 index 0000000000..f64b272a67 --- /dev/null +++ b/lib/util/attr.h @@ -0,0 +1,90 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Jelmer Vernooij 2007 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef __UTIL_ATTR_H__ +#define __UTIL_ATTR_H__ + +#ifdef __GNUC__ +/** gcc attribute used on function parameters so that it does not emit + * warnings about them being unused. **/ +# define UNUSED(param) param __attribute__ ((unused)) +#else +# define UNUSED(param) param +/** Feel free to add definitions for other compilers here. */ +#endif + +#ifdef HAVE_VISIBILITY_ATTR +# define _PUBLIC_ __attribute__((visibility("default"))) +#else +# define _PUBLIC_ +#endif + +#ifndef _DEPRECATED_ +#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 ) +#define _DEPRECATED_ __attribute__ ((deprecated)) +#else +#define _DEPRECATED_ +#endif +#endif + +#ifndef _WARN_UNUSED_RESULT_ +#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 ) +#define _WARN_UNUSED_RESULT_ __attribute__ ((warn_unused_result)) +#else +#define _WARN_UNUSED_RESULT_ +#endif +#endif + +#ifndef _NORETURN_ +#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 ) +#define _NORETURN_ __attribute__ ((noreturn)) +#else +#define _NORETURN_ +#endif +#endif + +#ifndef _PURE_ +#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1) +#define _PURE_ __attribute__((pure)) +#else +#define _PURE_ +#endif +#endif + +#ifndef NONNULL +#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1) +#define NONNULL(param) param __attribute__((nonnull)) +#else +#define NONNULL(param) param +#endif +#endif + +#ifndef PRINTF_ATTRIBUTE +#if __GNUC__ >= 3 +/** Use gcc attribute to check printf fns. a1 is the 1-based index of + * the parameter containing the format, and a2 the index of the first + * argument. Note that some gcc 2.x versions don't handle this + * properly **/ +#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) +#else +#define PRINTF_ATTRIBUTE(a1, a2) +#endif +#endif + +#endif /* __UTIL_ATTR_H__ */ diff --git a/lib/util/become_daemon.c b/lib/util/become_daemon.c new file mode 100644 index 0000000000..034114eade --- /dev/null +++ b/lib/util/become_daemon.c @@ -0,0 +1,93 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 2001-2002 + Copyright (C) Simo Sorce 2001 + Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003. + Copyright (C) James J Myers 2003 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "system/filesys.h" +#include "system/locale.h" + +/******************************************************************* + Close the low 3 fd's and open dev/null in their place. +********************************************************************/ +static void close_low_fds(bool stderr_too) +{ +#ifndef VALGRIND + int fd; + int i; + + close(0); + close(1); + + if (stderr_too) + close(2); + + /* try and use up these file descriptors, so silly + library routines writing to stdout etc won't cause havoc */ + for (i=0;i<3;i++) { + if (i == 2 && !stderr_too) + continue; + + fd = open("/dev/null",O_RDWR,0); + if (fd < 0) + fd = open("/dev/null",O_WRONLY,0); + if (fd < 0) { + DEBUG(0,("Can't open /dev/null\n")); + return; + } + if (fd != i) { + DEBUG(0,("Didn't get file descriptor %d\n",i)); + return; + } + } +#endif +} + +/** + Become a daemon, discarding the controlling terminal. +**/ + +_PUBLIC_ void become_daemon(bool Fork) +{ + if (Fork) { + if (fork()) { + _exit(0); + } + } + + /* detach from the terminal */ +#ifdef HAVE_SETSID + setsid(); +#elif defined(TIOCNOTTY) + { + int i = open("/dev/tty", O_RDWR, 0); + if (i != -1) { + ioctl(i, (int) TIOCNOTTY, (char *)0); + close(i); + } + } +#endif /* HAVE_SETSID */ + + /* Close fd's 0,1,2. Needed if started by rsh */ + close_low_fds(false); /* Don't close stderr, let the debug system + attach it to the logfile */ +} + diff --git a/lib/util/byteorder.h b/lib/util/byteorder.h new file mode 100644 index 0000000000..894beccabf --- /dev/null +++ b/lib/util/byteorder.h @@ -0,0 +1,231 @@ +/* + Unix SMB/CIFS implementation. + SMB Byte handling + Copyright (C) Andrew Tridgell 1992-1998 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _BYTEORDER_H +#define _BYTEORDER_H + +/* + This file implements macros for machine independent short and + int manipulation + +Here is a description of this file that I emailed to the samba list once: + +> I am confused about the way that byteorder.h works in Samba. I have +> looked at it, and I would have thought that you might make a distinction +> between LE and BE machines, but you only seem to distinguish between 386 +> and all other architectures. +> +> Can you give me a clue? + +sure. + +The distinction between 386 and other architectures is only there as +an optimisation. You can take it out completely and it will make no +difference. The routines (macros) in byteorder.h are totally byteorder +independent. The 386 optimsation just takes advantage of the fact that +the x86 processors don't care about alignment, so we don't have to +align ints on int boundaries etc. If there are other processors out +there that aren't alignment sensitive then you could also define +CAREFUL_ALIGNMENT=0 on those processors as well. + +Ok, now to the macros themselves. I'll take a simple example, say we +want to extract a 2 byte integer from a SMB packet and put it into a +type called uint16_t that is in the local machines byte order, and you +want to do it with only the assumption that uint16_t is _at_least_ 16 +bits long (this last condition is very important for architectures +that don't have any int types that are 2 bytes long) + +You do this: + +#define CVAL(buf,pos) (((uint8_t *)(buf))[pos]) +#define PVAL(buf,pos) ((uint_t)CVAL(buf,pos)) +#define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8) + +then to extract a uint16_t value at offset 25 in a buffer you do this: + +char *buffer = foo_bar(); +uint16_t xx = SVAL(buffer,25); + +We are using the byteoder independence of the ANSI C bitshifts to do +the work. A good optimising compiler should turn this into efficient +code, especially if it happens to have the right byteorder :-) + +I know these macros can be made a bit tidier by removing some of the +casts, but you need to look at byteorder.h as a whole to see the +reasoning behind them. byteorder.h defines the following macros: + +SVAL(buf,pos) - extract a 2 byte SMB value +IVAL(buf,pos) - extract a 4 byte SMB value +BVAL(buf,pos) - extract a 8 byte SMB value +SVALS(buf,pos) - signed version of SVAL() +IVALS(buf,pos) - signed version of IVAL() +BVALS(buf,pos) - signed version of BVAL() + +SSVAL(buf,pos,val) - put a 2 byte SMB value into a buffer +SIVAL(buf,pos,val) - put a 4 byte SMB value into a buffer +SBVAL(buf,pos,val) - put a 8 byte SMB value into a buffer +SSVALS(buf,pos,val) - signed version of SSVAL() +SIVALS(buf,pos,val) - signed version of SIVAL() +SBVALS(buf,pos,val) - signed version of SBVAL() + +RSVAL(buf,pos) - like SVAL() but for NMB byte ordering +RSVALS(buf,pos) - like SVALS() but for NMB byte ordering +RIVAL(buf,pos) - like IVAL() but for NMB byte ordering +RIVALS(buf,pos) - like IVALS() but for NMB byte ordering +RSSVAL(buf,pos,val) - like SSVAL() but for NMB ordering +RSIVAL(buf,pos,val) - like SIVAL() but for NMB ordering +RSIVALS(buf,pos,val) - like SIVALS() but for NMB ordering + +it also defines lots of intermediate macros, just ignore those :-) + +*/ + + +/* + on powerpc we can use the magic instructions to load/store + in little endian +*/ +#if (defined(__powerpc__) && defined(__GNUC__)) +static __inline__ uint16_t ld_le16(const uint16_t *addr) +{ + uint16_t val; + __asm__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr)); + return val; +} + +static __inline__ void st_le16(uint16_t *addr, const uint16_t val) +{ + __asm__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr)); +} + +static __inline__ uint32_t ld_le32(const uint32_t *addr) +{ + uint32_t val; + __asm__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr)); + return val; +} + +static __inline__ void st_le32(uint32_t *addr, const uint32_t val) +{ + __asm__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr)); +} +#define HAVE_ASM_BYTEORDER 1 +#else +#define HAVE_ASM_BYTEORDER 0 +#endif + + + +#undef CAREFUL_ALIGNMENT + +/* we know that the 386 can handle misalignment and has the "right" + byteorder */ +#if defined(__i386__) +#define CAREFUL_ALIGNMENT 0 +#endif + +#ifndef CAREFUL_ALIGNMENT +#define CAREFUL_ALIGNMENT 1 +#endif + +#define CVAL(buf,pos) ((uint_t)(((const uint8_t *)(buf))[pos])) +#define CVAL_NC(buf,pos) (((uint8_t *)(buf))[pos]) /* Non-const version of CVAL */ +#define PVAL(buf,pos) (CVAL(buf,pos)) +#define SCVAL(buf,pos,val) (CVAL_NC(buf,pos) = (val)) + +#if HAVE_ASM_BYTEORDER + +#define _PTRPOS(buf,pos) (((const uint8_t *)buf)+(pos)) +#define SVAL(buf,pos) ld_le16((const uint16_t *)_PTRPOS(buf,pos)) +#define IVAL(buf,pos) ld_le32((const uint32_t *)_PTRPOS(buf,pos)) +#define SSVAL(buf,pos,val) st_le16((uint16_t *)_PTRPOS(buf,pos), val) +#define SIVAL(buf,pos,val) st_le32((uint32_t *)_PTRPOS(buf,pos), val) +#define SVALS(buf,pos) ((int16_t)SVAL(buf,pos)) +#define IVALS(buf,pos) ((int32_t)IVAL(buf,pos)) +#define SSVALS(buf,pos,val) SSVAL((buf),(pos),((int16_t)(val))) +#define SIVALS(buf,pos,val) SIVAL((buf),(pos),((int32_t)(val))) + +#elif CAREFUL_ALIGNMENT + +#define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8) +#define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16) +#define SSVALX(buf,pos,val) (CVAL_NC(buf,pos)=(uint8_t)((val)&0xFF),CVAL_NC(buf,pos+1)=(uint8_t)((val)>>8)) +#define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16)) +#define SVALS(buf,pos) ((int16_t)SVAL(buf,pos)) +#define IVALS(buf,pos) ((int32_t)IVAL(buf,pos)) +#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((uint16_t)(val))) +#define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32_t)(val))) +#define SSVALS(buf,pos,val) SSVALX((buf),(pos),((int16_t)(val))) +#define SIVALS(buf,pos,val) SIVALX((buf),(pos),((int32_t)(val))) + +#else /* not CAREFUL_ALIGNMENT */ + +/* this handles things for architectures like the 386 that can handle + alignment errors */ +/* + WARNING: This section is dependent on the length of int16_t and int32_t + being correct +*/ + +/* get single value from an SMB buffer */ +#define SVAL(buf,pos) (*(const uint16_t *)((const char *)(buf) + (pos))) +#define SVAL_NC(buf,pos) (*(uint16_t *)((char *)(buf) + (pos))) /* Non const version of above. */ +#define IVAL(buf,pos) (*(const uint32_t *)((const char *)(buf) + (pos))) +#define IVAL_NC(buf,pos) (*(uint32_t *)((char *)(buf) + (pos))) /* Non const version of above. */ +#define SVALS(buf,pos) (*(const int16_t *)((const char *)(buf) + (pos))) +#define SVALS_NC(buf,pos) (*(int16_t *)((char *)(buf) + (pos))) /* Non const version of above. */ +#define IVALS(buf,pos) (*(const int32_t *)((const char *)(buf) + (pos))) +#define IVALS_NC(buf,pos) (*(int32_t *)((char *)(buf) + (pos))) /* Non const version of above. */ + +/* store single value in an SMB buffer */ +#define SSVAL(buf,pos,val) SVAL_NC(buf,pos)=((uint16_t)(val)) +#define SIVAL(buf,pos,val) IVAL_NC(buf,pos)=((uint32_t)(val)) +#define SSVALS(buf,pos,val) SVALS_NC(buf,pos)=((int16_t)(val)) +#define SIVALS(buf,pos,val) IVALS_NC(buf,pos)=((int32_t)(val)) + +#endif /* not CAREFUL_ALIGNMENT */ + +/* now the reverse routines - these are used in nmb packets (mostly) */ +#define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF)) +#define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16))) + +#define RSVAL(buf,pos) SREV(SVAL(buf,pos)) +#define RSVALS(buf,pos) SREV(SVALS(buf,pos)) +#define RIVAL(buf,pos) IREV(IVAL(buf,pos)) +#define RIVALS(buf,pos) IREV(IVALS(buf,pos)) +#define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val)) +#define RSSVALS(buf,pos,val) SSVALS(buf,pos,SREV(val)) +#define RSIVAL(buf,pos,val) SIVAL(buf,pos,IREV(val)) +#define RSIVALS(buf,pos,val) SIVALS(buf,pos,IREV(val)) + +/* Alignment macros. */ +#define ALIGN4(p,base) ((p) + ((4 - (PTR_DIFF((p), (base)) & 3)) & 3)) +#define ALIGN2(p,base) ((p) + ((2 - (PTR_DIFF((p), (base)) & 1)) & 1)) + + +/* macros for accessing SMB protocol elements */ +#define VWV(vwv) ((vwv)*2) + +/* 64 bit macros */ +#define BVAL(p, ofs) (IVAL(p,ofs) | (((uint64_t)IVAL(p,(ofs)+4)) << 32)) +#define BVALS(p, ofs) ((int64_t)BVAL(p,ofs)) +#define SBVAL(p, ofs, v) (SIVAL(p,ofs,(v)&0xFFFFFFFF), SIVAL(p,(ofs)+4,((uint64_t)(v))>>32)) +#define SBVALS(p, ofs, v) (SBVAL(p,ofs,(uint64_t)v)) + +#endif /* _BYTEORDER_H */ diff --git a/lib/util/capability.c b/lib/util/capability.c new file mode 100644 index 0000000000..2d13826c14 --- /dev/null +++ b/lib/util/capability.c @@ -0,0 +1,103 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 1998-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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file + * @brief Capabilities functions + **/ + +/* + capabilities fns - will be needed when we enable kernel oplocks +*/ + +#include "includes.h" +#include "system/network.h" +#include "system/wait.h" +#include "system/filesys.h" + + +#if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES) +/************************************************************************** + Try and abstract process capabilities (for systems that have them). +****************************************************************************/ +static bool set_process_capability( uint32_t cap_flag, bool enable ) +{ + if(cap_flag == KERNEL_OPLOCK_CAPABILITY) { + cap_t cap = cap_get_proc(); + + if (cap == NULL) { + DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n", + strerror(errno))); + return false; + } + + if(enable) + cap->cap_effective |= CAP_NETWORK_MGT; + else + cap->cap_effective &= ~CAP_NETWORK_MGT; + + if (cap_set_proc(cap) == -1) { + DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n", + strerror(errno))); + cap_free(cap); + return false; + } + + cap_free(cap); + + DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n")); + } + return true; +} + +/************************************************************************** + Try and abstract inherited process capabilities (for systems that have them). +****************************************************************************/ + +static bool set_inherited_process_capability( uint32_t cap_flag, bool enable ) +{ + if(cap_flag == KERNEL_OPLOCK_CAPABILITY) { + cap_t cap = cap_get_proc(); + + if (cap == NULL) { + DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n", + strerror(errno))); + return false; + } + + if(enable) + cap->cap_inheritable |= CAP_NETWORK_MGT; + else + cap->cap_inheritable &= ~CAP_NETWORK_MGT; + + if (cap_set_proc(cap) == -1) { + DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n", + strerror(errno))); + cap_free(cap); + return false; + } + + cap_free(cap); + + DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n")); + } + return true; +} +#endif diff --git a/lib/util/capability.m4 b/lib/util/capability.m4 new file mode 100644 index 0000000000..2a95a607d5 --- /dev/null +++ b/lib/util/capability.m4 @@ -0,0 +1,17 @@ +AC_CACHE_CHECK([for irix specific capabilities],samba_cv_HAVE_IRIX_SPECIFIC_CAPABILITIES,[ +AC_TRY_RUN([#include +#include +main() { + cap_t cap; + if ((cap = cap_get_proc()) == NULL) + exit(1); + cap->cap_effective |= CAP_NETWORK_MGT; + cap->cap_inheritable |= CAP_NETWORK_MGT; + cap_set_proc(cap); + exit(0); +} +], +samba_cv_HAVE_IRIX_SPECIFIC_CAPABILITIES=yes,samba_cv_HAVE_IRIX_SPECIFIC_CAPABILITIES=no,samba_cv_HAVE_IRIX_SPECIFIC_CAPABILITIES=cross)]) +if test x"$samba_cv_HAVE_IRIX_SPECIFIC_CAPABILITIES" = x"yes"; then + AC_DEFINE(HAVE_IRIX_SPECIFIC_CAPABILITIES,1,[Whether IRIX specific capabilities are available]) +fi diff --git a/lib/util/config.mk b/lib/util/config.mk new file mode 100644 index 0000000000..925713a53c --- /dev/null +++ b/lib/util/config.mk @@ -0,0 +1,71 @@ +[SUBSYSTEM::LIBSAMBA-UTIL] +PUBLIC_DEPENDENCIES = \ + LIBTALLOC LIBCRYPTO \ + SOCKET_WRAPPER LIBREPLACE_NETWORK \ + CHARSET EXECINFO + +LIBSAMBA-UTIL_OBJ_FILES = $(addprefix $(libutilsrcdir)/, \ + xfile.o \ + debug.o \ + fault.o \ + signal.o \ + system.o \ + time.o \ + genrand.o \ + dprintf.o \ + util_str.o \ + util_strlist.o \ + util_file.o \ + data_blob.o \ + util.o \ + fsusage.o \ + ms_fnmatch.o \ + mutex.o \ + idtree.o \ + become_daemon.o \ + params.o) + +PUBLIC_HEADERS += $(addprefix $(libutilsrcdir)/, util.h \ + attr.h \ + byteorder.h \ + data_blob.h \ + debug.h \ + mutex.h \ + safe_string.h \ + time.h \ + util_ldb.h \ + xfile.h) + +[SUBSYSTEM::ASN1_UTIL] + +ASN1_UTIL_OBJ_FILES = $(libutilsrcdir)/asn1.o + +$(eval $(call proto_header_template,$(libutilsrcdir)/asn1_proto.h,$(ASN1_UTIL_OBJ_FILES:.o=.c))) + +[SUBSYSTEM::UNIX_PRIVS] + +UNIX_PRIVS_OBJ_FILES = $(libutilsrcdir)/unix_privs.o + +$(eval $(call proto_header_template,$(libutilsrcdir)/unix_privs.h,$(UNIX_PRIVS_OBJ_FILES:.o=.c))) + +################################################ +# Start SUBSYSTEM WRAP_XATTR +[SUBSYSTEM::WRAP_XATTR] +PUBLIC_DEPENDENCIES = XATTR +# +# End SUBSYSTEM WRAP_XATTR +################################################ + +WRAP_XATTR_OBJ_FILES = $(libutilsrcdir)/wrap_xattr.o + +[SUBSYSTEM::UTIL_TDB] +PUBLIC_DEPENDENCIES = LIBTDB + +UTIL_TDB_OBJ_FILES = $(libutilsrcdir)/util_tdb.o + +$(eval $(call proto_header_template,$(libutilsrcdir)/util_tdb.h,$(UTIL_TDB_OBJ_FILES:.o=.c))) + +[SUBSYSTEM::UTIL_LDB] +PUBLIC_DEPENDENCIES = LIBLDB + +UTIL_LDB_OBJ_FILES = $(libutilsrcdir)/util_ldb.o diff --git a/lib/util/data_blob.c b/lib/util/data_blob.c new file mode 100644 index 0000000000..57b34b7ae7 --- /dev/null +++ b/lib/util/data_blob.c @@ -0,0 +1,232 @@ +/* + Unix SMB/CIFS implementation. + Easy management of byte-length data + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Andrew Bartlett 2001 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" + +/** + * @file + * @brief Manipulation of arbitrary data blobs + **/ + +/** + construct a data blob, must be freed with data_blob_free() + you can pass NULL for p and get a blank data blob +**/ +_PUBLIC_ DATA_BLOB data_blob_named(const void *p, size_t length, const char *name) +{ + DATA_BLOB ret; + + if (p == NULL && length == 0) { + ZERO_STRUCT(ret); + return ret; + } + + if (p) { + ret.data = (uint8_t *)talloc_memdup(NULL, p, length); + } else { + ret.data = talloc_array(NULL, uint8_t, length); + } + if (ret.data == NULL) { + ret.length = 0; + return ret; + } + talloc_set_name_const(ret.data, name); + ret.length = length; + return ret; +} + +/** + construct a data blob, using supplied TALLOC_CTX +**/ +_PUBLIC_ DATA_BLOB data_blob_talloc_named(TALLOC_CTX *mem_ctx, const void *p, size_t length, const char *name) +{ + DATA_BLOB ret = data_blob_named(p, length, name); + + if (ret.data) { + talloc_steal(mem_ctx, ret.data); + } + return ret; +} + + +/** + reference a data blob, to the supplied TALLOC_CTX. + Returns a NULL DATA_BLOB on failure +**/ +_PUBLIC_ DATA_BLOB data_blob_talloc_reference(TALLOC_CTX *mem_ctx, DATA_BLOB *blob) +{ + DATA_BLOB ret = *blob; + + ret.data = talloc_reference(mem_ctx, blob->data); + + if (!ret.data) { + return data_blob(NULL, 0); + } + return ret; +} + +/** + construct a zero data blob, using supplied TALLOC_CTX. + use this sparingly as it initialises data - better to initialise + yourself if you want specific data in the blob +**/ +_PUBLIC_ DATA_BLOB data_blob_talloc_zero(TALLOC_CTX *mem_ctx, size_t length) +{ + DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, length); + data_blob_clear(&blob); + return blob; +} + +/** +free a data blob +**/ +_PUBLIC_ void data_blob_free(DATA_BLOB *d) +{ + if (d) { + talloc_free(d->data); + d->data = NULL; + d->length = 0; + } +} + +/** +clear a DATA_BLOB's contents +**/ +_PUBLIC_ void data_blob_clear(DATA_BLOB *d) +{ + if (d->data) { + memset(d->data, 0, d->length); + } +} + +/** +free a data blob and clear its contents +**/ +_PUBLIC_ void data_blob_clear_free(DATA_BLOB *d) +{ + data_blob_clear(d); + data_blob_free(d); +} + + +/** +check if two data blobs are equal +**/ +_PUBLIC_ int data_blob_cmp(const DATA_BLOB *d1, const DATA_BLOB *d2) +{ + int ret; + if (d1->data == NULL && d2->data != NULL) { + return -1; + } + if (d1->data != NULL && d2->data == NULL) { + return 1; + } + if (d1->data == d2->data) { + return d1->length - d2->length; + } + ret = memcmp(d1->data, d2->data, MIN(d1->length, d2->length)); + if (ret == 0) { + return d1->length - d2->length; + } + return ret; +} + +/** +print the data_blob as hex string +**/ +_PUBLIC_ char *data_blob_hex_string(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob) +{ + int i; + char *hex_string; + + hex_string = talloc_array(mem_ctx, char, (blob->length*2)+1); + if (!hex_string) { + return NULL; + } + + for (i = 0; i < blob->length; i++) + slprintf(&hex_string[i*2], 3, "%02X", blob->data[i]); + + hex_string[(blob->length*2)] = '\0'; + return hex_string; +} + +/** + useful for constructing data blobs in test suites, while + avoiding const warnings +**/ +_PUBLIC_ DATA_BLOB data_blob_string_const(const char *str) +{ + DATA_BLOB blob; + blob.data = discard_const_p(uint8_t, str); + blob.length = str ? strlen(str) : 0; + return blob; +} + +/** + * Create a new data blob from const data + */ + +_PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length) +{ + DATA_BLOB blob; + blob.data = discard_const_p(uint8_t, p); + blob.length = length; + return blob; +} + + +/** + realloc a data_blob +**/ +_PUBLIC_ bool data_blob_realloc(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, size_t length) +{ + blob->data = talloc_realloc(mem_ctx, blob->data, uint8_t, length); + if (blob->data == NULL) + return false; + blob->length = length; + return true; +} + + +/** + append some data to a data blob +**/ +_PUBLIC_ bool data_blob_append(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, + const void *p, size_t length) +{ + size_t old_len = blob->length; + size_t new_len = old_len + length; + if (new_len < length || new_len < old_len) { + return false; + } + + if ((const uint8_t *)p + length < (const uint8_t *)p) { + return false; + } + + if (!data_blob_realloc(mem_ctx, blob, new_len)) { + return false; + } + + memcpy(blob->data + old_len, p, length); + return true; +} + diff --git a/lib/util/data_blob.h b/lib/util/data_blob.h new file mode 100644 index 0000000000..e9dca67772 --- /dev/null +++ b/lib/util/data_blob.h @@ -0,0 +1,123 @@ +/* + Unix SMB/CIFS implementation. + DATA BLOB + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* This is a public header file that is installed as part of Samba. + * If you remove any functions or change their signature, update + * the so version number. */ + +#ifndef _SAMBA_DATABLOB_H_ +#define _SAMBA_DATABLOB_H_ + +#ifndef _PUBLIC_ +#define _PUBLIC_ +#endif + +#include +#include + +/* used to hold an arbitrary blob of data */ +typedef struct datablob { + uint8_t *data; + size_t length; +} DATA_BLOB; + +struct data_blob_list_item { + struct data_blob_list_item *prev,*next; + DATA_BLOB blob; +}; + +/* by making struct ldb_val and DATA_BLOB the same, we can simplify + a fair bit of code */ +#define ldb_val datablob + +#define data_blob(ptr, size) data_blob_named(ptr, size, "DATA_BLOB: "__location__) +#define data_blob_talloc(ctx, ptr, size) data_blob_talloc_named(ctx, ptr, size, "DATA_BLOB: "__location__) +#define data_blob_dup_talloc(ctx, blob) data_blob_talloc_named(ctx, (blob)->data, (blob)->length, "DATA_BLOB: "__location__) + +/** + construct a data blob, must be freed with data_blob_free() + you can pass NULL for p and get a blank data blob +**/ +_PUBLIC_ DATA_BLOB data_blob_named(const void *p, size_t length, const char *name); + +/** + construct a data blob, using supplied TALLOC_CTX +**/ +_PUBLIC_ DATA_BLOB data_blob_talloc_named(TALLOC_CTX *mem_ctx, const void *p, size_t length, const char *name); + +/** + reference a data blob, to the supplied TALLOC_CTX. + Returns a NULL DATA_BLOB on failure +**/ +_PUBLIC_ DATA_BLOB data_blob_talloc_reference(TALLOC_CTX *mem_ctx, DATA_BLOB *blob); + +/** + construct a zero data blob, using supplied TALLOC_CTX. + use this sparingly as it initialises data - better to initialise + yourself if you want specific data in the blob +**/ +_PUBLIC_ DATA_BLOB data_blob_talloc_zero(TALLOC_CTX *mem_ctx, size_t length); + +/** +free a data blob +**/ +_PUBLIC_ void data_blob_free(DATA_BLOB *d); + +/** +clear a DATA_BLOB's contents +**/ +_PUBLIC_ void data_blob_clear(DATA_BLOB *d); + +/** +free a data blob and clear its contents +**/ +_PUBLIC_ void data_blob_clear_free(DATA_BLOB *d); + +/** +check if two data blobs are equal +**/ +_PUBLIC_ int data_blob_cmp(const DATA_BLOB *d1, const DATA_BLOB *d2); + +/** +print the data_blob as hex string +**/ +_PUBLIC_ char *data_blob_hex_string(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob); + +/** + useful for constructing data blobs in test suites, while + avoiding const warnings +**/ +_PUBLIC_ DATA_BLOB data_blob_string_const(const char *str); + +/** + * Create a new data blob from const data + */ +_PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length); + +/** + realloc a data_blob +**/ +_PUBLIC_ bool data_blob_realloc(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, size_t length); + +/** + append some data to a data blob +**/ +_PUBLIC_ bool data_blob_append(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, + const void *p, size_t length); + +#endif /* _SAMBA_DATABLOB_H_ */ diff --git a/lib/util/debug.c b/lib/util/debug.c new file mode 100644 index 0000000000..b6edb908c7 --- /dev/null +++ b/lib/util/debug.c @@ -0,0 +1,248 @@ +/* + Unix SMB/CIFS implementation. + Samba debug functions + Copyright (C) Andrew Tridgell 2003 + Copyright (C) James J Myers 2003 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "system/filesys.h" +#include "system/time.h" +#include "dynconfig/dynconfig.h" + +/** + * @file + * @brief Debug logging + **/ + +/** + * this global variable determines what messages are printed + */ +int _debug_level = 0; +_PUBLIC_ int *debug_level = &_debug_level; +int *DEBUGLEVEL_CLASS = NULL; /* For samba 3 */ + +/* the registered mutex handlers */ +static struct { + const char *name; + struct debug_ops ops; +} debug_handlers; + +/* state variables for the debug system */ +static struct { + int fd; + enum debug_logtype logtype; + const char *prog_name; +} state; + +static bool reopen_logs_scheduled; +static bool check_reopen_logs(void) +{ + if (state.fd == 0 || reopen_logs_scheduled) { + reopen_logs_scheduled = false; + reopen_logs(); + } + + if (state.fd <= 0) + return false; + + return true; +} + +_PUBLIC_ void debug_schedule_reopen_logs(void) +{ + reopen_logs_scheduled = true; +} + +static void log_timestring(int level, const char *location, const char *func) +{ + char *t = NULL; + char *s = NULL; + + if (!check_reopen_logs()) return; + + if (state.logtype != DEBUG_FILE) return; + + t = timestring(NULL, time(NULL)); + if (!t) return; + + asprintf(&s, "[%s, %d %s:%s()]\n", t, level, location, func); + talloc_free(t); + if (!s) return; + + write(state.fd, s, strlen(s)); + free(s); +} + +/** + the backend for debug messages. Note that the DEBUG() macro has already + ensured that the log level has been met before this is called +*/ +_PUBLIC_ void dbghdr(int level, const char *location, const char *func) +{ + log_timestring(level, location, func); + log_task_id(); +} + + +_PUBLIC_ void dbghdrclass(int level, int class, const char *location, const char *func) +{ + /* Simple wrapper, Samba 4 doesn't do debug classes */ + dbghdr(level, location, func); +} + +/** + the backend for debug messages. Note that the DEBUG() macro has already + ensured that the log level has been met before this is called + + @note You should never have to call this function directly. Call the DEBUG() + macro instead. +*/ +_PUBLIC_ void dbgtext(const char *format, ...) +{ + va_list ap; + char *s = NULL; + + if (!check_reopen_logs()) return; + + va_start(ap, format); + vasprintf(&s, format, ap); + va_end(ap); + + write(state.fd, s, strlen(s)); + free(s); +} + +_PUBLIC_ const char *logfile = NULL; + +/** + reopen the log file (usually called because the log file name might have changed) +*/ +_PUBLIC_ void reopen_logs(void) +{ + char *fname = NULL; + int old_fd = state.fd; + + switch (state.logtype) { + case DEBUG_STDOUT: + state.fd = 1; + break; + + case DEBUG_STDERR: + state.fd = 2; + break; + + case DEBUG_FILE: + if (logfile && (*logfile) == '/') { + fname = strdup(logfile); + } else { + asprintf(&fname, "%s/%s.log", dyn_LOGFILEBASE, state.prog_name); + } + if (fname) { + int newfd = open(fname, O_CREAT|O_APPEND|O_WRONLY, 0600); + if (newfd == -1) { + DEBUG(1, ("Failed to open new logfile: %s\n", fname)); + old_fd = -1; + } else { + state.fd = newfd; + } + free(fname); + } else { + DEBUG(1, ("Failed to find name for file-based logfile!\n")); + } + + break; + } + + if (old_fd > 2) { + close(old_fd); + } +} + +/** + control the name of the logfile and whether logging will be to stdout, stderr + or a file +*/ +_PUBLIC_ void setup_logging(const char *prog_name, enum debug_logtype new_logtype) +{ + if (state.logtype < new_logtype) { + state.logtype = new_logtype; + } + if (prog_name) { + state.prog_name = prog_name; + } + reopen_logs(); +} + +/** + return a string constant containing n tabs + no more than 10 tabs are returned +*/ +_PUBLIC_ const char *do_debug_tab(int n) +{ + const char *tabs[] = {"", "\t", "\t\t", "\t\t\t", "\t\t\t\t", "\t\t\t\t\t", + "\t\t\t\t\t\t", "\t\t\t\t\t\t\t", "\t\t\t\t\t\t\t\t", + "\t\t\t\t\t\t\t\t\t", "\t\t\t\t\t\t\t\t\t\t"}; + return tabs[MIN(n, 10)]; +} + + +/** + log suspicious usage - print comments and backtrace +*/ +_PUBLIC_ void log_suspicious_usage(const char *from, const char *info) +{ + if (!debug_handlers.ops.log_suspicious_usage) return; + + debug_handlers.ops.log_suspicious_usage(from, info); +} + + +/** + print suspicious usage - print comments and backtrace +*/ +_PUBLIC_ void print_suspicious_usage(const char* from, const char* info) +{ + if (!debug_handlers.ops.print_suspicious_usage) return; + + debug_handlers.ops.print_suspicious_usage(from, info); +} + +_PUBLIC_ uint32_t get_task_id(void) +{ + if (debug_handlers.ops.get_task_id) { + return debug_handlers.ops.get_task_id(); + } + return getpid(); +} + +_PUBLIC_ void log_task_id(void) +{ + if (!debug_handlers.ops.log_task_id) return; + + if (!check_reopen_logs()) return; + + debug_handlers.ops.log_task_id(state.fd); +} + +/** + register a set of debug handlers. +*/ +_PUBLIC_ void register_debug_handlers(const char *name, struct debug_ops *ops) +{ + debug_handlers.name = name; + debug_handlers.ops = *ops; +} diff --git a/lib/util/debug.h b/lib/util/debug.h new file mode 100644 index 0000000000..8f4fa2a8fc --- /dev/null +++ b/lib/util/debug.h @@ -0,0 +1,129 @@ +/* + Unix SMB/CIFS implementation. + Samba debug defines + Copyright (C) Andrew Tridgell 2003 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file + * @brief Debugging macros + */ + +/* the debug operations structure - contains function pointers to + various debug implementations of each operation */ +struct debug_ops { + /* function to log (using DEBUG) suspicious usage of data structure */ + void (*log_suspicious_usage)(const char* from, const char* info); + + /* function to log (using printf) suspicious usage of data structure. + * To be used in circumstances when using DEBUG would cause loop. */ + void (*print_suspicious_usage)(const char* from, const char* info); + + /* function to return process/thread id */ + uint32_t (*get_task_id)(void); + + /* function to log process/thread id */ + void (*log_task_id)(int fd); +}; + +#define DEBUGLEVEL *debug_level +extern int DEBUGLEVEL; + +#define debug_ctx() (_debug_ctx?_debug_ctx:(_debug_ctx=talloc_new(NULL))) + +#define DEBUGLVL(level) ((level) <= DEBUGLEVEL) +#define _DEBUG(level, body, header) do { \ + if (DEBUGLVL(level)) { \ + void* _debug_ctx=NULL; \ + if (header) { \ + dbghdr(level, __location__, __FUNCTION__); \ + } \ + dbgtext body; \ + talloc_free(_debug_ctx); \ + } \ +} while (0) +/** + * Write to the debug log. + */ +#define DEBUG(level, body) _DEBUG(level, body, true) +/** + * Add data to an existing debug log entry. + */ +#define DEBUGADD(level, body) _DEBUG(level, body, false) + +/** + * Obtain indentation string for the debug log. + * + * Level specified by n. + */ +#define DEBUGTAB(n) do_debug_tab(n) + +/** Possible destinations for the debug log */ +enum debug_logtype {DEBUG_STDOUT = 0, DEBUG_FILE = 1, DEBUG_STDERR = 2}; + +/** + the backend for debug messages. Note that the DEBUG() macro has already + ensured that the log level has been met before this is called +*/ +_PUBLIC_ void dbghdr(int level, const char *location, const char *func); + +/** + reopen the log file (usually called because the log file name might have changed) +*/ +_PUBLIC_ void reopen_logs(void); + +/** + * this global variable determines what messages are printed + */ +_PUBLIC_ void debug_schedule_reopen_logs(void); + +/** + control the name of the logfile and whether logging will be to stdout, stderr + or a file +*/ +_PUBLIC_ void setup_logging(const char *prog_name, enum debug_logtype new_logtype); + +/** + return a string constant containing n tabs + no more than 10 tabs are returned +*/ +_PUBLIC_ const char *do_debug_tab(int n); + +/** + log suspicious usage - print comments and backtrace +*/ +_PUBLIC_ void log_suspicious_usage(const char *from, const char *info); + +/** + print suspicious usage - print comments and backtrace +*/ +_PUBLIC_ void print_suspicious_usage(const char* from, const char* info); +_PUBLIC_ uint32_t get_task_id(void); +_PUBLIC_ void log_task_id(void); + +/** + register a set of debug handlers. +*/ +_PUBLIC_ void register_debug_handlers(const char *name, struct debug_ops *ops); + +/** + the backend for debug messages. Note that the DEBUG() macro has already + ensured that the log level has been met before this is called + + @note You should never have to call this function directly. Call the DEBUG() + macro instead. +*/ +_PUBLIC_ void dbgtext(const char *format, ...) PRINTF_ATTRIBUTE(1,2); diff --git a/lib/util/dlinklist.h b/lib/util/dlinklist.h new file mode 100644 index 0000000000..5624124459 --- /dev/null +++ b/lib/util/dlinklist.h @@ -0,0 +1,113 @@ +/* + Unix SMB/CIFS implementation. + some simple double linked list macros + Copyright (C) Andrew Tridgell 1998 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* To use these macros you must have a structure containing a next and + prev pointer */ + +#ifndef _DLINKLIST_H +#define _DLINKLIST_H + + +/* hook into the front of the list */ +#define DLIST_ADD(list, p) \ +do { \ + if (!(list)) { \ + (list) = (p); \ + (p)->next = (p)->prev = NULL; \ + } else { \ + (list)->prev = (p); \ + (p)->next = (list); \ + (p)->prev = NULL; \ + (list) = (p); \ + }\ +} while (0) + +/* remove an element from a list - element doesn't have to be in list. */ +#define DLIST_REMOVE(list, p) \ +do { \ + if ((p) == (list)) { \ + (list) = (p)->next; \ + if (list) (list)->prev = NULL; \ + } else { \ + if ((p)->prev) (p)->prev->next = (p)->next; \ + if ((p)->next) (p)->next->prev = (p)->prev; \ + } \ + if ((p) != (list)) (p)->next = (p)->prev = NULL; \ +} while (0) + +/* promote an element to the top of the list */ +#define DLIST_PROMOTE(list, p) \ +do { \ + DLIST_REMOVE(list, p); \ + DLIST_ADD(list, p); \ +} while (0) + +/* hook into the end of the list - needs a tmp pointer */ +#define DLIST_ADD_END(list, p, type) \ +do { \ + if (!(list)) { \ + (list) = (p); \ + (p)->next = (p)->prev = NULL; \ + } else { \ + type tmp; \ + for (tmp = (list); tmp->next; tmp = tmp->next) ; \ + tmp->next = (p); \ + (p)->next = NULL; \ + (p)->prev = tmp; \ + } \ +} while (0) + +/* insert 'p' after the given element 'el' in a list. If el is NULL then + this is the same as a DLIST_ADD() */ +#define DLIST_ADD_AFTER(list, p, el) \ +do { \ + if (!(list) || !(el)) { \ + DLIST_ADD(list, p); \ + } else { \ + p->prev = el; \ + p->next = el->next; \ + el->next = p; \ + if (p->next) p->next->prev = p; \ + }\ +} while (0) + +/* demote an element to the end of the list, needs a tmp pointer */ +#define DLIST_DEMOTE(list, p, tmp) \ +do { \ + DLIST_REMOVE(list, p); \ + DLIST_ADD_END(list, p, tmp); \ +} while (0) + +/* concatenate two lists - putting all elements of the 2nd list at the + end of the first list */ +#define DLIST_CONCATENATE(list1, list2, type) \ +do { \ + if (!(list1)) { \ + (list1) = (list2); \ + } else { \ + type tmp; \ + for (tmp = (list1); tmp->next; tmp = tmp->next) ; \ + tmp->next = (list2); \ + if (list2) { \ + (list2)->prev = tmp; \ + } \ + } \ +} while (0) + +#endif /* _DLINKLIST_H */ diff --git a/lib/util/dprintf.c b/lib/util/dprintf.c new file mode 100644 index 0000000000..e4f02758eb --- /dev/null +++ b/lib/util/dprintf.c @@ -0,0 +1,111 @@ +/* + Unix SMB/CIFS implementation. + display print functions + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Jelmer Vernooij 2007 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +/* + this module provides functions for printing internal strings in the + "display charset". + + This charset may be quite different from the chosen unix charset. + + Eventually these functions will need to take care of column count constraints + + The d_ prefix on print functions in Samba refers to the display character set + conversion +*/ + +#include "includes.h" +#include "system/locale.h" +#include "param/param.h" + +static smb_iconv_t display_cd = (smb_iconv_t)-1; + +void d_set_iconv(smb_iconv_t cd) +{ + display_cd = cd; +} + +_PUBLIC_ int d_vfprintf(FILE *f, const char *format, va_list ap) +{ + char *p, *p2; + int ret, clen; + va_list ap2; + + /* If there's nothing to convert, take a shortcut */ + if (display_cd == (smb_iconv_t)-1) { + return vfprintf(f, format, ap); + } + + /* do any message translations */ + va_copy(ap2, ap); + ret = vasprintf(&p, format, ap2); + va_end(ap2); + + if (ret <= 0) return ret; + + clen = convert_string_talloc_descriptor(NULL, display_cd, p, ret, (void **)&p2); + if (clen == -1) { + /* the string can't be converted - do the best we can, + filling in non-printing chars with '?' */ + int i; + for (i=0;i. +*/ + +#include "includes.h" +#include "version.h" +#include "system/wait.h" +#include "system/filesys.h" + +/** + * @file + * @brief Fault handling + */ + +/* the registered fault handler */ +static struct { + const char *name; + void (*fault_handler)(int sig); +} fault_handlers; + +static const char *progname; + +#ifdef HAVE_BACKTRACE +#include +#elif HAVE_LIBEXC_H +#include +#endif + +/** + * Write backtrace to debug log + */ +_PUBLIC_ void call_backtrace(void) +{ +#ifdef HAVE_BACKTRACE +#ifndef BACKTRACE_STACK_SIZE +#define BACKTRACE_STACK_SIZE 64 +#endif + void *backtrace_stack[BACKTRACE_STACK_SIZE]; + size_t backtrace_size; + char **backtrace_strings; + + /* get the backtrace (stack frames) */ + backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE); + backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size); + + DEBUG(0, ("BACKTRACE: %lu stack frames:\n", + (unsigned long)backtrace_size)); + + if (backtrace_strings) { + int i; + + for (i = 0; i < backtrace_size; i++) + DEBUGADD(0, (" #%u %s\n", i, backtrace_strings[i])); + + /* Leak the backtrace_strings, rather than risk what free() might do */ + } + +#elif HAVE_LIBEXC + +#define NAMESIZE 32 /* Arbitrary */ +#ifndef BACKTRACE_STACK_SIZE +#define BACKTRACE_STACK_SIZE 64 +#endif + + /* The IRIX libexc library provides an API for unwinding the stack. See + * libexc(3) for details. Apparantly trace_back_stack leaks memory, but + * since we are about to abort anyway, it hardly matters. + * + * Note that if we paniced due to a SIGSEGV or SIGBUS (or similar) this + * will fail with a nasty message upon failing to open the /proc entry. + */ + { + uint64_t addrs[BACKTRACE_STACK_SIZE]; + char * names[BACKTRACE_STACK_SIZE]; + char namebuf[BACKTRACE_STACK_SIZE * NAMESIZE]; + + int i; + int levels; + + ZERO_ARRAY(addrs); + ZERO_ARRAY(names); + ZERO_ARRAY(namebuf); + + for (i = 0; i < BACKTRACE_STACK_SIZE; i++) { + names[i] = namebuf + (i * NAMESIZE); + } + + levels = trace_back_stack(0, addrs, names, + BACKTRACE_STACK_SIZE, NAMESIZE); + + DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels)); + for (i = 0; i < levels; i++) { + DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i])); + } + } +#undef NAMESIZE +#endif +} + +_PUBLIC_ const char *panic_action = NULL; + +/** + Something really nasty happened - panic ! +**/ +_PUBLIC_ _NORETURN_ void smb_panic(const char *why) +{ + int result; + + if (panic_action && *panic_action) { + char pidstr[20]; + char cmdstring[200]; + safe_strcpy(cmdstring, panic_action, sizeof(cmdstring)); + snprintf(pidstr, sizeof(pidstr), "%u", getpid()); + all_string_sub(cmdstring, "%PID%", pidstr, sizeof(cmdstring)); + if (progname) { + all_string_sub(cmdstring, "%PROG%", progname, sizeof(cmdstring)); + } + DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmdstring)); + result = system(cmdstring); + + if (result == -1) + DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n", + strerror(errno))); + else + DEBUG(0, ("smb_panic(): action returned status %d\n", + WEXITSTATUS(result))); + } + DEBUG(0,("PANIC: %s\n", why)); + + call_backtrace(); + +#ifdef SIGABRT + CatchSignal(SIGABRT,SIGNAL_CAST SIG_DFL); +#endif + abort(); +} + +/** +report a fault +**/ +_NORETURN_ static void fault_report(int sig) +{ + static int counter; + + if (counter) _exit(1); + + DEBUG(0,("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n")); + DEBUG(0,("INTERNAL ERROR: Signal %d in pid %d (%s)",sig,(int)getpid(),SAMBA_VERSION_STRING)); + DEBUG(0,("\nPlease read the file BUGS.txt in the distribution\n")); + DEBUG(0,("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n")); + + smb_panic("internal error"); + + exit(1); +} + +/** +catch serious errors +**/ +_NORETURN_ static void sig_fault(int sig) +{ + if (fault_handlers.fault_handler) { + /* we have a fault handler, call it. It may not return. */ + fault_handlers.fault_handler(sig); + } + /* If it returns or doesn't exist, use regular reporter */ + fault_report(sig); +} + +/** +setup our fault handlers +**/ +_PUBLIC_ void fault_setup(const char *pname) +{ + if (progname == NULL) { + progname = pname; + } +#ifdef SIGSEGV + CatchSignal(SIGSEGV,SIGNAL_CAST sig_fault); +#endif +#ifdef SIGBUS + CatchSignal(SIGBUS,SIGNAL_CAST sig_fault); +#endif +#ifdef SIGABRT + CatchSignal(SIGABRT,SIGNAL_CAST sig_fault); +#endif +#ifdef SIGFPE + CatchSignal(SIGFPE,SIGNAL_CAST sig_fault); +#endif +} + +/** + register a fault handler. + Should only be called once in the execution of smbd. +*/ +_PUBLIC_ bool register_fault_handler(const char *name, + void (*fault_handler)(int sig)) +{ + if (fault_handlers.name != NULL) { + /* it's already registered! */ + DEBUG(2,("fault handler '%s' already registered - failed '%s'\n", + fault_handlers.name, name)); + return false; + } + + fault_handlers.name = name; + fault_handlers.fault_handler = fault_handler; + + DEBUG(2,("fault handler '%s' registered\n", name)); + return true; +} diff --git a/lib/util/fault.m4 b/lib/util/fault.m4 new file mode 100644 index 0000000000..b24e63641c --- /dev/null +++ b/lib/util/fault.m4 @@ -0,0 +1,5 @@ +AC_CHECK_HEADERS(execinfo.h) +AC_SEARCH_LIBS_EXT(backtrace, [execinfo], EXECINFO_LIBS) +AC_CHECK_FUNC_EXT(backtrace, $EXECINFO_LIBS) +SMB_EXT_LIB(EXECINFO,[${EXECINFO_LIBS}]) +SMB_ENABLE(EXECINFO) diff --git a/lib/util/fsusage.c b/lib/util/fsusage.c new file mode 100644 index 0000000000..43c8787216 --- /dev/null +++ b/lib/util/fsusage.c @@ -0,0 +1,154 @@ +/* + Unix SMB/CIFS implementation. + functions to calculate the free disk space + Copyright (C) Andrew Tridgell 1998-2000 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "system/filesys.h" + +/** + * @file + * @brief Utility functions for getting the amount of free disk space + */ + +/* Return the number of TOSIZE-byte blocks used by + BLOCKS FROMSIZE-byte blocks, rounding away from zero. +*/ +static uint64_t adjust_blocks(uint64_t blocks, uint64_t fromsize, uint64_t tosize) +{ + if (fromsize == tosize) /* e.g., from 512 to 512 */ + return blocks; + else if (fromsize > tosize) /* e.g., from 2048 to 512 */ + return blocks * (fromsize / tosize); + else /* e.g., from 256 to 512 */ + return (blocks + 1) / (tosize / fromsize); +} + +/** + * Retrieve amount of free disk space. + * this does all of the system specific guff to get the free disk space. + * It is derived from code in the GNU fileutils package, but has been + * considerably mangled for use here + * + * results are returned in *dfree and *dsize, in 512 byte units +*/ +_PUBLIC_ int sys_fsusage(const char *path, uint64_t *dfree, uint64_t *dsize) +{ +#ifdef STAT_STATFS3_OSF1 +#define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_fsize, (uint64_t)512) + struct statfs fsd; + + if (statfs (path, &fsd, sizeof (struct statfs)) != 0) + return -1; +#endif /* STAT_STATFS3_OSF1 */ + +#ifdef STAT_STATFS2_FS_DATA /* Ultrix */ +#define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)1024, (uint64_t)512) + struct fs_data fsd; + + if (statfs (path, &fsd) != 1) + return -1; + + (*dsize) = CONVERT_BLOCKS (fsd.fd_req.btot); + (*dfree) = CONVERT_BLOCKS (fsd.fd_req.bfreen); +#endif /* STAT_STATFS2_FS_DATA */ + +#ifdef STAT_STATFS2_BSIZE /* 4.3BSD, SunOS 4, HP-UX, AIX */ +#define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_bsize, (uint64_t)512) + struct statfs fsd; + + if (statfs (path, &fsd) < 0) + return -1; + +#ifdef STATFS_TRUNCATES_BLOCK_COUNTS + /* In SunOS 4.1.2, 4.1.3, and 4.1.3_U1, the block counts in the + struct statfs are truncated to 2GB. These conditions detect that + truncation, presumably without botching the 4.1.1 case, in which + the values are not truncated. The correct counts are stored in + undocumented spare fields. */ + if (fsd.f_blocks == 0x1fffff && fsd.f_spare[0] > 0) { + fsd.f_blocks = fsd.f_spare[0]; + fsd.f_bfree = fsd.f_spare[1]; + fsd.f_bavail = fsd.f_spare[2]; + } +#endif /* STATFS_TRUNCATES_BLOCK_COUNTS */ +#endif /* STAT_STATFS2_BSIZE */ + + +#ifdef STAT_STATFS2_FSIZE /* 4.4BSD */ +#define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_fsize, (uint64_t)512) + + struct statfs fsd; + + if (statfs (path, &fsd) < 0) + return -1; +#endif /* STAT_STATFS2_FSIZE */ + +#ifdef STAT_STATFS4 /* SVR3, Dynix, Irix, AIX */ +# if _AIX || defined(_CRAY) +# define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_bsize, (uint64_t)512) +# ifdef _CRAY +# define f_bavail f_bfree +# endif +# else +# define CONVERT_BLOCKS(B) ((uint64_t)B) +# ifndef _SEQUENT_ /* _SEQUENT_ is DYNIX/ptx */ +# ifndef DOLPHIN /* DOLPHIN 3.8.alfa/7.18 has f_bavail */ +# define f_bavail f_bfree +# endif +# endif +# endif + + struct statfs fsd; + + if (statfs (path, &fsd, sizeof fsd, 0) < 0) + return -1; + /* Empirically, the block counts on most SVR3 and SVR3-derived + systems seem to always be in terms of 512-byte blocks, + no matter what value f_bsize has. */ + +#endif /* STAT_STATFS4 */ + +#if defined(STAT_STATVFS) || defined(STAT_STATVFS64) /* SVR4 */ +# define CONVERT_BLOCKS(B) \ + adjust_blocks ((uint64_t)(B), fsd.f_frsize ? (uint64_t)fsd.f_frsize : (uint64_t)fsd.f_bsize, (uint64_t)512) + +#ifdef STAT_STATVFS64 + struct statvfs64 fsd; + if (statvfs64(path, &fsd) < 0) return -1; +#else + struct statvfs fsd; + if (statvfs(path, &fsd) < 0) return -1; +#endif + + /* f_frsize isn't guaranteed to be supported. */ + +#endif /* STAT_STATVFS */ + +#ifndef CONVERT_BLOCKS + /* we don't have any dfree code! */ + return -1; +#else +#if !defined(STAT_STATFS2_FS_DATA) + /* !Ultrix */ + (*dsize) = CONVERT_BLOCKS (fsd.f_blocks); + (*dfree) = CONVERT_BLOCKS (fsd.f_bavail); +#endif /* not STAT_STATFS2_FS_DATA */ +#endif + + return 0; +} diff --git a/lib/util/fsusage.m4 b/lib/util/fsusage.m4 new file mode 100644 index 0000000000..6d5d13fe25 --- /dev/null +++ b/lib/util/fsusage.m4 @@ -0,0 +1,190 @@ +################################################# +# these tests are taken from the GNU fileutils package +AC_CHECKING(how to get filesystem space usage) +AC_CHECK_HEADERS(sys/statfs.h sys/statvfs.h sys/vfs.h) + +AC_CHECK_HEADERS(sys/mount.h, , , [AC_INCLUDES_DEFAULT +#ifdef HAVE_SYS_PARAM_H +#include +#endif]) + +space=no + +# Test for statvfs64. +if test $space = no; then + # SVR4 + AC_CACHE_CHECK([statvfs64 function (SVR4)], fu_cv_sys_stat_statvfs64, + [AC_TRY_RUN([ +#if defined(HAVE_UNISTD_H) +#include +#endif +#include +#include + main () + { + struct statvfs64 fsd; + exit (statvfs64 (".", &fsd)); + }], + fu_cv_sys_stat_statvfs64=yes, + fu_cv_sys_stat_statvfs64=no, + fu_cv_sys_stat_statvfs64=cross)]) + if test $fu_cv_sys_stat_statvfs64 = yes; then + space=yes + AC_DEFINE(STAT_STATVFS64,1,[Whether statvfs64() is available]) + fi +fi + +# Perform only the link test since it seems there are no variants of the +# statvfs function. This check is more than just AC_CHECK_FUNCS(statvfs) +# because that got a false positive on SCO OSR5. Adding the declaration +# of a `struct statvfs' causes this test to fail (as it should) on such +# systems. That system is reported to work fine with STAT_STATFS4 which +# is what it gets when this test fails. +if test $space = no; then + # SVR4 + AC_CACHE_CHECK([statvfs function (SVR4)], fu_cv_sys_stat_statvfs, + [AC_TRY_LINK([#include +#include ], + [struct statvfs fsd; statvfs (0, &fsd);], + fu_cv_sys_stat_statvfs=yes, + fu_cv_sys_stat_statvfs=no)]) + if test $fu_cv_sys_stat_statvfs = yes; then + space=yes + AC_DEFINE(STAT_STATVFS,1,[Whether statvfs() is available]) + fi +fi + +if test $space = no; then + # DEC Alpha running OSF/1 + AC_MSG_CHECKING([for 3-argument statfs function (DEC OSF/1)]) + AC_CACHE_VAL(fu_cv_sys_stat_statfs3_osf1, + [AC_TRY_RUN([ +#include +#include +#include + main () + { + struct statfs fsd; + fsd.f_fsize = 0; + exit (statfs (".", &fsd, sizeof (struct statfs))); + }], + fu_cv_sys_stat_statfs3_osf1=yes, + fu_cv_sys_stat_statfs3_osf1=no, + fu_cv_sys_stat_statfs3_osf1=no)]) + AC_MSG_RESULT($fu_cv_sys_stat_statfs3_osf1) + if test $fu_cv_sys_stat_statfs3_osf1 = yes; then + space=yes + AC_DEFINE(STAT_STATFS3_OSF1,1,[Whether statfs requires 3 arguments]) + fi +fi + +if test $space = no; then +# AIX + AC_MSG_CHECKING([for two-argument statfs with statfs.bsize dnl +member (AIX, 4.3BSD)]) + AC_CACHE_VAL(fu_cv_sys_stat_statfs2_bsize, + [AC_TRY_RUN([ +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_SYS_MOUNT_H +#include +#endif +#ifdef HAVE_SYS_VFS_H +#include +#endif + main () + { + struct statfs fsd; + fsd.f_bsize = 0; + exit (statfs (".", &fsd)); + }], + fu_cv_sys_stat_statfs2_bsize=yes, + fu_cv_sys_stat_statfs2_bsize=no, + fu_cv_sys_stat_statfs2_bsize=no)]) + AC_MSG_RESULT($fu_cv_sys_stat_statfs2_bsize) + if test $fu_cv_sys_stat_statfs2_bsize = yes; then + space=yes + AC_DEFINE(STAT_STATFS2_BSIZE,1,[Whether statfs requires two arguments and struct statfs has bsize property]) + fi +fi + +if test $space = no; then +# SVR3 + AC_MSG_CHECKING([for four-argument statfs (AIX-3.2.5, SVR3)]) + AC_CACHE_VAL(fu_cv_sys_stat_statfs4, + [AC_TRY_RUN([#include +#include + main () + { + struct statfs fsd; + exit (statfs (".", &fsd, sizeof fsd, 0)); + }], + fu_cv_sys_stat_statfs4=yes, + fu_cv_sys_stat_statfs4=no, + fu_cv_sys_stat_statfs4=no)]) + AC_MSG_RESULT($fu_cv_sys_stat_statfs4) + if test $fu_cv_sys_stat_statfs4 = yes; then + space=yes + AC_DEFINE(STAT_STATFS4,1,[Whether statfs requires 4 arguments]) + fi +fi + +if test $space = no; then +# 4.4BSD and NetBSD + AC_MSG_CHECKING([for two-argument statfs with statfs.fsize dnl +member (4.4BSD and NetBSD)]) + AC_CACHE_VAL(fu_cv_sys_stat_statfs2_fsize, + [AC_TRY_RUN([#include +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_SYS_MOUNT_H +#include +#endif + main () + { + struct statfs fsd; + fsd.f_fsize = 0; + exit (statfs (".", &fsd)); + }], + fu_cv_sys_stat_statfs2_fsize=yes, + fu_cv_sys_stat_statfs2_fsize=no, + fu_cv_sys_stat_statfs2_fsize=no)]) + AC_MSG_RESULT($fu_cv_sys_stat_statfs2_fsize) + if test $fu_cv_sys_stat_statfs2_fsize = yes; then + space=yes + AC_DEFINE(STAT_STATFS2_FSIZE,1,[Whether statfs requires 2 arguments and struct statfs has fsize]) + fi +fi + +if test $space = no; then + # Ultrix + AC_MSG_CHECKING([for two-argument statfs with struct fs_data (Ultrix)]) + AC_CACHE_VAL(fu_cv_sys_stat_fs_data, + [AC_TRY_RUN([#include +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_SYS_MOUNT_H +#include +#endif +#ifdef HAVE_SYS_FS_TYPES_H +#include +#endif + main () + { + struct fs_data fsd; + /* Ultrix's statfs returns 1 for success, + 0 for not mounted, -1 for failure. */ + exit (statfs (".", &fsd) != 1); + }], + fu_cv_sys_stat_fs_data=yes, + fu_cv_sys_stat_fs_data=no, + fu_cv_sys_stat_fs_data=no)]) + AC_MSG_RESULT($fu_cv_sys_stat_fs_data) + if test $fu_cv_sys_stat_fs_data = yes; then + space=yes + AC_DEFINE(STAT_STATFS2_FS_DATA,1,[Whether statfs requires 2 arguments and struct fs_data is available]) + fi +fi diff --git a/lib/util/genrand.c b/lib/util/genrand.c new file mode 100644 index 0000000000..cd1823a9a0 --- /dev/null +++ b/lib/util/genrand.c @@ -0,0 +1,361 @@ +/* + Unix SMB/CIFS implementation. + + Functions to create reasonable random numbers for crypto use. + + Copyright (C) Jeremy Allison 2001 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "system/filesys.h" +#include "../lib/crypto/crypto.h" +#include "system/locale.h" + +/** + * @file + * @brief Random number generation + */ + +static unsigned char hash[258]; +static uint32_t counter; + +static bool done_reseed = false; +static unsigned int bytes_since_reseed = 0; + +static int urand_fd = -1; + +static void (*reseed_callback)(void *userdata, int *newseed); +static void *reseed_callback_userdata = NULL; + +/** + Copy any user given reseed data. +**/ + +_PUBLIC_ void set_rand_reseed_callback(void (*fn)(void *, int *), void *userdata) +{ + reseed_callback = fn; + reseed_callback_userdata = userdata; + set_need_random_reseed(); +} + +/** + * Tell the random number generator it needs to reseed. + */ +_PUBLIC_ void set_need_random_reseed(void) +{ + done_reseed = false; + bytes_since_reseed = 0; +} + +static void get_rand_reseed_data(int *reseed_data) +{ + if (reseed_callback) { + reseed_callback(reseed_callback_userdata, reseed_data); + } else { + *reseed_data = 0; + } +} + +/**************************************************************** + Setup the seed. +*****************************************************************/ + +static void seed_random_stream(unsigned char *seedval, size_t seedlen) +{ + unsigned char j = 0; + size_t ind; + + for (ind = 0; ind < 256; ind++) + hash[ind] = (unsigned char)ind; + + for( ind = 0; ind < 256; ind++) { + unsigned char tc; + + j += (hash[ind] + seedval[ind%seedlen]); + + tc = hash[ind]; + hash[ind] = hash[j]; + hash[j] = tc; + } + + hash[256] = 0; + hash[257] = 0; +} + +/**************************************************************** + Get datasize bytes worth of random data. +*****************************************************************/ + +static void get_random_stream(unsigned char *data, size_t datasize) +{ + unsigned char index_i = hash[256]; + unsigned char index_j = hash[257]; + size_t ind; + + for( ind = 0; ind < datasize; ind++) { + unsigned char tc; + unsigned char t; + + index_i++; + index_j += hash[index_i]; + + tc = hash[index_i]; + hash[index_i] = hash[index_j]; + hash[index_j] = tc; + + t = hash[index_i] + hash[index_j]; + data[ind] = hash[t]; + } + + hash[256] = index_i; + hash[257] = index_j; +} + +/**************************************************************** + Get a 16 byte hash from the contents of a file. + + Note that the hash is initialised, because the extra entropy is not + worth the valgrind pain. +*****************************************************************/ + +static void do_filehash(const char *fname, unsigned char *the_hash) +{ + unsigned char buf[1011]; /* deliberate weird size */ + unsigned char tmp_md4[16]; + int fd, n; + + ZERO_STRUCT(tmp_md4); + + fd = open(fname,O_RDONLY,0); + if (fd == -1) + return; + + while ((n = read(fd, (char *)buf, sizeof(buf))) > 0) { + mdfour(tmp_md4, buf, n); + for (n=0;n<16;n++) + the_hash[n] ^= tmp_md4[n]; + } + close(fd); +} + +/************************************************************** + Try and get a good random number seed. Try a number of + different factors. Firstly, try /dev/urandom - use if exists. + + We use /dev/urandom as a read of /dev/random can block if + the entropy pool dries up. This leads clients to timeout + or be very slow on connect. + + If we can't use /dev/urandom then seed the stream random generator + above... +**************************************************************/ + +static int do_reseed(bool use_fd, int fd) +{ + unsigned char seed_inbuf[40]; + uint32_t v1, v2; struct timeval tval; pid_t mypid; + int reseed_data = 0; + + if (use_fd) { + if (fd == -1) { + fd = open( "/dev/urandom", O_RDONLY,0); + } + if (fd != -1 + && (read(fd, seed_inbuf, sizeof(seed_inbuf)) == sizeof(seed_inbuf))) { + seed_random_stream(seed_inbuf, sizeof(seed_inbuf)); + return fd; + } + } + + /* Add in some secret file contents */ + + do_filehash("/etc/shadow", &seed_inbuf[0]); + + /* + * Add the counter, time of day, and pid. + */ + + GetTimeOfDay(&tval); + mypid = getpid(); + v1 = (counter++) + mypid + tval.tv_sec; + v2 = (counter++) * mypid + tval.tv_usec; + + SIVAL(seed_inbuf, 32, v1 ^ IVAL(seed_inbuf, 32)); + SIVAL(seed_inbuf, 36, v2 ^ IVAL(seed_inbuf, 36)); + + /* + * Add any user-given reseed data. + */ + + get_rand_reseed_data(&reseed_data); + if (reseed_data) { + size_t i; + for (i = 0; i < sizeof(seed_inbuf); i++) + seed_inbuf[i] ^= ((char *)(&reseed_data))[i % sizeof(reseed_data)]; + } + + seed_random_stream(seed_inbuf, sizeof(seed_inbuf)); + + return -1; +} + +/** + Interface to the (hopefully) good crypto random number generator. + Will use our internal PRNG if more than 40 bytes of random generation + has been requested, otherwise tries to read from /dev/random +**/ +_PUBLIC_ void generate_random_buffer(uint8_t *out, int len) +{ + unsigned char md4_buf[64]; + unsigned char tmp_buf[16]; + unsigned char *p; + + if(!done_reseed) { + bytes_since_reseed += len; + + /* Magic constant to try and avoid reading 40 bytes + * and setting up the PRNG if the app only ever wants + * a few bytes */ + if (bytes_since_reseed < 40) { + if (urand_fd == -1) { + urand_fd = open( "/dev/urandom", O_RDONLY,0); + } + if(urand_fd != -1 && (read(urand_fd, out, len) == len)) { + return; + } + } + + urand_fd = do_reseed(true, urand_fd); + done_reseed = true; + } + + /* + * Generate random numbers in chunks of 64 bytes, + * then md4 them & copy to the output buffer. + * This way the raw state of the stream is never externally + * seen. + */ + + p = out; + while(len > 0) { + int copy_len = len > 16 ? 16 : len; + + get_random_stream(md4_buf, sizeof(md4_buf)); + mdfour(tmp_buf, md4_buf, sizeof(md4_buf)); + memcpy(p, tmp_buf, copy_len); + p += copy_len; + len -= copy_len; + } +} + +/** + Interface to the (hopefully) good crypto random number generator. + Will always use /dev/urandom if available. +**/ +_PUBLIC_ void generate_secret_buffer(uint8_t *out, int len) +{ + if (urand_fd == -1) { + urand_fd = open( "/dev/urandom", O_RDONLY,0); + } + if(urand_fd != -1 && (read(urand_fd, out, len) == len)) { + return; + } + + generate_random_buffer(out, len); +} + +/** + generate a single random uint32_t +**/ +_PUBLIC_ uint32_t generate_random(void) +{ + uint8_t v[4]; + generate_random_buffer(v, 4); + return IVAL(v, 0); +} + + +/** + very basic password quality checker +**/ +_PUBLIC_ bool check_password_quality(const char *s) +{ + int has_digit=0, has_capital=0, has_lower=0, has_special=0, has_high=0; + while (*s) { + if (isdigit((unsigned char)*s)) { + has_digit |= 1; + } else if (isupper((unsigned char)*s)) { + has_capital |= 1; + } else if (islower((unsigned char)*s)) { + has_lower |= 1; + } else if (isascii((unsigned char)*s)) { + has_special |= 1; + } else { + has_high++; + } + s++; + } + + return ((has_digit + has_lower + has_capital + has_special) >= 3 + || (has_high > strlen(s)/2)); +} + +/** + Use the random number generator to generate a random string. +**/ + +_PUBLIC_ char *generate_random_str_list(TALLOC_CTX *mem_ctx, size_t len, const char *list) +{ + size_t i; + size_t list_len = strlen(list); + + char *retstr = talloc_array(mem_ctx, char, len + 1); + if (!retstr) return NULL; + + generate_random_buffer((uint8_t *)retstr, len); + for (i = 0; i < len; i++) { + retstr[i] = list[retstr[i] % list_len]; + } + retstr[i] = '\0'; + + return retstr; +} + +/** + * Generate a random text string consisting of the specified length. + * The returned string will be allocated. + * + * Characters used are: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#., + */ + +_PUBLIC_ char *generate_random_str(TALLOC_CTX *mem_ctx, size_t len) +{ + char *retstr; + const char *c_list = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#.,"; + +again: + retstr = generate_random_str_list(mem_ctx, len, c_list); + if (!retstr) return NULL; + + /* we need to make sure the random string passes basic quality tests + or it might be rejected by windows as a password */ + if (len >= 7 && !check_password_quality(retstr)) { + talloc_free(retstr); + goto again; + } + + return retstr; +} diff --git a/lib/util/idtree.c b/lib/util/idtree.c new file mode 100644 index 0000000000..193922973f --- /dev/null +++ b/lib/util/idtree.c @@ -0,0 +1,403 @@ +/* + Unix SMB/CIFS implementation. + + very efficient functions to manage mapping a id (such as a fnum) to + a pointer. This is used for fnum and search id allocation. + + Copyright (C) Andrew Tridgell 2004 + + This code is derived from lib/idr.c in the 2.6 Linux kernel, which was + written by Jim Houston jim.houston@ccur.com, and is + Copyright (C) 2002 by Concurrent Computer Corporation + + 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 + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* + see the section marked "public interface" below for documentation +*/ + +/** + * @file + */ + +#include "includes.h" + +#define IDR_BITS 5 +#define IDR_FULL 0xfffffffful +#if 0 /* unused */ +#define TOP_LEVEL_FULL (IDR_FULL >> 30) +#endif +#define IDR_SIZE (1 << IDR_BITS) +#define IDR_MASK ((1 << IDR_BITS)-1) +#define MAX_ID_SHIFT (sizeof(int)*8 - 1) +#define MAX_ID_BIT (1U << MAX_ID_SHIFT) +#define MAX_ID_MASK (MAX_ID_BIT - 1) +#define MAX_LEVEL (MAX_ID_SHIFT + IDR_BITS - 1) / IDR_BITS +#define IDR_FREE_MAX MAX_LEVEL + MAX_LEVEL + +#define set_bit(bit, v) (v) |= (1<<(bit)) +#define clear_bit(bit, v) (v) &= ~(1<<(bit)) +#define test_bit(bit, v) ((v) & (1<<(bit))) + +struct idr_layer { + uint32_t bitmap; + struct idr_layer *ary[IDR_SIZE]; + int count; +}; + +struct idr_context { + struct idr_layer *top; + struct idr_layer *id_free; + int layers; + int id_free_cnt; +}; + +static struct idr_layer *alloc_layer(struct idr_context *idp) +{ + struct idr_layer *p; + + if (!(p = idp->id_free)) + return NULL; + idp->id_free = p->ary[0]; + idp->id_free_cnt--; + p->ary[0] = NULL; + return p; +} + +static int find_next_bit(uint32_t bm, int maxid, int n) +{ + while (nary[0] = idp->id_free; + idp->id_free = p; + idp->id_free_cnt++; +} + +static int idr_pre_get(struct idr_context *idp) +{ + while (idp->id_free_cnt < IDR_FREE_MAX) { + struct idr_layer *new = talloc_zero(idp, struct idr_layer); + if(new == NULL) + return (0); + free_layer(idp, new); + } + return 1; +} + +static int sub_alloc(struct idr_context *idp, void *ptr, int *starting_id) +{ + int n, m, sh; + struct idr_layer *p, *new; + struct idr_layer *pa[MAX_LEVEL]; + int l, id, oid; + uint32_t bm; + + memset(pa, 0, sizeof(pa)); + + id = *starting_id; +restart: + p = idp->top; + l = idp->layers; + pa[l--] = NULL; + while (1) { + /* + * We run around this while until we reach the leaf node... + */ + n = (id >> (IDR_BITS*l)) & IDR_MASK; + bm = ~p->bitmap; + m = find_next_bit(bm, IDR_SIZE, n); + if (m == IDR_SIZE) { + /* no space available go back to previous layer. */ + l++; + oid = id; + id = (id | ((1 << (IDR_BITS*l))-1)) + 1; + + /* if already at the top layer, we need to grow */ + if (!(p = pa[l])) { + *starting_id = id; + return -2; + } + + /* If we need to go up one layer, continue the + * loop; otherwise, restart from the top. + */ + sh = IDR_BITS * (l + 1); + if (oid >> sh == id >> sh) + continue; + else + goto restart; + } + if (m != n) { + sh = IDR_BITS*l; + id = ((id >> sh) ^ n ^ m) << sh; + } + if ((id >= MAX_ID_BIT) || (id < 0)) + return -1; + if (l == 0) + break; + /* + * Create the layer below if it is missing. + */ + if (!p->ary[m]) { + if (!(new = alloc_layer(idp))) + return -1; + p->ary[m] = new; + p->count++; + } + pa[l--] = p; + p = p->ary[m]; + } + /* + * We have reached the leaf node, plant the + * users pointer and return the raw id. + */ + p->ary[m] = (struct idr_layer *)ptr; + set_bit(m, p->bitmap); + p->count++; + /* + * If this layer is full mark the bit in the layer above + * to show that this part of the radix tree is full. + * This may complete the layer above and require walking + * up the radix tree. + */ + n = id; + while (p->bitmap == IDR_FULL) { + if (!(p = pa[++l])) + break; + n = n >> IDR_BITS; + set_bit((n & IDR_MASK), p->bitmap); + } + return(id); +} + +static int idr_get_new_above_int(struct idr_context *idp, void *ptr, int starting_id) +{ + struct idr_layer *p, *new; + int layers, v, id; + + idr_pre_get(idp); + + id = starting_id; +build_up: + p = idp->top; + layers = idp->layers; + if (!p) { + if (!(p = alloc_layer(idp))) + return -1; + layers = 1; + } + /* + * Add a new layer to the top of the tree if the requested + * id is larger than the currently allocated space. + */ + while ((layers < MAX_LEVEL) && (id >= (1 << (layers*IDR_BITS)))) { + layers++; + if (!p->count) + continue; + if (!(new = alloc_layer(idp))) { + /* + * The allocation failed. If we built part of + * the structure tear it down. + */ + for (new = p; p && p != idp->top; new = p) { + p = p->ary[0]; + new->ary[0] = NULL; + new->bitmap = new->count = 0; + free_layer(idp, new); + } + return -1; + } + new->ary[0] = p; + new->count = 1; + if (p->bitmap == IDR_FULL) + set_bit(0, new->bitmap); + p = new; + } + idp->top = p; + idp->layers = layers; + v = sub_alloc(idp, ptr, &id); + if (v == -2) + goto build_up; + return(v); +} + +static int sub_remove(struct idr_context *idp, int shift, int id) +{ + struct idr_layer *p = idp->top; + struct idr_layer **pa[MAX_LEVEL]; + struct idr_layer ***paa = &pa[0]; + int n; + + *paa = NULL; + *++paa = &idp->top; + + while ((shift > 0) && p) { + n = (id >> shift) & IDR_MASK; + clear_bit(n, p->bitmap); + *++paa = &p->ary[n]; + p = p->ary[n]; + shift -= IDR_BITS; + } + n = id & IDR_MASK; + if (p != NULL && test_bit(n, p->bitmap)) { + clear_bit(n, p->bitmap); + p->ary[n] = NULL; + while(*paa && ! --((**paa)->count)){ + free_layer(idp, **paa); + **paa-- = NULL; + } + if ( ! *paa ) + idp->layers = 0; + return 0; + } + return -1; +} + +static void *_idr_find(struct idr_context *idp, int id) +{ + int n; + struct idr_layer *p; + + n = idp->layers * IDR_BITS; + p = idp->top; + /* + * This tests to see if bits outside the current tree are + * present. If so, tain't one of ours! + */ + if ((id & ~(~0 << MAX_ID_SHIFT)) >> (n + IDR_BITS)) + return NULL; + + /* Mask off upper bits we don't use for the search. */ + id &= MAX_ID_MASK; + + while (n >= IDR_BITS && p) { + n -= IDR_BITS; + p = p->ary[(id >> n) & IDR_MASK]; + } + return((void *)p); +} + +static int _idr_remove(struct idr_context *idp, int id) +{ + struct idr_layer *p; + + /* Mask off upper bits we don't use for the search. */ + id &= MAX_ID_MASK; + + if (sub_remove(idp, (idp->layers - 1) * IDR_BITS, id) == -1) { + return -1; + } + + if ( idp->top && idp->top->count == 1 && + (idp->layers > 1) && + idp->top->ary[0]) { + /* We can drop a layer */ + p = idp->top->ary[0]; + idp->top->bitmap = idp->top->count = 0; + free_layer(idp, idp->top); + idp->top = p; + --idp->layers; + } + while (idp->id_free_cnt >= IDR_FREE_MAX) { + p = alloc_layer(idp); + talloc_free(p); + } + return 0; +} + +/************************************************************************ + this is the public interface +**************************************************************************/ + +/** + initialise a idr tree. The context return value must be passed to + all subsequent idr calls. To destroy the idr tree use talloc_free() + on this context + */ +_PUBLIC_ struct idr_context *idr_init(TALLOC_CTX *mem_ctx) +{ + return talloc_zero(mem_ctx, struct idr_context); +} + +/** + allocate the next available id, and assign 'ptr' into its slot. + you can retrieve later this pointer using idr_find() +*/ +_PUBLIC_ int idr_get_new(struct idr_context *idp, void *ptr, int limit) +{ + int ret = idr_get_new_above_int(idp, ptr, 0); + if (ret > limit) { + idr_remove(idp, ret); + return -1; + } + return ret; +} + +/** + allocate a new id, giving the first available value greater than or + equal to the given starting id +*/ +_PUBLIC_ int idr_get_new_above(struct idr_context *idp, void *ptr, int starting_id, int limit) +{ + int ret = idr_get_new_above_int(idp, ptr, starting_id); + if (ret > limit) { + idr_remove(idp, ret); + return -1; + } + return ret; +} + +/** + allocate a new id randomly in the given range +*/ +_PUBLIC_ int idr_get_new_random(struct idr_context *idp, void *ptr, int limit) +{ + int id; + + /* first try a random starting point in the whole range, and if that fails, + then start randomly in the bottom half of the range. This can only + fail if the range is over half full */ + id = idr_get_new_above(idp, ptr, 1+(generate_random() % limit), limit); + if (id == -1) { + id = idr_get_new_above(idp, ptr, 1+(generate_random()%(limit/2)), limit); + } + + return id; +} + +/** + find a pointer value previously set with idr_get_new given an id +*/ +_PUBLIC_ void *idr_find(struct idr_context *idp, int id) +{ + return _idr_find(idp, id); +} + +/** + remove an id from the idr tree +*/ +_PUBLIC_ int idr_remove(struct idr_context *idp, int id) +{ + int ret; + ret = _idr_remove((struct idr_context *)idp, id); + if (ret != 0) { + DEBUG(0,("WARNING: attempt to remove unset id %d in idtree\n", id)); + } + return ret; +} diff --git a/lib/util/mainpage.dox b/lib/util/mainpage.dox new file mode 100644 index 0000000000..464151e771 --- /dev/null +++ b/lib/util/mainpage.dox @@ -0,0 +1,11 @@ +/** + +\mainpage util + +\section Introduction + +This library contains convenience functions that are used heavily +throughout Samba. None of these functions are SMB or Samba-specific. +It's a bit to Samba what GLib is to the GNOME folks. + +*/ diff --git a/lib/util/ms_fnmatch.c b/lib/util/ms_fnmatch.c new file mode 100644 index 0000000000..5e04ec1f4b --- /dev/null +++ b/lib/util/ms_fnmatch.c @@ -0,0 +1,223 @@ +/* + Unix SMB/CIFS implementation. + filename matching routine + Copyright (C) Andrew Tridgell 1992-2004 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* + This module was originally based on fnmatch.c copyright by the Free + Software Foundation. It bears little (if any) resemblence to that + code now +*/ + +/** + * @file + * @brief MS-style Filename matching + */ + +#include "includes.h" +#include "param/param.h" + +static int null_match(const char *p) +{ + for (;*p;p++) { + if (*p != '*' && + *p != '<' && + *p != '"' && + *p != '>') return -1; + } + return 0; +} + +/* + the max_n structure is purely for efficiency, it doesn't contribute + to the matching algorithm except by ensuring that the algorithm does + not grow exponentially +*/ +struct max_n { + const char *predot; + const char *postdot; +}; + + +/* + p and n are the pattern and string being matched. The max_n array is + an optimisation only. The ldot pointer is NULL if the string does + not contain a '.', otherwise it points at the last dot in 'n'. +*/ +static int ms_fnmatch_core(const char *p, const char *n, + struct max_n *max_n, const char *ldot) +{ + codepoint_t c, c2; + int i; + size_t size, size_n; + struct smb_iconv_convenience *iconv_convenience = lp_iconv_convenience(global_loadparm); + + while ((c = next_codepoint(iconv_convenience, p, &size))) { + p += size; + + switch (c) { + case '*': + /* a '*' matches zero or more characters of any type */ + if (max_n->predot && max_n->predot <= n) { + return null_match(p); + } + for (i=0; n[i]; i += size_n) { + next_codepoint(iconv_convenience, n+i, &size_n); + if (ms_fnmatch_core(p, n+i, max_n+1, ldot) == 0) { + return 0; + } + } + if (!max_n->predot || max_n->predot > n) max_n->predot = n; + return null_match(p); + + case '<': + /* a '<' matches zero or more characters of + any type, but stops matching at the last + '.' in the string. */ + if (max_n->predot && max_n->predot <= n) { + return null_match(p); + } + if (max_n->postdot && max_n->postdot <= n && n <= ldot) { + return -1; + } + for (i=0; n[i]; i += size_n) { + next_codepoint(iconv_convenience, n+i, &size_n); + if (ms_fnmatch_core(p, n+i, max_n+1, ldot) == 0) return 0; + if (n+i == ldot) { + if (ms_fnmatch_core(p, n+i+size_n, max_n+1, ldot) == 0) return 0; + if (!max_n->postdot || max_n->postdot > n) max_n->postdot = n; + return -1; + } + } + if (!max_n->predot || max_n->predot > n) max_n->predot = n; + return null_match(p); + + case '?': + /* a '?' matches any single character */ + if (! *n) { + return -1; + } + next_codepoint(iconv_convenience, n, &size_n); + n += size_n; + break; + + case '>': + /* a '?' matches any single character, but + treats '.' specially */ + if (n[0] == '.') { + if (! n[1] && null_match(p) == 0) { + return 0; + } + break; + } + if (! *n) return null_match(p); + next_codepoint(iconv_convenience, n, &size_n); + n += size_n; + break; + + case '"': + /* a bit like a soft '.' */ + if (*n == 0 && null_match(p) == 0) { + return 0; + } + if (*n != '.') return -1; + next_codepoint(iconv_convenience, n, &size_n); + n += size_n; + break; + + default: + c2 = next_codepoint(iconv_convenience, n, &size_n); + if (c != c2 && codepoint_cmpi(c, c2) != 0) { + return -1; + } + n += size_n; + break; + } + } + + if (! *n) { + return 0; + } + + return -1; +} + +int ms_fnmatch(const char *pattern, const char *string, enum protocol_types protocol) +{ + int ret, count, i; + struct max_n *max_n = NULL; + + if (strcmp(string, "..") == 0) { + string = "."; + } + + if (strpbrk(pattern, "<>*?\"") == NULL) { + /* this is not just an optimisation - it is essential + for LANMAN1 correctness */ + return strcasecmp_m(pattern, string); + } + + if (protocol <= PROTOCOL_LANMAN2) { + char *p = talloc_strdup(NULL, pattern); + if (p == NULL) { + return -1; + } + /* + for older negotiated protocols it is possible to + translate the pattern to produce a "new style" + pattern that exactly matches w2k behaviour + */ + for (i=0;p[i];i++) { + if (p[i] == '?') { + p[i] = '>'; + } else if (p[i] == '.' && + (p[i+1] == '?' || + p[i+1] == '*' || + p[i+1] == 0)) { + p[i] = '"'; + } else if (p[i] == '*' && + p[i+1] == '.') { + p[i] = '<'; + } + } + ret = ms_fnmatch(p, string, PROTOCOL_NT1); + talloc_free(p); + return ret; + } + + for (count=i=0;pattern[i];i++) { + if (pattern[i] == '*' || pattern[i] == '<') count++; + } + + max_n = talloc_zero_array(NULL, struct max_n, count); + if (max_n == NULL) { + return -1; + } + + ret = ms_fnmatch_core(pattern, string, max_n, strrchr(string, '.')); + + talloc_free(max_n); + + return ret; +} + + +/** a generic fnmatch function - uses for non-CIFS pattern matching */ +int gen_fnmatch(const char *pattern, const char *string) +{ + return ms_fnmatch(pattern, string, PROTOCOL_NT1); +} diff --git a/lib/util/mutex.c b/lib/util/mutex.c new file mode 100644 index 0000000000..4d0df68eed --- /dev/null +++ b/lib/util/mutex.c @@ -0,0 +1,56 @@ +/* + Unix SMB/CIFS implementation. + Samba mutex/lock functions + Copyright (C) Andrew Tridgell 2003 + Copyright (C) James J Myers 2003 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +#include "includes.h" +#include "mutex.h" + +/** + * @file + * @brief Mutex utility functions + */ + +/* the registered mutex handlers */ +static struct { + const char *name; + struct mutex_ops ops; +} mutex_handlers; + +/* read/write lock routines */ + + +/** + register a set of mutex/rwlock handlers. + Should only be called once in the execution of smbd. +*/ +_PUBLIC_ bool register_mutex_handlers(const char *name, struct mutex_ops *ops) +{ + if (mutex_handlers.name != NULL) { + /* it's already registered! */ + DEBUG(2,("mutex handler '%s' already registered - failed '%s'\n", + mutex_handlers.name, name)); + return false; + } + + mutex_handlers.name = name; + mutex_handlers.ops = *ops; + + DEBUG(2,("mutex handler '%s' registered\n", name)); + return true; +} + diff --git a/lib/util/mutex.h b/lib/util/mutex.h new file mode 100644 index 0000000000..bf845906f2 --- /dev/null +++ b/lib/util/mutex.h @@ -0,0 +1,75 @@ +#ifndef _MUTEX_H_ +#define _MUTEX_H_ +/* + Unix SMB/CIFS implementation. + Samba mutex functions + Copyright (C) Andrew Tridgell 2003 + Copyright (C) James J Myers 2003 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file + * @brief Mutex operations + */ + +struct mutex_ops; + +/* To add a new read/write lock, add it to enum rwlock_id + */ +enum rwlock_id { RWLOCK_SMBD, /* global smbd lock */ + + RWLOCK_MAX /* this MUST be kept last */ +}; + +#define MUTEX_LOCK_BY_ID(mutex_index) smb_mutex_lock_by_id(mutex_index, #mutex_index) +#define MUTEX_UNLOCK_BY_ID(mutex_index) smb_mutex_unlock_by_id(mutex_index, #mutex_index) +#define MUTEX_INIT(mutex, name) smb_mutex_init(mutex, #name) +#define MUTEX_DESTROY(mutex, name) smb_mutex_destroy(mutex, #name) +#define MUTEX_LOCK(mutex, name) smb_mutex_lock(mutex, #name) +#define MUTEX_UNLOCK(mutex, name) smb_mutex_unlock(mutex, #name) + +#define RWLOCK_INIT(rwlock, name) smb_rwlock_init(rwlock, #name) +#define RWLOCK_DESTROY(rwlock, name) smb_rwlock_destroy(rwlock, #name) +#define RWLOCK_LOCK_WRITE(rwlock, name) smb_rwlock_lock_write(rwlock, #name) +#define RWLOCK_LOCK_READ(rwlock, name) smb_rwlock_lock_read(rwlock, #name) +#define RWLOCK_UNLOCK(rwlock, name) smb_rwlock_unlock(rwlock, #name) + + + +/* this null typedef ensures we get the types right and avoids the + pitfalls of void* */ +typedef struct smb_mutex { + void *mutex; +} smb_mutex_t; +typedef struct { + void *rwlock; +} smb_rwlock_t; + +/* the mutex model operations structure - contains function pointers to + the model-specific implementations of each operation */ +struct mutex_ops { + int (*mutex_init)(smb_mutex_t *mutex, const char *name); + int (*mutex_lock)(smb_mutex_t *mutex, const char *name); + int (*mutex_unlock)(smb_mutex_t *mutex, const char *name); + int (*mutex_destroy)(smb_mutex_t *mutex, const char *name); + int (*rwlock_init)(smb_rwlock_t *rwlock, const char *name); + int (*rwlock_lock_write)(smb_rwlock_t *rwlock, const char *name); + int (*rwlock_lock_read)(smb_rwlock_t *rwlock, const char *name); + int (*rwlock_unlock)(smb_rwlock_t *rwlock, const char *name); + int (*rwlock_destroy)(smb_rwlock_t *rwlock, const char *name); +}; + +#endif /* endif _MUTEX_H_ */ diff --git a/lib/util/params.c b/lib/util/params.c new file mode 100644 index 0000000000..3a9e2b9505 --- /dev/null +++ b/lib/util/params.c @@ -0,0 +1,587 @@ +/* -------------------------------------------------------------------------- ** + * Microsoft Network Services for Unix, AKA., Andrew Tridgell's SAMBA. + * + * This module Copyright (C) 1990-1998 Karl Auer + * + * Rewritten almost completely by Christopher R. Hertel + * at the University of Minnesota, September, 1997. + * This module Copyright (C) 1997-1998 by the University of Minnesota + * -------------------------------------------------------------------------- ** + * + * 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * -------------------------------------------------------------------------- ** + * + * Module name: params + * + * -------------------------------------------------------------------------- ** + * + * This module performs lexical analysis and initial parsing of a + * Windows-like parameter file. It recognizes and handles four token + * types: section-name, parameter-name, parameter-value, and + * end-of-file. Comments and line continuation are handled + * internally. + * + * The entry point to the module is function pm_process(). This + * function opens the source file, calls the Parse() function to parse + * the input, and then closes the file when either the EOF is reached + * or a fatal error is encountered. + * + * A sample parameter file might look like this: + * + * [section one] + * parameter one = value string + * parameter two = another value + * [section two] + * new parameter = some value or t'other + * + * The parameter file is divided into sections by section headers: + * section names enclosed in square brackets (eg. [section one]). + * Each section contains parameter lines, each of which consist of a + * parameter name and value delimited by an equal sign. Roughly, the + * syntax is: + * + * :== {
} EOF + * + *
:==
{ } + * + *
:== '[' NAME ']' + * + * :== NAME '=' VALUE '\n' + * + * Blank lines and comment lines are ignored. Comment lines are lines + * beginning with either a semicolon (';') or a pound sign ('#'). + * + * All whitespace in section names and parameter names is compressed + * to single spaces. Leading and trailing whitespace is stipped from + * both names and values. + * + * Only the first equals sign in a parameter line is significant. + * Parameter values may contain equals signs, square brackets and + * semicolons. Internal whitespace is retained in parameter values, + * with the exception of the '\r' character, which is stripped for + * historic reasons. Parameter names may not start with a left square + * bracket, an equal sign, a pound sign, or a semicolon, because these + * are used to identify other tokens. + * + * -------------------------------------------------------------------------- ** + */ + +#include "includes.h" +#include "system/locale.h" + +/* -------------------------------------------------------------------------- ** + * Constants... + */ + +#define BUFR_INC 1024 + + +/* we can't use FILE* due to the 256 fd limit - use this cheap hack + instead */ +typedef struct { + char *buf; + char *p; + size_t size; + char *bufr; + int bSize; +} myFILE; + +static int mygetc(myFILE *f) +{ + if (f->p >= f->buf+f->size) return EOF; + /* be sure to return chars >127 as positive values */ + return (int)( *(f->p++) & 0x00FF ); +} + +static void myfile_close(myFILE *f) +{ + talloc_free(f); +} + +/* -------------------------------------------------------------------------- ** + * Functions... + */ + +static int EatWhitespace( myFILE *InFile ) + /* ------------------------------------------------------------------------ ** + * Scan past whitespace (see ctype(3C)) and return the first non-whitespace + * character, or newline, or EOF. + * + * Input: InFile - Input source. + * + * Output: The next non-whitespace character in the input stream. + * + * Notes: Because the config files use a line-oriented grammar, we + * explicitly exclude the newline character from the list of + * whitespace characters. + * - Note that both EOF (-1) and the nul character ('\0') are + * considered end-of-file markers. + * + * ------------------------------------------------------------------------ ** + */ + { + int c; + + for( c = mygetc( InFile ); isspace( c ) && ('\n' != c); c = mygetc( InFile ) ) + ; + return( c ); + } /* EatWhitespace */ + +static int EatComment( myFILE *InFile ) + /* ------------------------------------------------------------------------ ** + * Scan to the end of a comment. + * + * Input: InFile - Input source. + * + * Output: The character that marks the end of the comment. Normally, + * this will be a newline, but it *might* be an EOF. + * + * Notes: Because the config files use a line-oriented grammar, we + * explicitly exclude the newline character from the list of + * whitespace characters. + * - Note that both EOF (-1) and the nul character ('\0') are + * considered end-of-file markers. + * + * ------------------------------------------------------------------------ ** + */ + { + int c; + + for( c = mygetc( InFile ); ('\n'!=c) && (EOF!=c) && (c>0); c = mygetc( InFile ) ) + ; + return( c ); + } /* EatComment */ + +/***************************************************************************** + * Scan backards within a string to discover if the last non-whitespace + * character is a line-continuation character ('\\'). + * + * Input: line - A pointer to a buffer containing the string to be + * scanned. + * pos - This is taken to be the offset of the end of the + * string. This position is *not* scanned. + * + * Output: The offset of the '\\' character if it was found, or -1 to + * indicate that it was not. + * + *****************************************************************************/ + +static int Continuation(char *line, int pos ) +{ + pos--; + while( (pos >= 0) && isspace((int)line[pos])) + pos--; + + return (((pos >= 0) && ('\\' == line[pos])) ? pos : -1 ); +} + + +static bool Section( myFILE *InFile, bool (*sfunc)(const char *, void *), void *userdata ) + /* ------------------------------------------------------------------------ ** + * Scan a section name, and pass the name to function sfunc(). + * + * Input: InFile - Input source. + * sfunc - Pointer to the function to be called if the section + * name is successfully read. + * + * Output: true if the section name was read and true was returned from + * . false if failed or if a lexical error was + * encountered. + * + * ------------------------------------------------------------------------ ** + */ + { + int c; + int i; + int end; + const char *func = "params.c:Section() -"; + + i = 0; /* is the offset of the next free byte in bufr[] and */ + end = 0; /* is the current "end of string" offset. In most */ + /* cases these will be the same, but if the last */ + /* character written to bufr[] is a space, then */ + /* will be one less than . */ + + c = EatWhitespace( InFile ); /* We've already got the '['. Scan */ + /* past initial white space. */ + + while( (EOF != c) && (c > 0) ) + { + + /* Check that the buffer is big enough for the next character. */ + if( i > (InFile->bSize - 2) ) + { + char *tb; + + tb = talloc_realloc(InFile, InFile->bufr, char, InFile->bSize + BUFR_INC); + if( NULL == tb ) + { + DEBUG(0, ("%s Memory re-allocation failure.", func) ); + return( false ); + } + InFile->bufr = tb; + InFile->bSize += BUFR_INC; + } + + /* Handle a single character. */ + switch( c ) + { + case ']': /* Found the closing bracket. */ + InFile->bufr[end] = '\0'; + if( 0 == end ) /* Don't allow an empty name. */ + { + DEBUG(0, ("%s Empty section name in configuration file.\n", func )); + return( false ); + } + if( !sfunc(InFile->bufr,userdata) ) /* Got a valid name. Deal with it. */ + return( false ); + (void)EatComment( InFile ); /* Finish off the line. */ + return( true ); + + case '\n': /* Got newline before closing ']'. */ + i = Continuation( InFile->bufr, i ); /* Check for line continuation. */ + if( i < 0 ) + { + InFile->bufr[end] = '\0'; + DEBUG(0, ("%s Badly formed line in configuration file: %s\n", + func, InFile->bufr )); + return( false ); + } + end = ( (i > 0) && (' ' == InFile->bufr[i - 1]) ) ? (i - 1) : (i); + c = mygetc( InFile ); /* Continue with next line. */ + break; + + default: /* All else are a valid name chars. */ + if( isspace( c ) ) /* One space per whitespace region. */ + { + InFile->bufr[end] = ' '; + i = end + 1; + c = EatWhitespace( InFile ); + } + else /* All others copy verbatim. */ + { + InFile->bufr[i++] = c; + end = i; + c = mygetc( InFile ); + } + } + } + + /* We arrive here if we've met the EOF before the closing bracket. */ + DEBUG(0, ("%s Unexpected EOF in the configuration file\n", func)); + return( false ); + } /* Section */ + +static bool Parameter( myFILE *InFile, bool (*pfunc)(const char *, const char *, void *), int c, void *userdata ) + /* ------------------------------------------------------------------------ ** + * Scan a parameter name and value, and pass these two fields to pfunc(). + * + * Input: InFile - The input source. + * pfunc - A pointer to the function that will be called to + * process the parameter, once it has been scanned. + * c - The first character of the parameter name, which + * would have been read by Parse(). Unlike a comment + * line or a section header, there is no lead-in + * character that can be discarded. + * + * Output: true if the parameter name and value were scanned and processed + * successfully, else false. + * + * Notes: This function is in two parts. The first loop scans the + * parameter name. Internal whitespace is compressed, and an + * equal sign (=) terminates the token. Leading and trailing + * whitespace is discarded. The second loop scans the parameter + * value. When both have been successfully identified, they are + * passed to pfunc() for processing. + * + * ------------------------------------------------------------------------ ** + */ + { + int i = 0; /* Position within bufr. */ + int end = 0; /* bufr[end] is current end-of-string. */ + int vstart = 0; /* Starting position of the parameter value. */ + const char *func = "params.c:Parameter() -"; + + /* Read the parameter name. */ + while( 0 == vstart ) /* Loop until we've found the start of the value. */ + { + + if( i > (InFile->bSize - 2) ) /* Ensure there's space for next char. */ + { + char *tb; + + tb = talloc_realloc(InFile, InFile->bufr, char, InFile->bSize + BUFR_INC ); + if( NULL == tb ) + { + DEBUG(0, ("%s Memory re-allocation failure.", func) ); + return( false ); + } + InFile->bufr = tb; + InFile->bSize += BUFR_INC; + } + + switch( c ) + { + case '=': /* Equal sign marks end of param name. */ + if( 0 == end ) /* Don't allow an empty name. */ + { + DEBUG(0, ("%s Invalid parameter name in config. file.\n", func )); + return( false ); + } + InFile->bufr[end++] = '\0'; /* Mark end of string & advance. */ + i = end; /* New string starts here. */ + vstart = end; /* New string is parameter value. */ + InFile->bufr[i] = '\0'; /* New string is nul, for now. */ + break; + + case '\n': /* Find continuation char, else error. */ + i = Continuation( InFile->bufr, i ); + if( i < 0 ) + { + InFile->bufr[end] = '\0'; + DEBUG(1,("%s Ignoring badly formed line in configuration file: %s\n", + func, InFile->bufr )); + return( true ); + } + end = ( (i > 0) && (' ' == InFile->bufr[i - 1]) ) ? (i - 1) : (i); + c = mygetc( InFile ); /* Read past eoln. */ + break; + + case '\0': /* Shouldn't have EOF within param name. */ + case EOF: + InFile->bufr[i] = '\0'; + DEBUG(1,("%s Unexpected end-of-file at: %s\n", func, InFile->bufr )); + return( true ); + + default: + if( isspace( c ) ) /* One ' ' per whitespace region. */ + { + InFile->bufr[end] = ' '; + i = end + 1; + c = EatWhitespace( InFile ); + } + else /* All others verbatim. */ + { + InFile->bufr[i++] = c; + end = i; + c = mygetc( InFile ); + } + } + } + + /* Now parse the value. */ + c = EatWhitespace( InFile ); /* Again, trim leading whitespace. */ + while( (EOF !=c) && (c > 0) ) + { + + if( i > (InFile->bSize - 2) ) /* Make sure there's enough room. */ + { + char *tb; + + tb = talloc_realloc(InFile, InFile->bufr, char, InFile->bSize + BUFR_INC ); + if( NULL == tb ) + { + DEBUG(0, ("%s Memory re-allocation failure.", func) ); + return( false ); + } + InFile->bufr = tb; + InFile->bSize += BUFR_INC; + } + + switch( c ) + { + case '\r': /* Explicitly remove '\r' because the older */ + c = mygetc( InFile ); /* version called fgets_slash() which also */ + break; /* removes them. */ + + case '\n': /* Marks end of value unless there's a '\'. */ + i = Continuation( InFile->bufr, i ); + if( i < 0 ) + c = 0; + else + { + for( end = i; (end >= 0) && isspace((int)InFile->bufr[end]); end-- ) + ; + c = mygetc( InFile ); + } + break; + + default: /* All others verbatim. Note that spaces do */ + InFile->bufr[i++] = c; /* not advance . This allows trimming */ + if( !isspace( c ) ) /* of whitespace at the end of the line. */ + end = i; + c = mygetc( InFile ); + break; + } + } + InFile->bufr[end] = '\0'; /* End of value. */ + + return( pfunc( InFile->bufr, &InFile->bufr[vstart], userdata ) ); /* Pass name & value to pfunc(). */ + } /* Parameter */ + +static bool Parse( myFILE *InFile, + bool (*sfunc)(const char *, void *), + bool (*pfunc)(const char *, const char *, void *), + void *userdata ) + /* ------------------------------------------------------------------------ ** + * Scan & parse the input. + * + * Input: InFile - Input source. + * sfunc - Function to be called when a section name is scanned. + * See Section(). + * pfunc - Function to be called when a parameter is scanned. + * See Parameter(). + * + * Output: true if the file was successfully scanned, else false. + * + * Notes: The input can be viewed in terms of 'lines'. There are four + * types of lines: + * Blank - May contain whitespace, otherwise empty. + * Comment - First non-whitespace character is a ';' or '#'. + * The remainder of the line is ignored. + * Section - First non-whitespace character is a '['. + * Parameter - The default case. + * + * ------------------------------------------------------------------------ ** + */ + { + int c; + + c = EatWhitespace( InFile ); + while( (EOF != c) && (c > 0) ) + { + switch( c ) + { + case '\n': /* Blank line. */ + c = EatWhitespace( InFile ); + break; + + case ';': /* Comment line. */ + case '#': + c = EatComment( InFile ); + break; + + case '[': /* Section Header. */ + if( !Section( InFile, sfunc, userdata ) ) + return( false ); + c = EatWhitespace( InFile ); + break; + + case '\\': /* Bogus backslash. */ + c = EatWhitespace( InFile ); + break; + + default: /* Parameter line. */ + if( !Parameter( InFile, pfunc, c, userdata ) ) + return( false ); + c = EatWhitespace( InFile ); + break; + } + } + return( true ); + } /* Parse */ + +static myFILE *OpenConfFile( const char *FileName ) + /* ------------------------------------------------------------------------ ** + * Open a configuration file. + * + * Input: FileName - The pathname of the config file to be opened. + * + * Output: A pointer of type (char **) to the lines of the file + * + * ------------------------------------------------------------------------ ** + */ + { + const char *func = "params.c:OpenConfFile() -"; + myFILE *ret; + + ret = talloc(talloc_autofree_context(), myFILE); + if (!ret) return NULL; + + ret->buf = file_load(FileName, &ret->size, ret); + if( NULL == ret->buf ) + { + DEBUG( 1, + ("%s Unable to open configuration file \"%s\":\n\t%s\n", + func, FileName, strerror(errno)) ); + talloc_free(ret); + return NULL; + } + + ret->p = ret->buf; + ret->bufr = NULL; + ret->bSize = 0; + return( ret ); + } /* OpenConfFile */ + +bool pm_process( const char *FileName, + bool (*sfunc)(const char *, void *), + bool (*pfunc)(const char *, const char *, void *), + void *userdata) + /* ------------------------------------------------------------------------ ** + * Process the named parameter file. + * + * Input: FileName - The pathname of the parameter file to be opened. + * sfunc - A pointer to a function that will be called when + * a section name is discovered. + * pfunc - A pointer to a function that will be called when + * a parameter name and value are discovered. + * + * Output: TRUE if the file was successfully parsed, else FALSE. + * + * ------------------------------------------------------------------------ ** + */ + { + int result; + myFILE *InFile; + const char *func = "params.c:pm_process() -"; + + InFile = OpenConfFile( FileName ); /* Open the config file. */ + if( NULL == InFile ) + return( false ); + + DEBUG( 3, ("%s Processing configuration file \"%s\"\n", func, FileName) ); + + if( NULL != InFile->bufr ) /* If we already have a buffer */ + result = Parse( InFile, sfunc, pfunc, userdata ); /* (recursive call), then just */ + /* use it. */ + + else /* If we don't have a buffer */ + { /* allocate one, then parse, */ + InFile->bSize = BUFR_INC; /* then free. */ + InFile->bufr = talloc_array(InFile, char, InFile->bSize ); + if( NULL == InFile->bufr ) + { + DEBUG(0,("%s memory allocation failure.\n", func)); + myfile_close(InFile); + return( false ); + } + result = Parse( InFile, sfunc, pfunc, userdata ); + InFile->bufr = NULL; + InFile->bSize = 0; + } + + myfile_close(InFile); + + if( !result ) /* Generic failure. */ + { + DEBUG(0,("%s Failed. Error returned from params.c:parse().\n", func)); + return( false ); + } + + return( true ); /* Generic success. */ + } /* pm_process */ + +/* -------------------------------------------------------------------------- */ diff --git a/lib/util/safe_string.h b/lib/util/safe_string.h new file mode 100644 index 0000000000..a6c052f874 --- /dev/null +++ b/lib/util/safe_string.h @@ -0,0 +1,44 @@ +/* + Unix SMB/CIFS implementation. + Safe string handling routines. + Copyright (C) Andrew Tridgell 1994-1998 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _SAFE_STRING_H +#define _SAFE_STRING_H + +#ifndef _SPLINT_ /* http://www.splint.org */ +/* Some macros to ensure people don't use buffer overflow vulnerable string + functions. */ + +#ifdef strcpy +#undef strcpy +#endif /* strcpy */ +#define strcpy(dest,src) __ERROR__XX__NEVER_USE_STRCPY___; + +#ifdef strcat +#undef strcat +#endif /* strcat */ +#define strcat(dest,src) __ERROR__XX__NEVER_USE_STRCAT___; + +#ifdef sprintf +#undef sprintf +#endif /* sprintf */ +#define sprintf __ERROR__XX__NEVER_USE_SPRINTF__; + +#endif /* !_SPLINT_ */ + +#endif diff --git a/lib/util/signal.c b/lib/util/signal.c new file mode 100644 index 0000000000..ead947eb5e --- /dev/null +++ b/lib/util/signal.c @@ -0,0 +1,144 @@ +/* + Unix SMB/CIFS implementation. + signal handling functions + + Copyright (C) Andrew Tridgell 1998 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "system/wait.h" + +/** + * @file + * @brief Signal handling + */ + +/**************************************************************************** + Catch child exits and reap the child zombie status. +****************************************************************************/ + +static void sig_cld(int signum) +{ + while (waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0) + ; + + /* + * Turns out it's *really* important not to + * restore the signal handler here if we have real POSIX + * signal handling. If we do, then we get the signal re-delivered + * immediately - hey presto - instant loop ! JRA. + */ + +#if !defined(HAVE_SIGACTION) + CatchSignal(SIGCLD, sig_cld); +#endif +} + +/**************************************************************************** +catch child exits - leave status; +****************************************************************************/ + +static void sig_cld_leave_status(int signum) +{ + /* + * Turns out it's *really* important not to + * restore the signal handler here if we have real POSIX + * signal handling. If we do, then we get the signal re-delivered + * immediately - hey presto - instant loop ! JRA. + */ + +#if !defined(HAVE_SIGACTION) + CatchSignal(SIGCLD, sig_cld_leave_status); +#endif +} + +/** + Block sigs. +**/ + +void BlockSignals(bool block, int signum) +{ +#ifdef HAVE_SIGPROCMASK + sigset_t set; + sigemptyset(&set); + sigaddset(&set,signum); + sigprocmask(block?SIG_BLOCK:SIG_UNBLOCK,&set,NULL); +#elif defined(HAVE_SIGBLOCK) + if (block) { + sigblock(sigmask(signum)); + } else { + sigsetmask(siggetmask() & ~sigmask(signum)); + } +#else + /* yikes! This platform can't block signals? */ + static int done; + if (!done) { + DEBUG(0,("WARNING: No signal blocking available\n")); + done=1; + } +#endif +} + +/** + Catch a signal. This should implement the following semantics: + + 1) The handler remains installed after being called. + 2) The signal should be blocked during handler execution. +**/ + +void (*CatchSignal(int signum,void (*handler)(int )))(int) +{ +#ifdef HAVE_SIGACTION + struct sigaction act; + struct sigaction oldact; + + ZERO_STRUCT(act); + + act.sa_handler = handler; +#ifdef SA_RESTART + /* + * We *want* SIGALRM to interrupt a system call. + */ + if(signum != SIGALRM) + act.sa_flags = SA_RESTART; +#endif + sigemptyset(&act.sa_mask); + sigaddset(&act.sa_mask,signum); + sigaction(signum,&act,&oldact); + return oldact.sa_handler; +#else /* !HAVE_SIGACTION */ + /* FIXME: need to handle sigvec and systems with broken signal() */ + return signal(signum, handler); +#endif +} + +/** + Ignore SIGCLD via whatever means is necessary for this OS. +**/ + +void CatchChild(void) +{ + CatchSignal(SIGCLD, sig_cld); +} + +/** + Catch SIGCLD but leave the child around so it's status can be reaped. +**/ + +void CatchChildLeaveStatus(void) +{ + CatchSignal(SIGCLD, sig_cld_leave_status); +} diff --git a/lib/util/signal.m4 b/lib/util/signal.m4 new file mode 100644 index 0000000000..c6d7f72f68 --- /dev/null +++ b/lib/util/signal.m4 @@ -0,0 +1 @@ +AC_CHECK_FUNCS(sigprocmask sigblock sigaction) diff --git a/lib/util/system.c b/lib/util/system.c new file mode 100644 index 0000000000..9bd1800233 --- /dev/null +++ b/lib/util/system.c @@ -0,0 +1,90 @@ +/* + Unix SMB/CIFS implementation. + Samba system utilities + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 1998-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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "system/network.h" +#include "system/filesys.h" + +/* + The idea is that this file will eventually have wrappers around all + important system calls in samba. The aims are: + + - to enable easier porting by putting OS dependent stuff in here + + - to allow for hooks into other "pseudo-filesystems" + + - to allow easier integration of things like the japanese extensions + + - to support the philosophy of Samba to expose the features of + the OS within the SMB model. In general whatever file/printer/variable + expansions/etc make sense to the OS should be acceptable to Samba. +*/ + +/************************************************************************** +A wrapper for gethostbyname() that tries avoids looking up hostnames +in the root domain, which can cause dial-on-demand links to come up for no +apparent reason. +****************************************************************************/ + +_PUBLIC_ struct hostent *sys_gethostbyname(const char *name) +{ +#ifdef REDUCE_ROOT_DNS_LOOKUPS + char query[256], hostname[256]; + char *domain; + + /* Does this name have any dots in it? If so, make no change */ + + if (strchr(name, '.')) + return(gethostbyname(name)); + + /* Get my hostname, which should have domain name + attached. If not, just do the gethostname on the + original string. + */ + + gethostname(hostname, sizeof(hostname) - 1); + hostname[sizeof(hostname) - 1] = 0; + if ((domain = strchr(hostname, '.')) == NULL) + return(gethostbyname(name)); + + /* Attach domain name to query and do modified query. + If names too large, just do gethostname on the + original string. + */ + + if((strlen(name) + strlen(domain)) >= sizeof(query)) + return(gethostbyname(name)); + + slprintf(query, sizeof(query)-1, "%s%s", name, domain); + return(gethostbyname(query)); +#else /* REDUCE_ROOT_DNS_LOOKUPS */ + return(gethostbyname(name)); +#endif /* REDUCE_ROOT_DNS_LOOKUPS */ +} + +_PUBLIC_ struct in_addr sys_inet_makeaddr(int net, int host) +{ + struct in_addr in; + struct in_addr in2; + in = inet_makeaddr(net, host); + in2.s_addr = in.s_addr; + return in2; +} + diff --git a/lib/util/tests/file.c b/lib/util/tests/file.c new file mode 100644 index 0000000000..3377e833dc --- /dev/null +++ b/lib/util/tests/file.c @@ -0,0 +1,97 @@ +/* + Unix SMB/CIFS implementation. + + util_file testing + + Copyright (C) Jelmer Vernooij 2005 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "system/filesys.h" +#include "torture/torture.h" + +#define TEST_FILENAME "utilfile.test" +#define TEST_LINE1 "This is list line 1..." +#define TEST_LINE2 ".. and this is line 2" +#define TEST_LINE3 "and end of the file" + +#define TEST_DATA TEST_LINE1 "\n" TEST_LINE2 "\n" TEST_LINE3 + +static bool test_file_load_save(struct torture_context *tctx) +{ + size_t len; + char *data; + TALLOC_CTX *mem_ctx = tctx; + + torture_assert(tctx, file_save(TEST_FILENAME, TEST_DATA, strlen(TEST_DATA)), + "saving file"); + + torture_assert_file_contains_text(tctx, TEST_FILENAME, TEST_DATA, + "file contents"); + + data = file_load(TEST_FILENAME, &len, mem_ctx); + torture_assert(tctx, data, "loading file"); + + torture_assert_int_equal(tctx, len, strlen(TEST_DATA), "Length"); + + torture_assert_mem_equal(tctx, data, TEST_DATA, len, "Contents"); + + unlink(TEST_FILENAME); + return true; +} + + +static bool test_afdgets(struct torture_context *tctx) +{ + int fd; + char *line; + TALLOC_CTX *mem_ctx = tctx; + + torture_assert(tctx, file_save(TEST_FILENAME, (const void *)TEST_DATA, + strlen(TEST_DATA)), + "saving file"); + + fd = open(TEST_FILENAME, O_RDONLY); + + torture_assert(tctx, fd != -1, "opening file"); + + line = afdgets(fd, mem_ctx, 8); + torture_assert(tctx, strcmp(line, TEST_LINE1) == 0, "line 1 mismatch"); + + line = afdgets(fd, mem_ctx, 8); + torture_assert(tctx, strcmp(line, TEST_LINE2) == 0, "line 2 mismatch"); + + line = afdgets(fd, mem_ctx, 8); + torture_assert(tctx, strcmp(line, TEST_LINE3) == 0, "line 3 mismatch"); + + close(fd); + + unlink(TEST_FILENAME); + return true; +} + +struct torture_suite *torture_local_util_file(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "FILE"); + + torture_suite_add_simple_test(suite, "file_load_save", + test_file_load_save); + + torture_suite_add_simple_test(suite, "afdgets", + test_afdgets); + + return suite; +} diff --git a/lib/util/tests/genrand.c b/lib/util/tests/genrand.c new file mode 100644 index 0000000000..5fe229c089 --- /dev/null +++ b/lib/util/tests/genrand.c @@ -0,0 +1,65 @@ +/* + Unix SMB/CIFS implementation. + + local testing of random data routines. + + Copyright (C) Jelmer Vernooij + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "torture/torture.h" + +static void dummy_reseed(void *userdata, int *d) +{ + *d = 42; +} + +static bool test_reseed_callback(struct torture_context *tctx) +{ + set_rand_reseed_callback(dummy_reseed, NULL); + return true; +} + +static bool test_check_password_quality(struct torture_context *tctx) +{ + torture_assert(tctx, !check_password_quality(""), "empty password"); + torture_assert(tctx, !check_password_quality("a"), "one char password"); + torture_assert(tctx, !check_password_quality("aaaaaaaaaaaa"), "same char password"); + torture_assert(tctx, !check_password_quality("BLA"), "multiple upcases password"); + torture_assert(tctx, !check_password_quality("123"), "digits only"); + torture_assert(tctx, check_password_quality("A2e"), "valid"); + torture_assert(tctx, check_password_quality("BA2eLi443"), "valid"); + return true; +} + +static bool test_generate_random_str(struct torture_context *tctx) +{ + TALLOC_CTX *mem_ctx = talloc_init(__FUNCTION__); + char *r = generate_random_str(mem_ctx, 10); + torture_assert_int_equal(tctx, strlen(r), 10, "right length generated"); + r = generate_random_str(mem_ctx, 5); + torture_assert_int_equal(tctx, strlen(r), 5, "right length generated"); + return true; +} + +struct torture_suite *torture_local_genrand(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "GENRAND"); + torture_suite_add_simple_test(suite, "reseed_callback", test_reseed_callback); + torture_suite_add_simple_test(suite, "check_password_quality", test_check_password_quality); + torture_suite_add_simple_test(suite, "generate_random_str", test_generate_random_str); + return suite; +} diff --git a/lib/util/tests/idtree.c b/lib/util/tests/idtree.c new file mode 100644 index 0000000000..d89fb8c489 --- /dev/null +++ b/lib/util/tests/idtree.c @@ -0,0 +1,121 @@ +/* + Unix SMB/CIFS implementation. + + local testing of idtree routines. + + Copyright (C) Andrew Tridgell 2004 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "torture/torture.h" + +static bool torture_local_idtree_simple(struct torture_context *tctx) +{ + struct idr_context *idr; + int i, ret; + int *ids; + int *present; + extern int torture_numops; + int n = torture_numops; + TALLOC_CTX *mem_ctx = tctx; + + idr = idr_init(mem_ctx); + + ids = talloc_zero_array(mem_ctx, int, n); + present = talloc_zero_array(mem_ctx, int, n); + + for (i=0;i 2007 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "torture/torture.h" + +static bool test_string_sub_simple(struct torture_context *tctx) +{ + char tmp[100]; + safe_strcpy(tmp, "foobar", sizeof(tmp)); + string_sub(tmp, "foo", "bar", sizeof(tmp)); + torture_assert_str_equal(tctx, tmp, "barbar", "invalid sub"); + return true; +} + +static bool test_string_sub_multiple(struct torture_context *tctx) +{ + char tmp[100]; + safe_strcpy(tmp, "fooblafoo", sizeof(tmp)); + string_sub(tmp, "foo", "bar", sizeof(tmp)); + torture_assert_str_equal(tctx, tmp, "barblabar", "invalid sub"); + return true; +} + +static bool test_string_sub_longer(struct torture_context *tctx) +{ + char tmp[100]; + safe_strcpy(tmp, "foobla", sizeof(tmp)); + string_sub(tmp, "foo", "blie", sizeof(tmp)); + torture_assert_str_equal(tctx, tmp, "bliebla", "invalid sub"); + return true; +} + +static bool test_string_sub_shorter(struct torture_context *tctx) +{ + char tmp[100]; + safe_strcpy(tmp, "foobla", sizeof(tmp)); + string_sub(tmp, "foo", "bl", sizeof(tmp)); + torture_assert_str_equal(tctx, tmp, "blbla", "invalid sub"); + return true; +} + +static bool test_string_sub_special_char(struct torture_context *tctx) +{ + char tmp[100]; + safe_strcpy(tmp, "foobla", sizeof(tmp)); + string_sub(tmp, "foo", "%b;l", sizeof(tmp)); + torture_assert_str_equal(tctx, tmp, "_b_lbla", "invalid sub"); + return true; +} + +static bool test_string_sub_talloc_simple(struct torture_context *tctx) +{ + char *t; + + t = string_sub_talloc(tctx, "foobla", "foo", "bl"); + + torture_assert_str_equal(tctx, t, "blbla", "invalid sub"); + + return true; +} + +static bool test_string_sub_talloc_multiple(struct torture_context *tctx) +{ + char *t; + + t = string_sub_talloc(tctx, "fooblafoo", "foo", "aapnootmies"); + + torture_assert_str_equal(tctx, t, "aapnootmiesblaaapnootmies", + "invalid sub"); + + return true; +} + + + +struct torture_suite *torture_local_util_str(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "STR"); + + torture_suite_add_simple_test(suite, "string_sub_simple", + test_string_sub_simple); + + torture_suite_add_simple_test(suite, "string_sub_multiple", + test_string_sub_multiple); + + torture_suite_add_simple_test(suite, "string_sub_shorter", + test_string_sub_shorter); + + torture_suite_add_simple_test(suite, "string_sub_longer", + test_string_sub_longer); + + torture_suite_add_simple_test(suite, "string_sub_special_chars", + test_string_sub_special_char); + + torture_suite_add_simple_test(suite, "string_sub_talloc_simple", + test_string_sub_talloc_simple); + + torture_suite_add_simple_test(suite, "string_sub_talloc_multiple", + test_string_sub_talloc_multiple); + + return suite; +} diff --git a/lib/util/tests/strlist.c b/lib/util/tests/strlist.c new file mode 100644 index 0000000000..9af26f9e71 --- /dev/null +++ b/lib/util/tests/strlist.c @@ -0,0 +1,103 @@ +/* + Unix SMB/CIFS implementation. + + util_strlist testing + + Copyright (C) Jelmer Vernooij 2005 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "torture/torture.h" + +static const char *test_lists_shell_strings[] = { + "", + "foo", + "foo bar", + "foo bar \"bla \"", + "foo \"\" bla", + "bla \"\"\"\" blie", + NULL +}; + +static bool test_lists_shell(struct torture_context *tctx, + const void *test_data) +{ + const char *data = (const char *)test_data; + const char **ret1, **ret2, *tmp; + bool match = true; + TALLOC_CTX *mem_ctx = tctx; + + ret1 = str_list_make_shell(mem_ctx, data, " "); + tmp = str_list_join_shell(mem_ctx, ret1, ' '); + ret2 = str_list_make_shell(mem_ctx, tmp, " "); + + if ((ret1 == NULL || ret2 == NULL) && ret2 != ret1) { + match = false; + } else { + int j; + for (j = 0; ret1[j] && ret2[j]; j++) { + if (strcmp(ret1[j], ret2[j]) != 0) { + match = false; + break; + } + } + + if (ret1[j] || ret2[j]) + match = false; + } + + torture_assert(tctx, match, talloc_asprintf(tctx, + "str_list_{make,join}_shell: Error double parsing, first run:\n%s\nSecond run: \n%s", data, tmp)); + return true; +} + +static bool test_list_copy(struct torture_context *tctx) +{ + const char **result; + const char *list[] = { "foo", "bar", NULL }; + const char *empty_list[] = { NULL }; + const char **null_list = NULL; + + result = str_list_copy(tctx, list); + torture_assert_int_equal(tctx, str_list_length(result), 2, "list length"); + torture_assert_str_equal(tctx, result[0], "foo", "element 0"); + torture_assert_str_equal(tctx, result[1], "bar", "element 1"); + torture_assert_str_equal(tctx, result[2], NULL, "element 2"); + + result = str_list_copy(tctx, empty_list); + torture_assert_int_equal(tctx, str_list_length(result), 0, "list length"); + torture_assert_str_equal(tctx, result[0], NULL, "element 0"); + + result = str_list_copy(tctx, null_list); + torture_assert(tctx, result == NULL, "result NULL"); + + return true; +} + +struct torture_suite *torture_local_util_strlist(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "STRLIST"); + int i; + + for (i = 0; test_lists_shell_strings[i]; i++) { + torture_suite_add_simple_tcase_const(suite, "lists_shell", + test_lists_shell, &test_lists_shell_strings[i]); + } + + torture_suite_add_simple_test(suite, "list_copy", test_list_copy); + + return suite; +} diff --git a/lib/util/time.c b/lib/util/time.c new file mode 100644 index 0000000000..978d73cc0a --- /dev/null +++ b/lib/util/time.c @@ -0,0 +1,622 @@ +/* + Unix SMB/CIFS implementation. + time handling functions + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "system/time.h" + +/** + * @file + * @brief time handling functions + */ + +#ifndef TIME_T_MIN +/* we use 0 here, because (time_t)-1 means error */ +#define TIME_T_MIN 0 +#endif + +/* + * we use the INT32_MAX here as on 64 bit systems, + * gmtime() fails with INT64_MAX + */ + +#ifndef TIME_T_MAX +#define TIME_T_MAX MIN(INT32_MAX,_TYPE_MAXIMUM(time_t)) +#endif + +/** + External access to time_t_min and time_t_max. +**/ +_PUBLIC_ time_t get_time_t_max(void) +{ + return TIME_T_MAX; +} + +/** +a gettimeofday wrapper +**/ +_PUBLIC_ void GetTimeOfDay(struct timeval *tval) +{ +#ifdef HAVE_GETTIMEOFDAY_TZ + gettimeofday(tval,NULL); +#else + gettimeofday(tval); +#endif +} + + +#define TIME_FIXUP_CONSTANT 11644473600LL + +/** +interpret an 8 byte "filetime" structure to a time_t +It's originally in "100ns units since jan 1st 1601" +**/ +_PUBLIC_ time_t nt_time_to_unix(NTTIME nt) +{ + if (nt == 0) { + return 0; + } + if (nt == -1LL) { + return (time_t)-1; + } + nt += 1000*1000*10/2; + nt /= 1000*1000*10; + nt -= TIME_FIXUP_CONSTANT; + + if (TIME_T_MIN > nt || nt > TIME_T_MAX) { + return 0; + } + + return (time_t)nt; +} + + +/** +put a 8 byte filetime from a time_t +This takes GMT as input +**/ +_PUBLIC_ void unix_to_nt_time(NTTIME *nt, time_t t) +{ + uint64_t t2; + + if (t == (time_t)-1) { + *nt = (NTTIME)-1LL; + return; + } + if (t == 0) { + *nt = 0; + return; + } + + t2 = t; + t2 += TIME_FIXUP_CONSTANT; + t2 *= 1000*1000*10; + + *nt = t2; +} + + +/** +check if it's a null unix time +**/ +_PUBLIC_ bool null_time(time_t t) +{ + return t == 0 || + t == (time_t)0xFFFFFFFF || + t == (time_t)-1; +} + + +/** +check if it's a null NTTIME +**/ +_PUBLIC_ bool null_nttime(NTTIME t) +{ + return t == 0 || t == (NTTIME)-1; +} + +/******************************************************************* + create a 16 bit dos packed date +********************************************************************/ +static uint16_t make_dos_date1(struct tm *t) +{ + uint16_t ret=0; + ret = (((unsigned int)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1); + ret = ((ret&0xFF)<<8) | (t->tm_mday | (((t->tm_mon+1) & 0x7) << 5)); + return ret; +} + +/******************************************************************* + create a 16 bit dos packed time +********************************************************************/ +static uint16_t make_dos_time1(struct tm *t) +{ + uint16_t ret=0; + ret = ((((unsigned int)t->tm_min >> 3)&0x7) | (((unsigned int)t->tm_hour) << 3)); + ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5)); + return ret; +} + +/******************************************************************* + create a 32 bit dos packed date/time from some parameters + This takes a GMT time and returns a packed localtime structure +********************************************************************/ +static uint32_t make_dos_date(time_t unixdate, int zone_offset) +{ + struct tm *t; + uint32_t ret=0; + + if (unixdate == 0) { + return 0; + } + + unixdate -= zone_offset; + + t = gmtime(&unixdate); + if (!t) { + return 0xFFFFFFFF; + } + + ret = make_dos_date1(t); + ret = ((ret&0xFFFF)<<16) | make_dos_time1(t); + + return ret; +} + +/** +put a dos date into a buffer (time/date format) +This takes GMT time and puts local time in the buffer +**/ +_PUBLIC_ void push_dos_date(uint8_t *buf, int offset, time_t unixdate, int zone_offset) +{ + uint32_t x = make_dos_date(unixdate, zone_offset); + SIVAL(buf,offset,x); +} + +/** +put a dos date into a buffer (date/time format) +This takes GMT time and puts local time in the buffer +**/ +_PUBLIC_ void push_dos_date2(uint8_t *buf,int offset,time_t unixdate, int zone_offset) +{ + uint32_t x; + x = make_dos_date(unixdate, zone_offset); + x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16); + SIVAL(buf,offset,x); +} + +/** +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) +**/ +_PUBLIC_ void push_dos_date3(uint8_t *buf,int offset,time_t unixdate, int zone_offset) +{ + if (!null_time(unixdate)) { + unixdate -= zone_offset; + } + SIVAL(buf,offset,unixdate); +} + +/******************************************************************* + interpret a 32 bit dos packed date/time to some parameters +********************************************************************/ +static void interpret_dos_date(uint32_t date,int *year,int *month,int *day,int *hour,int *minute,int *second) +{ + uint32_t p0,p1,p2,p3; + + 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; +} + +/** + create a unix date (int GMT) from a dos date (which is actually in + localtime) +**/ +_PUBLIC_ time_t pull_dos_date(const uint8_t *date_ptr, int zone_offset) +{ + uint32_t dos_date=0; + struct tm t; + time_t ret; + + dos_date = IVAL(date_ptr,0); + + if (dos_date == 0) return (time_t)0; + + interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon, + &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec); + t.tm_isdst = -1; + + ret = timegm(&t); + + ret += zone_offset; + + return ret; +} + +/** +like make_unix_date() but the words are reversed +**/ +_PUBLIC_ time_t pull_dos_date2(const uint8_t *date_ptr, int zone_offset) +{ + uint32_t x,x2; + + x = IVAL(date_ptr,0); + x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16); + SIVAL(&x,0,x2); + + return pull_dos_date((const uint8_t *)&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 +**/ +_PUBLIC_ time_t pull_dos_date3(const uint8_t *date_ptr, int zone_offset) +{ + time_t t = (time_t)IVAL(date_ptr,0); + if (!null_time(t)) { + t += zone_offset; + } + return t; +} + + +/** +return a HTTP/1.0 time string +**/ +_PUBLIC_ char *http_timestring(TALLOC_CTX *mem_ctx, time_t 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); + } + +#ifndef 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); +#endif /* !HAVE_STRFTIME */ + + return buf; +} + +/** + Return the date and time as a string +**/ +_PUBLIC_ char *timestring(TALLOC_CTX *mem_ctx, time_t t) +{ + char *TimeBuf; + char tempTime[80]; + struct tm *tm; + + tm = localtime(&t); + if (!tm) { + return talloc_asprintf(mem_ctx, + "%ld seconds since the Epoch", + (long)t); + } + +#ifdef HAVE_STRFTIME + /* some versions of gcc complain about using %c. This is a bug + in the gcc warning, not a bug in this code. See a recent + strftime() manual page for details. + */ + strftime(tempTime,sizeof(tempTime)-1,"%c %Z",tm); + TimeBuf = talloc_strdup(mem_ctx, tempTime); +#else + TimeBuf = talloc_strdup(mem_ctx, asctime(tm)); +#endif + + return TimeBuf; +} + +/** + return a talloced string representing a NTTIME for human consumption +*/ +_PUBLIC_ const char *nt_time_string(TALLOC_CTX *mem_ctx, NTTIME nt) +{ + time_t t; + if (nt == 0) { + return "NTTIME(0)"; + } + t = nt_time_to_unix(nt); + return timestring(mem_ctx, t); +} + + +/** + put a NTTIME into a packet +*/ +_PUBLIC_ void push_nttime(uint8_t *base, uint16_t offset, NTTIME t) +{ + SBVAL(base, offset, t); +} + +/** + pull a NTTIME from a packet +*/ +_PUBLIC_ NTTIME pull_nttime(uint8_t *base, uint16_t offset) +{ + NTTIME ret = BVAL(base, offset); + return ret; +} + +/** + return (tv1 - tv2) in microseconds +*/ +_PUBLIC_ int64_t usec_time_diff(const struct timeval *tv1, const struct timeval *tv2) +{ + int64_t sec_diff = tv1->tv_sec - tv2->tv_sec; + return (sec_diff * 1000000) + (int64_t)(tv1->tv_usec - tv2->tv_usec); +} + + +/** + return a zero timeval +*/ +_PUBLIC_ struct timeval timeval_zero(void) +{ + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 0; + return tv; +} + +/** + return true if a timeval is zero +*/ +_PUBLIC_ bool timeval_is_zero(const struct timeval *tv) +{ + return tv->tv_sec == 0 && tv->tv_usec == 0; +} + +/** + return a timeval for the current time +*/ +_PUBLIC_ struct timeval timeval_current(void) +{ + struct timeval tv; + GetTimeOfDay(&tv); + return tv; +} + +/** + return a timeval struct with the given elements +*/ +_PUBLIC_ struct timeval timeval_set(uint32_t secs, uint32_t usecs) +{ + struct timeval tv; + tv.tv_sec = secs; + tv.tv_usec = usecs; + return tv; +} + + +/** + return a timeval ofs microseconds after tv +*/ +_PUBLIC_ struct timeval timeval_add(const struct timeval *tv, + uint32_t secs, uint32_t usecs) +{ + struct timeval tv2 = *tv; + const unsigned int million = 1000000; + tv2.tv_sec += secs; + tv2.tv_usec += usecs; + tv2.tv_sec += tv2.tv_usec / million; + tv2.tv_usec = tv2.tv_usec % million; + return tv2; +} + +/** + return the sum of two timeval structures +*/ +struct timeval timeval_sum(const struct timeval *tv1, + const struct timeval *tv2) +{ + return timeval_add(tv1, tv2->tv_sec, tv2->tv_usec); +} + +/** + return a timeval secs/usecs into the future +*/ +_PUBLIC_ struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs) +{ + struct timeval tv = timeval_current(); + return timeval_add(&tv, secs, usecs); +} + +/** + compare two timeval structures. + Return -1 if tv1 < tv2 + Return 0 if tv1 == tv2 + Return 1 if tv1 > tv2 +*/ +_PUBLIC_ int timeval_compare(const struct timeval *tv1, const struct timeval *tv2) +{ + if (tv1->tv_sec > tv2->tv_sec) return 1; + if (tv1->tv_sec < tv2->tv_sec) return -1; + if (tv1->tv_usec > tv2->tv_usec) return 1; + if (tv1->tv_usec < tv2->tv_usec) return -1; + return 0; +} + +/** + return true if a timer is in the past +*/ +_PUBLIC_ bool timeval_expired(const struct timeval *tv) +{ + struct timeval tv2 = timeval_current(); + if (tv2.tv_sec > tv->tv_sec) return true; + if (tv2.tv_sec < tv->tv_sec) return false; + return (tv2.tv_usec >= tv->tv_usec); +} + +/** + return the number of seconds elapsed between two times +*/ +_PUBLIC_ double timeval_elapsed2(const struct timeval *tv1, const struct timeval *tv2) +{ + return (tv2->tv_sec - tv1->tv_sec) + + (tv2->tv_usec - tv1->tv_usec)*1.0e-6; +} + +/** + return the number of seconds elapsed since a given time +*/ +_PUBLIC_ double timeval_elapsed(const struct timeval *tv) +{ + struct timeval tv2 = timeval_current(); + return timeval_elapsed2(tv, &tv2); +} + +/** + return the lesser of two timevals +*/ +_PUBLIC_ struct timeval timeval_min(const struct timeval *tv1, + const struct timeval *tv2) +{ + if (tv1->tv_sec < tv2->tv_sec) return *tv1; + if (tv1->tv_sec > tv2->tv_sec) return *tv2; + if (tv1->tv_usec < tv2->tv_usec) return *tv1; + return *tv2; +} + +/** + return the greater of two timevals +*/ +_PUBLIC_ struct timeval timeval_max(const struct timeval *tv1, + const struct timeval *tv2) +{ + if (tv1->tv_sec > tv2->tv_sec) return *tv1; + if (tv1->tv_sec < tv2->tv_sec) return *tv2; + if (tv1->tv_usec > tv2->tv_usec) return *tv1; + return *tv2; +} + +/** + return the difference between two timevals as a timeval + if tv1 comes after tv2, then return a zero timeval + (this is *tv2 - *tv1) +*/ +_PUBLIC_ struct timeval timeval_until(const struct timeval *tv1, + const struct timeval *tv2) +{ + struct timeval t; + if (timeval_compare(tv1, tv2) >= 0) { + return timeval_zero(); + } + t.tv_sec = tv2->tv_sec - tv1->tv_sec; + if (tv1->tv_usec > tv2->tv_usec) { + t.tv_sec--; + t.tv_usec = 1000000 - (tv1->tv_usec - tv2->tv_usec); + } else { + t.tv_usec = tv2->tv_usec - tv1->tv_usec; + } + return t; +} + + +/** + convert a timeval to a NTTIME +*/ +_PUBLIC_ NTTIME timeval_to_nttime(const struct timeval *tv) +{ + return 10*(tv->tv_usec + + ((TIME_FIXUP_CONSTANT + (uint64_t)tv->tv_sec) * 1000000)); +} + +/** + convert a NTTIME to a timeval +*/ +_PUBLIC_ void nttime_to_timeval(struct timeval *tv, NTTIME t) +{ + if (tv == NULL) return; + + t += 10/2; + t /= 10; + t -= TIME_FIXUP_CONSTANT*1000*1000; + + tv->tv_sec = t / 1000000; + + if (TIME_T_MIN > tv->tv_sec || tv->tv_sec > TIME_T_MAX) { + tv->tv_sec = 0; + tv->tv_usec = 0; + return; + } + + tv->tv_usec = t - tv->tv_sec*1000000; +} + +/******************************************************************* +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 + (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 + */ +_PUBLIC_ int get_time_zone(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); +} + +/** + check if 2 NTTIMEs are equal. +*/ +bool nt_time_equal(NTTIME *t1, NTTIME *t2) +{ + return *t1 == *t2; +} diff --git a/lib/util/time.h b/lib/util/time.h new file mode 100644 index 0000000000..e4008c5782 --- /dev/null +++ b/lib/util/time.h @@ -0,0 +1,232 @@ +/* + Unix SMB/CIFS implementation. + time utility functions + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _SAMBA_TIME_H_ +#define _SAMBA_TIME_H_ + +#ifndef _PUBLIC_ +#define _PUBLIC_ +#endif + +/* 64 bit time (100 nanosec) 1601 - cifs6.txt, section 3.5, page 30, 4 byte aligned */ +typedef uint64_t NTTIME; + +/** + External access to time_t_min and time_t_max. +**/ +_PUBLIC_ time_t get_time_t_max(void); + +/** +a gettimeofday wrapper +**/ +_PUBLIC_ void GetTimeOfDay(struct timeval *tval); + +/** +interpret an 8 byte "filetime" structure to a time_t +It's originally in "100ns units since jan 1st 1601" +**/ +_PUBLIC_ time_t nt_time_to_unix(NTTIME nt); + +/** +put a 8 byte filetime from a time_t +This takes GMT as input +**/ +_PUBLIC_ void unix_to_nt_time(NTTIME *nt, time_t t); + +/** +check if it's a null unix time +**/ +_PUBLIC_ bool null_time(time_t t); + +/** +check if it's a null NTTIME +**/ +_PUBLIC_ bool null_nttime(NTTIME t); + +/** +put a dos date into a buffer (time/date format) +This takes GMT time and puts local time in the buffer +**/ +_PUBLIC_ void push_dos_date(uint8_t *buf, int offset, time_t unixdate, int zone_offset); + +/** +put a dos date into a buffer (date/time format) +This takes GMT time and puts local time in the buffer +**/ +_PUBLIC_ void push_dos_date2(uint8_t *buf,int offset,time_t unixdate, int zone_offset); + +/** +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) +**/ +_PUBLIC_ void push_dos_date3(uint8_t *buf,int offset,time_t unixdate, int zone_offset); + +/** + create a unix date (int GMT) from a dos date (which is actually in + localtime) +**/ +_PUBLIC_ time_t pull_dos_date(const uint8_t *date_ptr, int zone_offset); + +/** +like make_unix_date() but the words are reversed +**/ +_PUBLIC_ time_t pull_dos_date2(const uint8_t *date_ptr, int 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 +**/ +_PUBLIC_ time_t pull_dos_date3(const uint8_t *date_ptr, int zone_offset); + +/** +return a HTTP/1.0 time string +**/ +_PUBLIC_ char *http_timestring(TALLOC_CTX *mem_ctx, time_t t); + +/** + Return the date and time as a string +**/ +_PUBLIC_ char *timestring(TALLOC_CTX *mem_ctx, time_t t); + +/** + return a talloced string representing a NTTIME for human consumption +*/ +_PUBLIC_ const char *nt_time_string(TALLOC_CTX *mem_ctx, NTTIME nt); + +/** + put a NTTIME into a packet +*/ +_PUBLIC_ void push_nttime(uint8_t *base, uint16_t offset, NTTIME t); + +/** + pull a NTTIME from a packet +*/ +_PUBLIC_ NTTIME pull_nttime(uint8_t *base, uint16_t offset); + +/** + parse a nttime as a large integer in a string and return a NTTIME +*/ +_PUBLIC_ NTTIME nttime_from_string(const char *s); + +/** + return (tv1 - tv2) in microseconds +*/ +_PUBLIC_ int64_t usec_time_diff(const struct timeval *tv1, const struct timeval *tv2); + +/** + return a zero timeval +*/ +_PUBLIC_ struct timeval timeval_zero(void); + +/** + return true if a timeval is zero +*/ +_PUBLIC_ bool timeval_is_zero(const struct timeval *tv); + +/** + return a timeval for the current time +*/ +_PUBLIC_ struct timeval timeval_current(void); + +/** + return a timeval struct with the given elements +*/ +_PUBLIC_ struct timeval timeval_set(uint32_t secs, uint32_t usecs); + +/** + return a timeval ofs microseconds after tv +*/ +_PUBLIC_ struct timeval timeval_add(const struct timeval *tv, + uint32_t secs, uint32_t usecs); + +/** + return the sum of two timeval structures +*/ +struct timeval timeval_sum(const struct timeval *tv1, + const struct timeval *tv2); + +/** + return a timeval secs/usecs into the future +*/ +_PUBLIC_ struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs); + +/** + compare two timeval structures. + Return -1 if tv1 < tv2 + Return 0 if tv1 == tv2 + Return 1 if tv1 > tv2 +*/ +_PUBLIC_ int timeval_compare(const struct timeval *tv1, const struct timeval *tv2); + +/** + return true if a timer is in the past +*/ +_PUBLIC_ bool timeval_expired(const struct timeval *tv); + +/** + return the number of seconds elapsed between two times +*/ +_PUBLIC_ double timeval_elapsed2(const struct timeval *tv1, const struct timeval *tv2); + +/** + return the number of seconds elapsed since a given time +*/ +_PUBLIC_ double timeval_elapsed(const struct timeval *tv); + +/** + return the lesser of two timevals +*/ +_PUBLIC_ struct timeval timeval_min(const struct timeval *tv1, + const struct timeval *tv2); + +/** + return the greater of two timevals +*/ +_PUBLIC_ struct timeval timeval_max(const struct timeval *tv1, + const struct timeval *tv2); + +/** + return the difference between two timevals as a timeval + if tv1 comes after tv2, then return a zero timeval + (this is *tv2 - *tv1) +*/ +_PUBLIC_ struct timeval timeval_until(const struct timeval *tv1, + const struct timeval *tv2); + +/** + convert a timeval to a NTTIME +*/ +_PUBLIC_ NTTIME timeval_to_nttime(const struct timeval *tv); + +/** + convert a NTTIME to a timeval +*/ +_PUBLIC_ void nttime_to_timeval(struct timeval *tv, NTTIME t); + +/** + return the UTC offset in seconds west of UTC, or 0 if it cannot be determined + */ +_PUBLIC_ int get_time_zone(time_t t); + +/** + check if 2 NTTIMEs are equal. +*/ +bool nt_time_equal(NTTIME *t1, NTTIME *t2); + +#endif /* _SAMBA_TIME_H_ */ diff --git a/lib/util/time.m4 b/lib/util/time.m4 new file mode 100644 index 0000000000..f61ae4cd25 --- /dev/null +++ b/lib/util/time.m4 @@ -0,0 +1,9 @@ +AC_CACHE_CHECK([if gettimeofday takes tz argument],samba_cv_HAVE_GETTIMEOFDAY_TZ,[ +AC_TRY_RUN([ +#include +#include +main() { struct timeval tv; exit(gettimeofday(&tv, NULL));}], + samba_cv_HAVE_GETTIMEOFDAY_TZ=yes,samba_cv_HAVE_GETTIMEOFDAY_TZ=no,samba_cv_HAVE_GETTIMEOFDAY_TZ=cross)]) +if test x"$samba_cv_HAVE_GETTIMEOFDAY_TZ" = x"yes"; then + AC_DEFINE(HAVE_GETTIMEOFDAY_TZ,1,[Whether gettimeofday() is available]) +fi diff --git a/lib/util/unix_privs.c b/lib/util/unix_privs.c new file mode 100644 index 0000000000..47c172dcfa --- /dev/null +++ b/lib/util/unix_privs.c @@ -0,0 +1,77 @@ +/* + Unix SMB/CIFS implementation. + + gain/lose root privileges + + Copyright (C) Andrew Tridgell 2004 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "system/filesys.h" + +/** + * @file + * @brief Gaining/losing root privileges + */ + +/* + there are times when smbd needs to temporarily gain root privileges + to do some operation. To do this you call root_privileges(), which + returns a talloc handle. To restore your previous privileges + talloc_free() this pointer. + + Note that this call is considered successful even if it does not + manage to gain root privileges, but it will call smb_abort() if it + fails to restore the privileges afterwards. The logic is that + failing to gain root access can be caught by whatever operation + needs to be run as root failing, but failing to lose the root + privileges is dangerous. + + This also means that this code is safe to be called from completely + unprivileged processes. +*/ + +struct saved_state { + uid_t uid; +}; + +static int privileges_destructor(struct saved_state *s) +{ + if (geteuid() != s->uid && + seteuid(s->uid) != 0) { + smb_panic("Failed to restore privileges"); + } + return 0; +} + +/** + * Obtain root privileges for the current process. + * + * The privileges can be dropped by talloc_free()-ing the + * token returned by this function + */ +void *root_privileges(void) +{ + struct saved_state *s; + s = talloc(NULL, struct saved_state); + if (!s) return NULL; + s->uid = geteuid(); + if (s->uid != 0) { + seteuid(0); + } + talloc_set_destructor(s, privileges_destructor); + return s; +} diff --git a/lib/util/util.c b/lib/util/util.c new file mode 100644 index 0000000000..5fc785d642 --- /dev/null +++ b/lib/util/util.c @@ -0,0 +1,608 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 2001-2002 + Copyright (C) Simo Sorce 2001 + Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003. + Copyright (C) James J Myers 2003 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "system/network.h" +#include "system/filesys.h" +#include "system/locale.h" + +/** + * @file + * @brief Misc utility functions + */ + +/** + Find a suitable temporary directory. The result should be copied immediately + as it may be overwritten by a subsequent call. +**/ +_PUBLIC_ const char *tmpdir(void) +{ + char *p; + if ((p = getenv("TMPDIR"))) + return p; + return "/tmp"; +} + + +/** + Check if a file exists - call vfs_file_exist for samba files. +**/ +_PUBLIC_ bool file_exist(const char *fname) +{ + struct stat st; + + if (stat(fname, &st) != 0) { + return false; + } + + return ((S_ISREG(st.st_mode)) || (S_ISFIFO(st.st_mode))); +} + +/** + Check a files mod time. +**/ + +_PUBLIC_ time_t file_modtime(const char *fname) +{ + struct stat st; + + if (stat(fname,&st) != 0) + return(0); + + return(st.st_mtime); +} + +/** + Check if a directory exists. +**/ + +_PUBLIC_ bool directory_exist(const char *dname) +{ + struct stat st; + bool ret; + + if (stat(dname,&st) != 0) { + return false; + } + + ret = S_ISDIR(st.st_mode); + if(!ret) + errno = ENOTDIR; + return ret; +} + +/** + * Try to create the specified directory if it didn't exist. + * + * @retval true if the directory already existed and has the right permissions + * or was successfully created. + */ +_PUBLIC_ bool directory_create_or_exist(const char *dname, uid_t uid, + mode_t dir_perms) +{ + mode_t old_umask; + struct stat st; + + old_umask = umask(0); + if (lstat(dname, &st) == -1) { + if (errno == ENOENT) { + /* Create directory */ + if (mkdir(dname, dir_perms) == -1) { + DEBUG(0, ("error creating directory " + "%s: %s\n", dname, + strerror(errno))); + umask(old_umask); + return false; + } + } else { + DEBUG(0, ("lstat failed on directory %s: %s\n", + dname, strerror(errno))); + umask(old_umask); + return false; + } + } else { + /* Check ownership and permission on existing directory */ + if (!S_ISDIR(st.st_mode)) { + DEBUG(0, ("directory %s isn't a directory\n", + dname)); + umask(old_umask); + return false; + } + if ((st.st_uid != uid) || + ((st.st_mode & 0777) != dir_perms)) { + DEBUG(0, ("invalid permissions on directory " + "%s\n", dname)); + umask(old_umask); + return false; + } + } + return true; +} + + +/** + Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available, + else + if SYSV use O_NDELAY + if BSD use FNDELAY +**/ + +_PUBLIC_ int set_blocking(int fd, bool set) +{ + int val; +#ifdef O_NONBLOCK +#define FLAG_TO_SET O_NONBLOCK +#else +#ifdef SYSV +#define FLAG_TO_SET O_NDELAY +#else /* BSD */ +#define FLAG_TO_SET FNDELAY +#endif +#endif + + if((val = fcntl(fd, F_GETFL, 0)) == -1) + return -1; + if(set) /* Turn blocking on - ie. clear nonblock flag */ + val &= ~FLAG_TO_SET; + else + val |= FLAG_TO_SET; + return fcntl( fd, F_SETFL, val); +#undef FLAG_TO_SET +} + + +/** + Sleep for a specified number of milliseconds. +**/ + +_PUBLIC_ void msleep(unsigned int t) +{ + struct timeval tval; + + tval.tv_sec = t/1000; + tval.tv_usec = 1000*(t%1000); + /* this should be the real select - do NOT replace + with sys_select() */ + select(0,NULL,NULL,NULL,&tval); +} + +/** + Get my own name, return in malloc'ed storage. +**/ + +_PUBLIC_ char *get_myname(void) +{ + char *hostname; + char *p; + + hostname = (char *)malloc(MAXHOSTNAMELEN+1); + *hostname = 0; + + /* get my host name */ + if (gethostname(hostname, MAXHOSTNAMELEN+1) == -1) { + DEBUG(0,("gethostname failed\n")); + return NULL; + } + + /* Ensure null termination. */ + hostname[MAXHOSTNAMELEN] = '\0'; + + /* split off any parts after an initial . */ + p = strchr(hostname, '.'); + + if (p != NULL) + *p = 0; + + return hostname; +} + +/** + Return true if a string could be a pure IP address. +**/ + +_PUBLIC_ bool is_ipaddress(const char *str) +{ + bool pure_address = true; + int i; + + if (str == NULL) return false; + + for (i=0; pure_address && str[i]; i++) + if (!(isdigit((int)str[i]) || str[i] == '.')) + pure_address = false; + + /* Check that a pure number is not misinterpreted as an IP */ + pure_address = pure_address && (strchr(str, '.') != NULL); + + return pure_address; +} + +/** + Interpret an internet address or name into an IP address in 4 byte form. +**/ +_PUBLIC_ uint32_t interpret_addr(const char *str) +{ + struct hostent *hp; + uint32_t res; + + if (str == NULL || *str == 0 || + strcmp(str,"0.0.0.0") == 0) { + return 0; + } + if (strcmp(str,"255.255.255.255") == 0) { + return 0xFFFFFFFF; + } + /* recognise 'localhost' as a special name. This fixes problems with + some hosts that don't have localhost in /etc/hosts */ + if (strcasecmp(str,"localhost") == 0) { + str = "127.0.0.1"; + } + + /* if it's in the form of an IP address then get the lib to interpret it */ + if (is_ipaddress(str)) { + res = inet_addr(str); + } else { + /* otherwise assume it's a network name of some sort and use + sys_gethostbyname */ + if ((hp = sys_gethostbyname(str)) == 0) { + DEBUG(3,("sys_gethostbyname: Unknown host. %s\n",str)); + return 0; + } + + if(hp->h_addr == NULL) { + DEBUG(3,("sys_gethostbyname: host address is invalid for host %s\n",str)); + return 0; + } + memcpy((char *)&res,(char *)hp->h_addr, 4); + } + + if (res == (uint32_t)-1) + return(0); + + return(res); +} + +/** + A convenient addition to interpret_addr(). +**/ +_PUBLIC_ struct in_addr interpret_addr2(const char *str) +{ + struct in_addr ret; + uint32_t a = interpret_addr(str); + ret.s_addr = a; + return ret; +} + +/** + Check if an IP is the 0.0.0.0. +**/ + +_PUBLIC_ bool is_zero_ip(struct in_addr ip) +{ + return ip.s_addr == 0; +} + +/** + Are two IPs on the same subnet? +**/ + +_PUBLIC_ bool same_net(struct in_addr ip1, struct in_addr ip2, struct in_addr mask) +{ + uint32_t net1,net2,nmask; + + nmask = ntohl(mask.s_addr); + net1 = ntohl(ip1.s_addr); + net2 = ntohl(ip2.s_addr); + + return((net1 & nmask) == (net2 & nmask)); +} + + +/** + Check if a process exists. Does this work on all unixes? +**/ + +_PUBLIC_ bool process_exists(pid_t pid) +{ + /* Doing kill with a non-positive pid causes messages to be + * sent to places we don't want. */ + SMB_ASSERT(pid > 0); + return(kill(pid,0) == 0 || errno != ESRCH); +} + +/** + Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping + is dealt with in posix.c +**/ + +_PUBLIC_ bool fcntl_lock(int fd, int op, off_t offset, off_t count, int type) +{ + struct flock lock; + int ret; + + DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type)); + + lock.l_type = type; + lock.l_whence = SEEK_SET; + lock.l_start = offset; + lock.l_len = count; + lock.l_pid = 0; + + ret = fcntl(fd,op,&lock); + + if (ret == -1 && errno != 0) + DEBUG(3,("fcntl_lock: fcntl lock gave errno %d (%s)\n",errno,strerror(errno))); + + /* a lock query */ + if (op == F_GETLK) { + if ((ret != -1) && + (lock.l_type != F_UNLCK) && + (lock.l_pid != 0) && + (lock.l_pid != getpid())) { + DEBUG(3,("fcntl_lock: fd %d is locked by pid %d\n",fd,(int)lock.l_pid)); + return true; + } + + /* it must be not locked or locked by me */ + return false; + } + + /* a lock set or unset */ + if (ret == -1) { + DEBUG(3,("fcntl_lock: lock failed at offset %.0f count %.0f op %d type %d (%s)\n", + (double)offset,(double)count,op,type,strerror(errno))); + return false; + } + + /* everything went OK */ + DEBUG(8,("fcntl_lock: Lock call successful\n")); + + return true; +} + + +static void print_asc(int level, const uint8_t *buf,int len) +{ + int i; + for (i=0;i 0) && + (len > i+16) && + (memcmp(&buf[i], &empty, 16) == 0)) + { + i +=16; + continue; + } + + if (i i+16) && + (memcmp(&buf[i], &empty, 16) == 0)) { + if (!skipped) { + DEBUGADD(level,("skipping zero buffer bytes\n")); + skipped = true; + } + } + } + } + + if (i%16) { + int n; + n = 16 - (i%16); + DEBUGADD(level,(" ")); + if (n>8) DEBUGADD(level,(" ")); + while (n--) DEBUGADD(level,(" ")); + n = MIN(8,i%16); + print_asc(level,&buf[i-(i%16)],n); DEBUGADD(level,( " " )); + n = (i%16) - n; + if (n>0) print_asc(level,&buf[i-n],n); + DEBUGADD(level,("\n")); + } + +} + +/** + * Write dump of binary data to the log file. + * + * The data is only written if the log level is at least level. + */ +_PUBLIC_ void dump_data(int level, const uint8_t *buf, int len) +{ + _dump_data(level, buf, len, false); +} + +/** + * Write dump of binary data to the log file. + * + * The data is only written if the log level is at least level. + * 16 zero bytes in a row are ommited + */ +_PUBLIC_ void dump_data_skip_zeros(int level, const uint8_t *buf, int len) +{ + _dump_data(level, buf, len, true); +} + + +/** + malloc that aborts with smb_panic on fail or zero size. +**/ + +_PUBLIC_ void *smb_xmalloc(size_t size) +{ + void *p; + if (size == 0) + smb_panic("smb_xmalloc: called with zero size.\n"); + if ((p = malloc(size)) == NULL) + smb_panic("smb_xmalloc: malloc fail.\n"); + return p; +} + +/** + Memdup with smb_panic on fail. +**/ + +_PUBLIC_ void *smb_xmemdup(const void *p, size_t size) +{ + void *p2; + p2 = smb_xmalloc(size); + memcpy(p2, p, size); + return p2; +} + +/** + strdup that aborts on malloc fail. +**/ + +_PUBLIC_ char *smb_xstrdup(const char *s) +{ + char *s1 = strdup(s); + if (!s1) + smb_panic("smb_xstrdup: malloc fail\n"); + return s1; +} + + +/** + Like strdup but for memory. +**/ + +_PUBLIC_ void *memdup(const void *p, size_t size) +{ + void *p2; + if (size == 0) + return NULL; + p2 = malloc(size); + if (!p2) + return NULL; + memcpy(p2, p, size); + return p2; +} + +/** + * Write a password to the log file. + * + * @note Only actually does something if DEBUG_PASSWORD was defined during + * compile-time. + */ +_PUBLIC_ void dump_data_pw(const char *msg, const uint8_t * data, size_t len) +{ +#ifdef DEBUG_PASSWORD + DEBUG(11, ("%s", msg)); + if (data != NULL && len > 0) + { + dump_data(11, data, len); + } +#endif +} + + +/** + * see if a range of memory is all zero. A NULL pointer is considered + * to be all zero + */ +_PUBLIC_ bool all_zero(const uint8_t *ptr, size_t size) +{ + int i; + if (!ptr) return true; + for (i=0;i= MAX_MALLOC_SIZE/el_size) { + return NULL; + } + if (!ptr) { + return malloc(el_size * count); + } + return realloc(ptr, el_size * count); +} + +/**************************************************************************** + Type-safe malloc. +****************************************************************************/ + +void *malloc_array(size_t el_size, unsigned int count) +{ + return realloc_array(NULL, el_size, count); +} + +_PUBLIC_ void *talloc_check_name_abort(const void *ptr, const char *name) +{ + void *result; + + result = talloc_check_name(ptr, name); + if (result != NULL) + return result; + + DEBUG(0, ("Talloc type mismatch, expected %s, got %s\n", + name, talloc_get_name(ptr))); + smb_panic("talloc type mismatch"); + /* Keep the compiler happy */ + return NULL; +} + diff --git a/lib/util/util.h b/lib/util/util.h new file mode 100644 index 0000000000..4616de9f94 --- /dev/null +++ b/lib/util/util.h @@ -0,0 +1,813 @@ +/* + Unix SMB/CIFS implementation. + Utility functions for Samba + Copyright (C) Andrew Tridgell 1992-1999 + Copyright (C) Jelmer Vernooij 2005 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _SAMBA_UTIL_H_ +#define _SAMBA_UTIL_H_ + +#include "../lib/util/attr.h" + +#include "charset/charset.h" + +/* for TALLOC_CTX */ +#include + +/** + * @file + * @brief Helpful macros + */ + +struct smbsrv_tcon; + +extern const char *logfile; +extern const char *panic_action; + +#include "../lib/util/time.h" +#include "../lib/util/data_blob.h" +#include "../lib/util/xfile.h" +#include "../lib/util/debug.h" +#include "../lib/util/mutex.h" +#include "../lib/util/byteorder.h" + +/** + this is a warning hack. The idea is to use this everywhere that we + get the "discarding const" warning from gcc. That doesn't actually + fix the problem of course, but it means that when we do get to + cleaning them up we can do it by searching the code for + discard_const. + + It also means that other error types aren't as swamped by the noise + of hundreds of const warnings, so we are more likely to notice when + we get new errors. + + Please only add more uses of this macro when you find it + _really_ hard to fix const warnings. Our aim is to eventually use + this function in only a very few places. + + Also, please call this via the discard_const_p() macro interface, as that + makes the return type safe. +*/ +#ifndef discard_const +#define discard_const(ptr) ((void *)((uintptr_t)(ptr))) +#endif + +/** Type-safe version of discard_const */ +#ifndef discard_const_p +#define discard_const_p(type, ptr) ((type *)discard_const(ptr)) +#endif + +/** + * assert macros + */ +#define SMB_ASSERT(b) do { if (!(b)) { \ + DEBUG(0,("PANIC: assert failed at %s(%d)\n", __FILE__, __LINE__)); \ + smb_panic("assert failed"); }} while (0) + +#ifndef SAFE_FREE /* Oh no this is also defined in tdb.h */ +/** + * Free memory if the pointer and zero the pointer. + * + * @note You are explicitly allowed to pass NULL pointers -- they will + * always be ignored. + **/ +#define SAFE_FREE(x) do { if ((x) != NULL) {free(discard_const_p(void *, (x))); (x)=NULL;} } while(0) +#endif + +/** + * Type-safe version of malloc. Allocated one copy of the + * specified data type. + */ +#define malloc_p(type) (type *)malloc(sizeof(type)) + +/** + * Allocate an array of elements of one data type. Does type-checking. + */ +#define malloc_array_p(type, count) (type *)realloc_array(NULL, sizeof(type), count) + +/** + * Resize an array of elements of one data type. Does type-checking. + */ +#define realloc_p(p, type, count) (type *)realloc_array(p, sizeof(type), count) + +#if defined(VALGRIND) +#define strlen(x) valgrind_strlen(x) +#endif + +/** + * zero a structure + */ +#ifndef ZERO_STRUCT +#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x)) +#endif + +/** + * zero a structure given a pointer to the structure + */ +#ifndef ZERO_STRUCTP +#define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0) +#endif + +/** + * zero a structure given a pointer to the structure - no zero check + */ +#ifndef ZERO_STRUCTPN +#define ZERO_STRUCTPN(x) memset((char *)(x), 0, sizeof(*(x))) +#endif + +/* zero an array - note that sizeof(array) must work - ie. it must not be a + pointer */ +#ifndef ZERO_ARRAY +#define ZERO_ARRAY(x) memset((char *)(x), 0, sizeof(x)) +#endif + +/** + * work out how many elements there are in a static array + */ +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) +#endif + +/** + * pointer difference macro + */ +#ifndef PTR_DIFF +#define PTR_DIFF(p1,p2) ((ptrdiff_t)(((const char *)(p1)) - (const char *)(p2))) +#endif + +/* The following definitions come from lib/util/fault.c */ + + +/** + * Write backtrace to debug log + */ +_PUBLIC_ void call_backtrace(void); + +/** + Something really nasty happened - panic ! +**/ +_PUBLIC_ _NORETURN_ void smb_panic(const char *why); + +/** +setup our fault handlers +**/ +_PUBLIC_ void fault_setup(const char *pname); + +/** + register a fault handler. + Should only be called once in the execution of smbd. +*/ +_PUBLIC_ bool register_fault_handler(const char *name, void (*fault_handler)(int sig)); + +/* The following definitions come from lib/util/signal.c */ + + +/** + Block sigs. +**/ +void BlockSignals(bool block, int signum); + +/** + Catch a signal. This should implement the following semantics: + + 1) The handler remains installed after being called. + 2) The signal should be blocked during handler execution. +**/ +void (*CatchSignal(int signum,void (*handler)(int )))(int); + +/** + Ignore SIGCLD via whatever means is necessary for this OS. +**/ +void CatchChild(void); + +/** + Catch SIGCLD but leave the child around so it's status can be reaped. +**/ +void CatchChildLeaveStatus(void); + +/* The following definitions come from lib/util/system.c */ + + +struct in_addr; + +/************************************************************************** +A wrapper for gethostbyname() that tries avoids looking up hostnames +in the root domain, which can cause dial-on-demand links to come up for no +apparent reason. +****************************************************************************/ +_PUBLIC_ struct hostent *sys_gethostbyname(const char *name); +_PUBLIC_ struct in_addr sys_inet_makeaddr(int net, int host); + +/* The following definitions come from lib/util/genrand.c */ + +/** + Copy any user given reseed data. +**/ +_PUBLIC_ void set_rand_reseed_callback(void (*fn)(void *, int *), void *); + +/** + * Tell the random number generator it needs to reseed. + */ +_PUBLIC_ void set_need_random_reseed(void); + +/** + Interface to the (hopefully) good crypto random number generator. + Will use our internal PRNG if more than 40 bytes of random generation + has been requested, otherwise tries to read from /dev/random +**/ +_PUBLIC_ void generate_random_buffer(uint8_t *out, int len); + +/** + Interface to the (hopefully) good crypto random number generator. + Will always use /dev/urandom if available. +**/ +_PUBLIC_ void generate_secret_buffer(uint8_t *out, int len); + +/** + generate a single random uint32_t +**/ +_PUBLIC_ uint32_t generate_random(void); + +/** + very basic password quality checker +**/ +_PUBLIC_ bool check_password_quality(const char *s); + +/** + Use the random number generator to generate a random string. +**/ +_PUBLIC_ char *generate_random_str_list(TALLOC_CTX *mem_ctx, size_t len, const char *list); + +/** + * Generate a random text string consisting of the specified length. + * The returned string will be allocated. + * + * Characters used are: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#., + */ +_PUBLIC_ char *generate_random_str(TALLOC_CTX *mem_ctx, size_t len); + +/* The following definitions come from lib/util/dprintf.c */ + +_PUBLIC_ void d_set_iconv(smb_iconv_t); +_PUBLIC_ int d_vfprintf(FILE *f, const char *format, va_list ap) PRINTF_ATTRIBUTE(2,0); +_PUBLIC_ int d_fprintf(FILE *f, const char *format, ...) PRINTF_ATTRIBUTE(2,3); +_PUBLIC_ int d_printf(const char *format, ...) PRINTF_ATTRIBUTE(1,2); +_PUBLIC_ void display_set_stderr(void); + +/* The following definitions come from lib/util/util_str.c */ + + +/** + Trim the specified elements off the front and back of a string. +**/ +_PUBLIC_ bool trim_string(char *s, const char *front, const char *back); + +/** + Find the number of 'c' chars in a string +**/ +_PUBLIC_ _PURE_ size_t count_chars(const char *s, char c); + +/** + Safe string copy into a known length string. maxlength does not + include the terminating zero. +**/ +_PUBLIC_ char *safe_strcpy(char *dest,const char *src, size_t maxlength); + +/** + Safe string cat into a string. maxlength does not + include the terminating zero. +**/ +_PUBLIC_ char *safe_strcat(char *dest, const char *src, size_t maxlength); + +/** + Routine to get hex characters and turn them into a 16 byte array. + the array can be variable length, and any non-hex-numeric + characters are skipped. "0xnn" or "0Xnn" is specially catered + for. + + valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n" + + +**/ +_PUBLIC_ size_t strhex_to_str(char *p, size_t len, const char *strhex); + +/** + * Parse a hex string and return a data blob. + */ +_PUBLIC_ _PURE_ DATA_BLOB strhex_to_data_blob(const char *strhex) ; + +/** + * Routine to print a buffer as HEX digits, into an allocated string. + */ +_PUBLIC_ void hex_encode(const unsigned char *buff_in, size_t len, char **out_hex_buffer); + +/** + * talloc version of hex_encode() + */ +_PUBLIC_ char *hex_encode_talloc(TALLOC_CTX *mem_ctx, const unsigned char *buff_in, size_t len); + +/** + Substitute a string for a pattern in another string. Make sure there is + enough room! + + This routine looks for pattern in s and replaces it with + insert. It may do multiple replacements. + + Any of " ; ' $ or ` in the insert string are replaced with _ + if len==0 then the string cannot be extended. This is different from the old + use of len==0 which was for no length checks to be done. +**/ +_PUBLIC_ void string_sub(char *s,const char *pattern, const char *insert, size_t len); + + +_PUBLIC_ char *string_sub_talloc(TALLOC_CTX *mem_ctx, const char *s, + const char *pattern, const char *insert); + +/** + Similar to string_sub() but allows for any character to be substituted. + Use with caution! + if len==0 then the string cannot be extended. This is different from the old + use of len==0 which was for no length checks to be done. +**/ +_PUBLIC_ void all_string_sub(char *s,const char *pattern,const char *insert, size_t len); + +/** + Unescape a URL encoded string, in place. +**/ +_PUBLIC_ void rfc1738_unescape(char *buf); +size_t valgrind_strlen(const char *s); + +/** + format a string into length-prefixed dotted domain format, as used in NBT + and in some ADS structures +**/ +_PUBLIC_ const char *str_format_nbt_domain(TALLOC_CTX *mem_ctx, const char *s); + +/** + * Add a string to an array of strings. + * + * num should be a pointer to an integer that holds the current + * number of elements in strings. It will be updated by this function. + */ +_PUBLIC_ bool add_string_to_array(TALLOC_CTX *mem_ctx, + const char *str, const char ***strings, int *num); + +/** + varient of strcmp() that handles NULL ptrs +**/ +_PUBLIC_ int strcmp_safe(const char *s1, const char *s2); + +/** +return the number of bytes occupied by a buffer in ASCII format +the result includes the null termination +limited by 'n' bytes +**/ +_PUBLIC_ size_t ascii_len_n(const char *src, size_t n); + +/** + Return a string representing a CIFS attribute for a file. +**/ +_PUBLIC_ char *attrib_string(TALLOC_CTX *mem_ctx, uint32_t attrib); + +/** + Set a boolean variable from the text value stored in the passed string. + Returns true in success, false if the passed string does not correctly + represent a boolean. +**/ +_PUBLIC_ bool set_boolean(const char *boolean_string, bool *boolean); + +/** + * Parse a string containing a boolean value. + * + * val will be set to the read value. + * + * @retval true if a boolean value was parsed, false otherwise. + */ +_PUBLIC_ bool conv_str_bool(const char * str, bool * val); + +/** + * Convert a size specification like 16K into an integral number of bytes. + **/ +_PUBLIC_ bool conv_str_size(const char * str, uint64_t * val); + +/** + * Parse a uint64_t value from a string + * + * val will be set to the value read. + * + * @retval true if parsing was successful, false otherwise + */ +_PUBLIC_ bool conv_str_u64(const char * str, uint64_t * val); + +/** +return the number of bytes occupied by a buffer in CH_UTF16 format +the result includes the null termination +**/ +_PUBLIC_ size_t utf16_len(const void *buf); + +/** +return the number of bytes occupied by a buffer in CH_UTF16 format +the result includes the null termination +limited by 'n' bytes +**/ +_PUBLIC_ size_t utf16_len_n(const void *src, size_t n); +_PUBLIC_ size_t ucs2_align(const void *base_ptr, const void *p, int flags); + +/** +Do a case-insensitive, whitespace-ignoring string compare. +**/ +_PUBLIC_ int strwicmp(const char *psz1, const char *psz2); + +/** + String replace. +**/ +_PUBLIC_ void string_replace(char *s, char oldc, char newc); + +/** + * Compare 2 strings. + * + * @note The comparison is case-insensitive. + **/ +_PUBLIC_ bool strequal(const char *s1, const char *s2); + +/* The following definitions come from lib/util/util_strlist.c */ + + +/** + build a null terminated list of strings from a input string and a + separator list. The separator list must contain characters less than + or equal to 0x2f for this to work correctly on multi-byte strings +*/ +_PUBLIC_ const char **str_list_make(TALLOC_CTX *mem_ctx, const char *string, const char *sep); + +/** + * build a null terminated list of strings from an argv-like input string + * Entries are seperated by spaces and can be enclosed by quotes. + * Does NOT support escaping + */ +_PUBLIC_ const char **str_list_make_shell(TALLOC_CTX *mem_ctx, const char *string, const char *sep); + +/** + * join a list back to one string + */ +_PUBLIC_ char *str_list_join(TALLOC_CTX *mem_ctx, const char **list, char seperator); + +/** join a list back to one (shell-like) string; entries + * seperated by spaces, using quotes where necessary */ +_PUBLIC_ char *str_list_join_shell(TALLOC_CTX *mem_ctx, const char **list, char sep); + +/** + return the number of elements in a string list +*/ +_PUBLIC_ size_t str_list_length(const char **list); + +/** + copy a string list +*/ +_PUBLIC_ const char **str_list_copy(TALLOC_CTX *mem_ctx, const char **list); + +/** + Return true if all the elements of the list match exactly. + */ +_PUBLIC_ bool str_list_equal(const char **list1, const char **list2); + +/** + add an entry to a string list +*/ +_PUBLIC_ const char **str_list_add(const char **list, const char *s); + +/** + remove an entry from a string list +*/ +_PUBLIC_ void str_list_remove(const char **list, const char *s); + +/** + return true if a string is in a list +*/ +_PUBLIC_ bool str_list_check(const char **list, const char *s); + +/** + return true if a string is in a list, case insensitively +*/ +_PUBLIC_ bool str_list_check_ci(const char **list, const char *s); + +/* The following definitions come from lib/util/util_file.c */ + + +/** +read a line from a file with possible \ continuation chars. +Blanks at the start or end of a line are stripped. +The string will be allocated if s2 is NULL +**/ +_PUBLIC_ char *fgets_slash(char *s2,int maxlen,XFILE *f); + +/** + * Read one line (data until next newline or eof) and allocate it + */ +_PUBLIC_ char *afdgets(int fd, TALLOC_CTX *mem_ctx, size_t hint); + +/** +load a file into memory from a fd. +**/ +_PUBLIC_ char *fd_load(int fd, size_t *size, TALLOC_CTX *mem_ctx); + +/** +load a file into memory +**/ +_PUBLIC_ char *file_load(const char *fname, size_t *size, TALLOC_CTX *mem_ctx); + +/** +mmap (if possible) or read a file +**/ +_PUBLIC_ void *map_file(const char *fname, size_t size); + +/** +load a file into memory and return an array of pointers to lines in the file +must be freed with talloc_free(). +**/ +_PUBLIC_ char **file_lines_load(const char *fname, int *numlines, TALLOC_CTX *mem_ctx); + +/** +load a fd into memory and return an array of pointers to lines in the file +must be freed with talloc_free(). If convert is true calls unix_to_dos on +the list. +**/ +_PUBLIC_ char **fd_lines_load(int fd, int *numlines, TALLOC_CTX *mem_ctx); + +/** +take a list of lines and modify them to produce a list where \ continues +a line +**/ +_PUBLIC_ void file_lines_slashcont(char **lines); + +/** + save a lump of data into a file. Mostly used for debugging +*/ +_PUBLIC_ bool file_save(const char *fname, const void *packet, size_t length); +_PUBLIC_ int vfdprintf(int fd, const char *format, va_list ap) PRINTF_ATTRIBUTE(2,0); +_PUBLIC_ int fdprintf(int fd, const char *format, ...) PRINTF_ATTRIBUTE(2,3); +_PUBLIC_ bool large_file_support(const char *path); + +/* The following definitions come from lib/util/util.c */ + + +/** + Find a suitable temporary directory. The result should be copied immediately + as it may be overwritten by a subsequent call. +**/ +_PUBLIC_ const char *tmpdir(void); + +/** + Check if a file exists - call vfs_file_exist for samba files. +**/ +_PUBLIC_ bool file_exist(const char *fname); + +/** + Check a files mod time. +**/ +_PUBLIC_ time_t file_modtime(const char *fname); + +/** + Check if a directory exists. +**/ +_PUBLIC_ bool directory_exist(const char *dname); + +/** + * Try to create the specified directory if it didn't exist. + * + * @retval true if the directory already existed and has the right permissions + * or was successfully created. + */ +_PUBLIC_ bool directory_create_or_exist(const char *dname, uid_t uid, + mode_t dir_perms); + +/** + Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available, + else + if SYSV use O_NDELAY + if BSD use FNDELAY +**/ +_PUBLIC_ int set_blocking(int fd, bool set); + +/** + Sleep for a specified number of milliseconds. +**/ +_PUBLIC_ void msleep(unsigned int t); + +/** + Get my own name, return in malloc'ed storage. +**/ +_PUBLIC_ char* get_myname(void); + +/** + Return true if a string could be a pure IP address. +**/ +_PUBLIC_ bool is_ipaddress(const char *str); + +/** + Interpret an internet address or name into an IP address in 4 byte form. +**/ +_PUBLIC_ uint32_t interpret_addr(const char *str); + +/** + A convenient addition to interpret_addr(). +**/ +_PUBLIC_ struct in_addr interpret_addr2(const char *str); + +/** + Check if an IP is the 0.0.0.0. +**/ +_PUBLIC_ bool is_zero_ip(struct in_addr ip); + +/** + Are two IPs on the same subnet? +**/ +_PUBLIC_ bool same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask); + +/** + Check if a process exists. Does this work on all unixes? +**/ +_PUBLIC_ bool process_exists(pid_t pid); + +/** + Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping + is dealt with in posix.c +**/ +_PUBLIC_ bool fcntl_lock(int fd, int op, off_t offset, off_t count, int type); + +/** + * Write dump of binary data to the log file. + * + * The data is only written if the log level is at least level. + */ +_PUBLIC_ void dump_data(int level, const uint8_t *buf,int len); + +/** + * Write dump of binary data to the log file. + * + * The data is only written if the log level is at least level. + * 16 zero bytes in a row are ommited + */ +_PUBLIC_ void dump_data_skip_zeros(int level, const uint8_t *buf, int len); + +/** + malloc that aborts with smb_panic on fail or zero size. +**/ +_PUBLIC_ void *smb_xmalloc(size_t size); + +/** + Memdup with smb_panic on fail. +**/ +_PUBLIC_ void *smb_xmemdup(const void *p, size_t size); + +/** + strdup that aborts on malloc fail. +**/ +_PUBLIC_ char *smb_xstrdup(const char *s); + +/** + Like strdup but for memory. +**/ +_PUBLIC_ void *memdup(const void *p, size_t size); + +/** + * Write a password to the log file. + * + * @note Only actually does something if DEBUG_PASSWORD was defined during + * compile-time. + */ +_PUBLIC_ void dump_data_pw(const char *msg, const uint8_t * data, size_t len); + +/** + * see if a range of memory is all zero. A NULL pointer is considered + * to be all zero + */ +_PUBLIC_ bool all_zero(const uint8_t *ptr, size_t size); + +/** + realloc an array, checking for integer overflow in the array size +*/ +_PUBLIC_ void *realloc_array(void *ptr, size_t el_size, unsigned count); + +/* The following definitions come from lib/util/fsusage.c */ + + +/** + * Retrieve amount of free disk space. + * this does all of the system specific guff to get the free disk space. + * It is derived from code in the GNU fileutils package, but has been + * considerably mangled for use here + * + * results are returned in *dfree and *dsize, in 512 byte units +*/ +_PUBLIC_ int sys_fsusage(const char *path, uint64_t *dfree, uint64_t *dsize); + +/* The following definitions come from lib/util/ms_fnmatch.c */ + + +/** + * @file + * @brief MS-style Filename matching + */ + +/* protocol types. It assumes that higher protocols include lower protocols + as subsets. FIXME: Move to one of the smb-specific headers */ +enum protocol_types { + PROTOCOL_NONE, + PROTOCOL_CORE, + PROTOCOL_COREPLUS, + PROTOCOL_LANMAN1, + PROTOCOL_LANMAN2, + PROTOCOL_NT1, + PROTOCOL_SMB2 +}; + +int ms_fnmatch(const char *pattern, const char *string, enum protocol_types protocol); + +/** a generic fnmatch function - uses for non-CIFS pattern matching */ +int gen_fnmatch(const char *pattern, const char *string); + +/* The following definitions come from lib/util/mutex.c */ + + +/** + register a set of mutex/rwlock handlers. + Should only be called once in the execution of smbd. +*/ +_PUBLIC_ bool register_mutex_handlers(const char *name, struct mutex_ops *ops); + +/* The following definitions come from lib/util/idtree.c */ + + +/** + initialise a idr tree. The context return value must be passed to + all subsequent idr calls. To destroy the idr tree use talloc_free() + on this context + */ +_PUBLIC_ struct idr_context *idr_init(TALLOC_CTX *mem_ctx); + +/** + allocate the next available id, and assign 'ptr' into its slot. + you can retrieve later this pointer using idr_find() +*/ +_PUBLIC_ int idr_get_new(struct idr_context *idp, void *ptr, int limit); + +/** + allocate a new id, giving the first available value greater than or + equal to the given starting id +*/ +_PUBLIC_ int idr_get_new_above(struct idr_context *idp, void *ptr, int starting_id, int limit); + +/** + allocate a new id randomly in the given range +*/ +_PUBLIC_ int idr_get_new_random(struct idr_context *idp, void *ptr, int limit); + +/** + find a pointer value previously set with idr_get_new given an id +*/ +_PUBLIC_ void *idr_find(struct idr_context *idp, int id); + +/** + remove an id from the idr tree +*/ +_PUBLIC_ int idr_remove(struct idr_context *idp, int id); + +/* The following definitions come from lib/util/become_daemon.c */ + +/** + Become a daemon, discarding the controlling terminal. +**/ +_PUBLIC_ void become_daemon(bool fork); + +/** + * Load a ini-style file. + */ +bool pm_process( const char *fileName, + bool (*sfunc)(const char *, void *), + bool (*pfunc)(const char *, const char *, void *), + void *userdata); + +/** + * Add-on to talloc_get_type + */ +_PUBLIC_ void *talloc_check_name_abort(const void *ptr, const char *name); +#define talloc_get_type_abort(ptr, type) \ + (type *)talloc_check_name_abort(ptr, #type) + +#endif /* _SAMBA_UTIL_H_ */ diff --git a/lib/util/util.m4 b/lib/util/util.m4 new file mode 100644 index 0000000000..9e362954cd --- /dev/null +++ b/lib/util/util.m4 @@ -0,0 +1 @@ +AC_CHECK_FUNCS(setsid) diff --git a/lib/util/util_file.c b/lib/util/util_file.c new file mode 100644 index 0000000000..c3e22196c0 --- /dev/null +++ b/lib/util/util_file.c @@ -0,0 +1,404 @@ +/* + * Unix SMB/CIFS implementation. + * SMB parameters and setup + * Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995. + * + * Added afdgets() Jelmer Vernooij 2005 + * + * 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 3 of the License, or (at your option) + * any later version. + * + * This program 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 General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + */ + +#include "includes.h" +#include "system/shmem.h" +#include "system/filesys.h" + +/** + * @file + * @brief File-related utility functions + */ + +/** +read a line from a file with possible \ continuation chars. +Blanks at the start or end of a line are stripped. +The string will be allocated if s2 is NULL +**/ +_PUBLIC_ char *fgets_slash(char *s2,int maxlen,XFILE *f) +{ + char *s=s2; + int len = 0; + int c; + bool start_of_line = true; + + if (x_feof(f)) + return(NULL); + + if (maxlen <2) return(NULL); + + if (!s2) + { + maxlen = MIN(maxlen,8); + s = (char *)malloc(maxlen); + } + + if (!s) return(NULL); + + *s = 0; + + while (len < maxlen-1) + { + c = x_getc(f); + switch (c) + { + case '\r': + break; + case '\n': + while (len > 0 && s[len-1] == ' ') + { + s[--len] = 0; + } + if (len > 0 && s[len-1] == '\\') + { + s[--len] = 0; + start_of_line = true; + break; + } + return(s); + case EOF: + if (len <= 0 && !s2) + SAFE_FREE(s); + return(len>0?s:NULL); + case ' ': + if (start_of_line) + break; + /* fall through */ + default: + start_of_line = false; + s[len++] = c; + s[len] = 0; + } + if (!s2 && len > maxlen-3) + { + char *t; + + maxlen *= 2; + t = realloc_p(s, char, maxlen); + if (!t) { + DEBUG(0,("fgets_slash: failed to expand buffer!\n")); + SAFE_FREE(s); + return(NULL); + } else s = t; + } + } + return(s); +} + +/** + * Read one line (data until next newline or eof) and allocate it + */ +_PUBLIC_ char *afdgets(int fd, TALLOC_CTX *mem_ctx, size_t hint) +{ + char *data = NULL; + ssize_t alloc_size = 0, offset = 0, ret; + int p; + + if (hint <= 0) hint = 0x100; + + do { + alloc_size += hint; + + data = talloc_realloc(mem_ctx, data, char, alloc_size); + + if (!data) + return NULL; + + ret = read(fd, data + offset, hint); + + if (ret == 0) { + return NULL; + } + + if (ret == -1) { + talloc_free(data); + return NULL; + } + + /* Find newline */ + for (p = 0; p < ret; p++) { + if (data[offset + p] == '\n') + break; + } + + if (p < ret) { + data[offset + p] = '\0'; + + /* Go back to position of newline */ + lseek(fd, p - ret + 1, SEEK_CUR); + return data; + } + + offset += ret; + + } while (ret == hint); + + data[offset] = '\0'; + + return data; +} + + +/** +load a file into memory from a fd. +**/ +_PUBLIC_ char *fd_load(int fd, size_t *size, TALLOC_CTX *mem_ctx) +{ + struct stat sbuf; + char *p; + + if (fstat(fd, &sbuf) != 0) return NULL; + + p = (char *)talloc_size(mem_ctx, sbuf.st_size+1); + if (!p) return NULL; + + if (read(fd, p, sbuf.st_size) != sbuf.st_size) { + talloc_free(p); + return NULL; + } + p[sbuf.st_size] = 0; + + if (size) *size = sbuf.st_size; + + return p; +} + +/** +load a file into memory +**/ +_PUBLIC_ char *file_load(const char *fname, size_t *size, TALLOC_CTX *mem_ctx) +{ + int fd; + char *p; + + if (!fname || !*fname) return NULL; + + fd = open(fname,O_RDONLY); + if (fd == -1) return NULL; + + p = fd_load(fd, size, mem_ctx); + + close(fd); + + return p; +} + + +/** +mmap (if possible) or read a file +**/ +_PUBLIC_ void *map_file(const char *fname, size_t size) +{ + size_t s2 = 0; + void *p = NULL; +#ifdef HAVE_MMAP + int fd; + fd = open(fname, O_RDONLY, 0); + if (fd == -1) { + DEBUG(2,("Failed to load %s - %s\n", fname, strerror(errno))); + return NULL; + } + p = mmap(NULL, size, PROT_READ, MAP_SHARED|MAP_FILE, fd, 0); + close(fd); + if (p == MAP_FAILED) { + DEBUG(1,("Failed to mmap %s - %s\n", fname, strerror(errno))); + return NULL; + } +#endif + if (!p) { + p = file_load(fname, &s2, talloc_autofree_context()); + if (!p) return NULL; + if (s2 != size) { + DEBUG(1,("incorrect size for %s - got %d expected %d\n", + fname, (int)s2, (int)size)); + talloc_free(p); + return NULL; + } + } + + return p; +} + + +/** +parse a buffer into lines +'p' will be freed on error, and otherwise will be made a child of the returned array +**/ +static char **file_lines_parse(char *p, size_t size, int *numlines, TALLOC_CTX *mem_ctx) +{ + int i; + char *s, **ret; + + if (!p) return NULL; + + for (s = p, i=0; s < p+size; s++) { + if (s[0] == '\n') i++; + } + + ret = talloc_array(mem_ctx, char *, i+2); + if (!ret) { + talloc_free(p); + return NULL; + } + + talloc_steal(ret, p); + + memset(ret, 0, sizeof(ret[0])*(i+2)); + + ret[0] = p; + for (s = p, i=0; s < p+size; s++) { + if (s[0] == '\n') { + s[0] = 0; + i++; + ret[i] = s+1; + } + if (s[0] == '\r') s[0] = 0; + } + + /* remove any blank lines at the end */ + while (i > 0 && ret[i-1][0] == 0) { + i--; + } + + if (numlines) *numlines = i; + + return ret; +} + + +/** +load a file into memory and return an array of pointers to lines in the file +must be freed with talloc_free(). +**/ +_PUBLIC_ char **file_lines_load(const char *fname, int *numlines, TALLOC_CTX *mem_ctx) +{ + char *p; + size_t size; + + p = file_load(fname, &size, mem_ctx); + if (!p) return NULL; + + return file_lines_parse(p, size, numlines, mem_ctx); +} + +/** +load a fd into memory and return an array of pointers to lines in the file +must be freed with talloc_free(). If convert is true calls unix_to_dos on +the list. +**/ +_PUBLIC_ char **fd_lines_load(int fd, int *numlines, TALLOC_CTX *mem_ctx) +{ + char *p; + size_t size; + + p = fd_load(fd, &size, mem_ctx); + if (!p) return NULL; + + return file_lines_parse(p, size, numlines, mem_ctx); +} + + +/** +take a list of lines and modify them to produce a list where \ continues +a line +**/ +_PUBLIC_ void file_lines_slashcont(char **lines) +{ + int i, j; + + for (i=0; lines[i];) { + int len = strlen(lines[i]); + if (lines[i][len-1] == '\\') { + lines[i][len-1] = ' '; + if (lines[i+1]) { + char *p = &lines[i][len]; + while (p < lines[i+1]) *p++ = ' '; + for (j = i+1; lines[j]; j++) lines[j] = lines[j+1]; + } + } else { + i++; + } + } +} + +/** + save a lump of data into a file. Mostly used for debugging +*/ +_PUBLIC_ bool file_save(const char *fname, const void *packet, size_t length) +{ + int fd; + fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0644); + if (fd == -1) { + return false; + } + if (write(fd, packet, length) != (size_t)length) { + return false; + } + close(fd); + return true; +} + +_PUBLIC_ int vfdprintf(int fd, const char *format, va_list ap) +{ + char *p; + int len, ret; + va_list ap2; + + va_copy(ap2, ap); + len = vasprintf(&p, format, ap2); + va_end(ap2); + if (len <= 0) return len; + ret = write(fd, p, len); + SAFE_FREE(p); + return ret; +} + +_PUBLIC_ int fdprintf(int fd, const char *format, ...) +{ + va_list ap; + int ret; + + va_start(ap, format); + ret = vfdprintf(fd, format, ap); + va_end(ap); + return ret; +} + + +/* + try to determine if the filesystem supports large files +*/ +_PUBLIC_ bool large_file_support(const char *path) +{ + int fd; + ssize_t ret; + char c; + + fd = open(path, O_RDWR|O_CREAT, 0600); + unlink(path); + if (fd == -1) { + /* have to assume large files are OK */ + return true; + } + ret = pread(fd, &c, 1, ((uint64_t)1)<<32); + close(fd); + return ret == 0; +} diff --git a/lib/util/util_getent.c b/lib/util/util_getent.c new file mode 100644 index 0000000000..b9b2658f59 --- /dev/null +++ b/lib/util/util_getent.c @@ -0,0 +1,283 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Simo Sorce 2001 + Copyright (C) Jeremy Allison 2001 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" + + +/**************************************************************** + Returns a single linked list of group entries. + Use grent_free() to free it after use. +****************************************************************/ + +struct sys_grent * getgrent_list(void) +{ + struct sys_grent *glist; + struct sys_grent *gent; + struct group *grp; + + gent = malloc_p(struct sys_grent); + if (gent == NULL) { + DEBUG (0, ("Out of memory in getgrent_list!\n")); + return NULL; + } + memset(gent, '\0', sizeof(struct sys_grent)); + glist = gent; + + setgrent(); + grp = getgrent(); + if (grp == NULL) { + endgrent(); + SAFE_FREE(glist); + return NULL; + } + + while (grp != NULL) { + int i,num; + + if (grp->gr_name) { + if ((gent->gr_name = strdup(grp->gr_name)) == NULL) + goto err; + } + if (grp->gr_passwd) { + if ((gent->gr_passwd = strdup(grp->gr_passwd)) == NULL) + goto err; + } + gent->gr_gid = grp->gr_gid; + + /* number of strings in gr_mem */ + for (num = 0; grp->gr_mem[num]; num++) + ; + + /* alloc space for gr_mem string pointers */ + if ((gent->gr_mem = malloc_array_p(char *, num+1)) == NULL) + goto err; + + memset(gent->gr_mem, '\0', (num+1) * sizeof(char *)); + + for (i=0; i < num; i++) { + if ((gent->gr_mem[i] = strdup(grp->gr_mem[i])) == NULL) + goto err; + } + gent->gr_mem[num] = NULL; + + grp = getgrent(); + if (grp) { + gent->next = malloc_p(struct sys_grent); + if (gent->next == NULL) + goto err; + gent = gent->next; + memset(gent, '\0', sizeof(struct sys_grent)); + } + } + + endgrent(); + return glist; + + err: + + endgrent(); + DEBUG(0, ("Out of memory in getgrent_list!\n")); + grent_free(glist); + return NULL; +} + +/**************************************************************** + Free the single linked list of group entries made by + getgrent_list() +****************************************************************/ + +void grent_free (struct sys_grent *glist) +{ + while (glist) { + struct sys_grent *prev; + + SAFE_FREE(glist->gr_name); + SAFE_FREE(glist->gr_passwd); + if (glist->gr_mem) { + int i; + for (i = 0; glist->gr_mem[i]; i++) + SAFE_FREE(glist->gr_mem[i]); + SAFE_FREE(glist->gr_mem); + } + prev = glist; + glist = glist->next; + SAFE_FREE(prev); + } +} + +/**************************************************************** + Returns a single linked list of passwd entries. + Use pwent_free() to free it after use. +****************************************************************/ + +struct sys_pwent * getpwent_list(void) +{ + struct sys_pwent *plist; + struct sys_pwent *pent; + struct passwd *pwd; + + pent = malloc_p(struct sys_pwent); + if (pent == NULL) { + DEBUG (0, ("Out of memory in getpwent_list!\n")); + return NULL; + } + plist = pent; + + setpwent(); + pwd = getpwent(); + while (pwd != NULL) { + memset(pent, '\0', sizeof(struct sys_pwent)); + if (pwd->pw_name) { + if ((pent->pw_name = strdup(pwd->pw_name)) == NULL) + goto err; + } + if (pwd->pw_passwd) { + if ((pent->pw_passwd = strdup(pwd->pw_passwd)) == NULL) + goto err; + } + pent->pw_uid = pwd->pw_uid; + pent->pw_gid = pwd->pw_gid; + if (pwd->pw_gecos) { + if ((pent->pw_name = strdup(pwd->pw_gecos)) == NULL) + goto err; + } + if (pwd->pw_dir) { + if ((pent->pw_name = strdup(pwd->pw_dir)) == NULL) + goto err; + } + if (pwd->pw_shell) { + if ((pent->pw_name = strdup(pwd->pw_shell)) == NULL) + goto err; + } + + pwd = getpwent(); + if (pwd) { + pent->next = malloc_p(struct sys_pwent); + if (pent->next == NULL) + goto err; + pent = pent->next; + } + } + + endpwent(); + return plist; + + err: + + endpwent(); + DEBUG(0, ("Out of memory in getpwent_list!\n")); + pwent_free(plist); + return NULL; +} + +/**************************************************************** + Free the single linked list of passwd entries made by + getpwent_list() +****************************************************************/ + +void pwent_free (struct sys_pwent *plist) +{ + while (plist) { + struct sys_pwent *prev; + + SAFE_FREE(plist->pw_name); + SAFE_FREE(plist->pw_passwd); + SAFE_FREE(plist->pw_gecos); + SAFE_FREE(plist->pw_dir); + SAFE_FREE(plist->pw_shell); + + prev = plist; + plist = plist->next; + SAFE_FREE(prev); + } +} + +/**************************************************************** + Add the individual group users onto the list. +****************************************************************/ + +static struct sys_userlist *add_members_to_userlist(struct sys_userlist *list_head, const struct group *grp) +{ + size_t num_users, i; + + /* Count the number of users. */ + for (num_users = 0; grp->gr_mem[num_users]; num_users++) + ; + + for (i = 0; i < num_users; i++) { + struct sys_userlist *entry = malloc_p(struct sys_userlist); + if (entry == NULL) { + free_userlist(list_head); + return NULL; + } + entry->unix_name = (char *)strdup(grp->gr_mem[i]); + if (entry->unix_name == NULL) { + SAFE_FREE(entry); + free_userlist(list_head); + return NULL; + } + DLIST_ADD(list_head, entry); + } + return list_head; +} + +/**************************************************************** + Get the list of UNIX users in a group. + We have to enumerate the /etc/group file as some UNIX getgrnam() + calls won't do that for us (notably Tru64 UNIX). +****************************************************************/ + +struct sys_userlist *get_users_in_group(const char *gname) +{ + struct sys_userlist *list_head = NULL; + struct group *gptr; + +#if !defined(BROKEN_GETGRNAM) + if ((gptr = (struct group *)getgrnam(gname)) == NULL) + return NULL; + return add_members_to_userlist(list_head, gptr); +#else + /* BROKEN_GETGRNAM - True64 */ + setgrent(); + while((gptr = getgrent()) != NULL) { + if (strequal(gname, gptr->gr_name)) { + list_head = add_members_to_userlist(list_head, gptr); + if (list_head == NULL) + return NULL; + } + } + endgrent(); + return list_head; +#endif +} + +/**************************************************************** + Free list allocated above. +****************************************************************/ + +void free_userlist(struct sys_userlist *list_head) +{ + while (list_head) { + struct sys_userlist *old_head = list_head; + DLIST_REMOVE(list_head, list_head); + SAFE_FREE(old_head->unix_name); + SAFE_FREE(old_head); + } +} diff --git a/lib/util/util_ldb.c b/lib/util/util_ldb.c new file mode 100644 index 0000000000..0465022edd --- /dev/null +++ b/lib/util/util_ldb.c @@ -0,0 +1,134 @@ +/* + Unix SMB/CIFS implementation. + + common share info functions + + Copyright (C) Andrew Tridgell 2004 + Copyright (C) Tim Potter 2004 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "lib/events/events.h" +#include "lib/ldb/include/ldb.h" +#include "lib/ldb/include/ldb_errors.h" +#include "lib/util/util_ldb.h" +/* + search the sam for the specified attributes - va_list variant +*/ +int gendb_search_v(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct ldb_dn *basedn, + struct ldb_message ***msgs, + const char * const *attrs, + const char *format, + va_list ap) +{ + enum ldb_scope scope = LDB_SCOPE_SUBTREE; + struct ldb_result *res; + char *expr = NULL; + int ret; + + if (format) { + expr = talloc_vasprintf(mem_ctx, format, ap); + if (expr == NULL) { + return -1; + } + } else { + scope = LDB_SCOPE_BASE; + } + + res = NULL; + + ret = ldb_search(ldb, mem_ctx, &res, basedn, scope, attrs, + expr?"%s":NULL, expr); + + if (ret == LDB_SUCCESS) { + talloc_steal(mem_ctx, res->msgs); + + DEBUG(6,("gendb_search_v: %s %s -> %d\n", + basedn?ldb_dn_get_linearized(basedn):"NULL", + expr?expr:"NULL", res->count)); + + ret = res->count; + *msgs = res->msgs; + talloc_free(res); + } else if (scope == LDB_SCOPE_BASE && ret == LDB_ERR_NO_SUCH_OBJECT) { + ret = 0; + *msgs = NULL; + } else { + DEBUG(4,("gendb_search_v: search failed: %s\n", + ldb_errstring(ldb))); + ret = -1; + } + + talloc_free(expr); + + return ret; +} + +/* + search the LDB for the specified attributes - varargs variant +*/ +int gendb_search(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct ldb_dn *basedn, + struct ldb_message ***res, + const char * const *attrs, + const char *format, ...) +{ + va_list ap; + int count; + + va_start(ap, format); + count = gendb_search_v(ldb, mem_ctx, basedn, res, attrs, format, ap); + va_end(ap); + + return count; +} + +/* + search the LDB for a specified record (by DN) +*/ + +int gendb_search_dn(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct ldb_dn *dn, + struct ldb_message ***res, + const char * const *attrs) +{ + return gendb_search(ldb, mem_ctx, dn, res, attrs, NULL); +} + +/* + setup some initial ldif in a ldb +*/ +int gendb_add_ldif(struct ldb_context *ldb, const char *ldif_string) +{ + struct ldb_ldif *ldif; + int ret; + ldif = ldb_ldif_read_string(ldb, &ldif_string); + if (ldif == NULL) return -1; + ret = ldb_add(ldb, ldif->msg); + talloc_free(ldif); + return ret; +} + +char *wrap_casefold(void *context, void *mem_ctx, const char *s, size_t n) +{ + return strupper_talloc_n(mem_ctx, s, n); +} + + diff --git a/lib/util/util_ldb.h b/lib/util/util_ldb.h new file mode 100644 index 0000000000..43f98ae1a9 --- /dev/null +++ b/lib/util/util_ldb.h @@ -0,0 +1,27 @@ +#ifndef __LIB_UTIL_UTIL_LDB_H__ +#define __LIB_UTIL_UTIL_LDB_H__ + +/* The following definitions come from lib/util/util_ldb.c */ + +int gendb_search_v(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct ldb_dn *basedn, + struct ldb_message ***msgs, + const char * const *attrs, + const char *format, + va_list ap) PRINTF_ATTRIBUTE(6,0); +int gendb_search(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct ldb_dn *basedn, + struct ldb_message ***res, + const char * const *attrs, + const char *format, ...) PRINTF_ATTRIBUTE(6,7); +int gendb_search_dn(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + struct ldb_dn *dn, + struct ldb_message ***res, + const char * const *attrs); +int gendb_add_ldif(struct ldb_context *ldb, const char *ldif_string); +char *wrap_casefold(void *context, void *mem_ctx, const char *s, size_t n); + +#endif /* __LIB_UTIL_UTIL_LDB_H__ */ diff --git a/lib/util/util_pw.c b/lib/util/util_pw.c new file mode 100644 index 0000000000..11e46ec4e3 --- /dev/null +++ b/lib/util/util_pw.c @@ -0,0 +1,77 @@ +/* + Unix SMB/CIFS implementation. + + Safe versions of getpw* calls + + Copyright (C) Andrew Bartlett 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" + +static struct passwd *alloc_copy_passwd(TALLOC_CTX *mem_ctx, + const struct passwd *from) +{ + struct passwd *ret = talloc_zero(mem_ctx, struct passwd); + + if (ret == NULL) + return NULL; + + ret->pw_name = talloc_strdup(ret, from->pw_name); + ret->pw_passwd = talloc_strdup(ret, from->pw_passwd); + ret->pw_uid = from->pw_uid; + ret->pw_gid = from->pw_gid; + ret->pw_gecos = talloc_strdup(ret, from->pw_gecos); + ret->pw_dir = talloc_strdup(ret, from->pw_dir); + ret->pw_shell = talloc_strdup(ret, from->pw_shell); + + return ret; +} + +struct passwd *getpwnam_alloc(TALLOC_CTX *mem_ctx, const char *name) +{ + struct passwd *temp; + + temp = sys_getpwnam(name); + + if (!temp) { +#if 0 + if (errno == ENOMEM) { + /* what now? */ + } +#endif + return NULL; + } + + return alloc_copy_passwd(mem_ctx, temp); +} + +struct passwd *getpwuid_alloc(TALLOC_CTX *mem_ctx, uid_t uid) +{ + struct passwd *temp; + + temp = sys_getpwuid(uid); + + if (!temp) { +#if 0 + if (errno == ENOMEM) { + /* what now? */ + } +#endif + return NULL; + } + + return alloc_copy_passwd(mem_ctx, temp); +} diff --git a/lib/util/util_str.c b/lib/util/util_str.c new file mode 100644 index 0000000000..9ea6403c52 --- /dev/null +++ b/lib/util/util_str.c @@ -0,0 +1,790 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + + Copyright (C) Andrew Tridgell 1992-2001 + Copyright (C) Simo Sorce 2001-2002 + Copyright (C) Martin Pool 2003 + Copyright (C) James Peach 2005 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "libcli/raw/smb.h" +#include "system/locale.h" + +/** + * @file + * @brief String utilities. + **/ + + +/** + Trim the specified elements off the front and back of a string. +**/ +_PUBLIC_ bool trim_string(char *s, const char *front, const char *back) +{ + bool ret = false; + size_t front_len; + size_t back_len; + size_t len; + + /* Ignore null or empty strings. */ + if (!s || (s[0] == '\0')) + return false; + + front_len = front? strlen(front) : 0; + back_len = back? strlen(back) : 0; + + len = strlen(s); + + if (front_len) { + while (len && strncmp(s, front, front_len)==0) { + /* Must use memmove here as src & dest can + * easily overlap. Found by valgrind. JRA. */ + memmove(s, s+front_len, (len-front_len)+1); + len -= front_len; + ret=true; + } + } + + if (back_len) { + while ((len >= back_len) && strncmp(s+len-back_len,back,back_len)==0) { + s[len-back_len]='\0'; + len -= back_len; + ret=true; + } + } + return ret; +} + +/** + Find the number of 'c' chars in a string +**/ +_PUBLIC_ _PURE_ size_t count_chars(const char *s, char c) +{ + size_t count = 0; + + while (*s) { + if (*s == c) count++; + s ++; + } + + return count; +} + + + +/** + Safe string copy into a known length string. maxlength does not + include the terminating zero. +**/ +_PUBLIC_ char *safe_strcpy(char *dest,const char *src, size_t maxlength) +{ + size_t len; + + if (!dest) { + DEBUG(0,("ERROR: NULL dest in safe_strcpy\n")); + return NULL; + } + +#ifdef DEVELOPER + /* We intentionally write out at the extremity of the destination + * string. If the destination is too short (e.g. pstrcpy into mallocd + * or fstring) then this should cause an error under a memory + * checker. */ + dest[maxlength] = '\0'; + if (PTR_DIFF(&len, dest) > 0) { /* check if destination is on the stack, ok if so */ + log_suspicious_usage("safe_strcpy", src); + } +#endif + + if (!src) { + *dest = 0; + return dest; + } + + len = strlen(src); + + if (len > maxlength) { + DEBUG(0,("ERROR: string overflow by %u (%u - %u) in safe_strcpy [%.50s]\n", + (uint_t)(len-maxlength), (unsigned)len, (unsigned)maxlength, src)); + len = maxlength; + } + + memmove(dest, src, len); + dest[len] = 0; + return dest; +} + +/** + Safe string cat into a string. maxlength does not + include the terminating zero. +**/ +_PUBLIC_ char *safe_strcat(char *dest, const char *src, size_t maxlength) +{ + size_t src_len, dest_len; + + if (!dest) { + DEBUG(0,("ERROR: NULL dest in safe_strcat\n")); + return NULL; + } + + if (!src) + return dest; + +#ifdef DEVELOPER + if (PTR_DIFF(&src_len, dest) > 0) { /* check if destination is on the stack, ok if so */ + log_suspicious_usage("safe_strcat", src); + } +#endif + src_len = strlen(src); + dest_len = strlen(dest); + + if (src_len + dest_len > maxlength) { + DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n", + (int)(src_len + dest_len - maxlength), src)); + if (maxlength > dest_len) { + memcpy(&dest[dest_len], src, maxlength - dest_len); + } + dest[maxlength] = 0; + return NULL; + } + + memcpy(&dest[dest_len], src, src_len); + dest[dest_len + src_len] = 0; + return dest; +} + +/** + Routine to get hex characters and turn them into a 16 byte array. + the array can be variable length, and any non-hex-numeric + characters are skipped. "0xnn" or "0Xnn" is specially catered + for. + + valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n" + + +**/ +_PUBLIC_ size_t strhex_to_str(char *p, size_t len, const char *strhex) +{ + size_t i; + size_t num_chars = 0; + uint8_t lonybble, hinybble; + const char *hexchars = "0123456789ABCDEF"; + char *p1 = NULL, *p2 = NULL; + + for (i = 0; i < len && strhex[i] != 0; i++) { + if (strncasecmp(hexchars, "0x", 2) == 0) { + i++; /* skip two chars */ + continue; + } + + if (!(p1 = strchr(hexchars, toupper((unsigned char)strhex[i])))) + break; + + i++; /* next hex digit */ + + if (!(p2 = strchr(hexchars, toupper((unsigned char)strhex[i])))) + break; + + /* get the two nybbles */ + hinybble = PTR_DIFF(p1, hexchars); + lonybble = PTR_DIFF(p2, hexchars); + + p[num_chars] = (hinybble << 4) | lonybble; + num_chars++; + + p1 = NULL; + p2 = NULL; + } + return num_chars; +} + +/** + * Parse a hex string and return a data blob. + */ +_PUBLIC_ _PURE_ DATA_BLOB strhex_to_data_blob(const char *strhex) +{ + DATA_BLOB ret_blob = data_blob(NULL, strlen(strhex)/2+1); + + ret_blob.length = strhex_to_str((char *)ret_blob.data, + strlen(strhex), + strhex); + + return ret_blob; +} + + +/** + * Routine to print a buffer as HEX digits, into an allocated string. + */ +_PUBLIC_ void hex_encode(const unsigned char *buff_in, size_t len, char **out_hex_buffer) +{ + int i; + char *hex_buffer; + + *out_hex_buffer = malloc_array_p(char, (len*2)+1); + hex_buffer = *out_hex_buffer; + + for (i = 0; i < len; i++) + slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]); +} + +/** + * talloc version of hex_encode() + */ +_PUBLIC_ char *hex_encode_talloc(TALLOC_CTX *mem_ctx, const unsigned char *buff_in, size_t len) +{ + int i; + char *hex_buffer; + + hex_buffer = talloc_array(mem_ctx, char, (len*2)+1); + + for (i = 0; i < len; i++) + slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]); + + return hex_buffer; +} + +/** + Substitute a string for a pattern in another string. Make sure there is + enough room! + + This routine looks for pattern in s and replaces it with + insert. It may do multiple replacements. + + Any of " ; ' $ or ` in the insert string are replaced with _ + if len==0 then the string cannot be extended. This is different from the old + use of len==0 which was for no length checks to be done. +**/ + +_PUBLIC_ void string_sub(char *s, const char *pattern, const char *insert, size_t len) +{ + char *p; + ssize_t ls, lp, li, i; + + if (!insert || !pattern || !*pattern || !s) + return; + + ls = (ssize_t)strlen(s); + lp = (ssize_t)strlen(pattern); + li = (ssize_t)strlen(insert); + + if (len == 0) + len = ls + 1; /* len is number of *bytes* */ + + while (lp <= ls && (p = strstr(s, pattern))) { + if (ls + (li-lp) >= len) { + DEBUG(0,("ERROR: string overflow by %d in string_sub(%.50s, %d)\n", + (int)(ls + (li-lp) - len), + pattern, (int)len)); + break; + } + if (li != lp) { + memmove(p+li,p+lp,strlen(p+lp)+1); + } + for (i=0;i= len) { + DEBUG(0,("ERROR: string overflow by %d in all_string_sub(%.50s, %d)\n", + (int)(ls + (li-lp) - len), + pattern, (int)len)); + break; + } + if (li != lp) { + memmove(p+li,p+lp,strlen(p+lp)+1); + } + memcpy(p, insert, li); + s = p + li; + ls += (li-lp); + } +} + + + +/** + Unescape a URL encoded string, in place. +**/ + +_PUBLIC_ void rfc1738_unescape(char *buf) +{ + char *p=buf; + + while ((p=strchr(p,'+'))) + *p = ' '; + + p = buf; + + while (p && *p && (p=strchr(p,'%'))) { + int c1 = p[1]; + int c2 = p[2]; + + if (c1 >= '0' && c1 <= '9') + c1 = c1 - '0'; + else if (c1 >= 'A' && c1 <= 'F') + c1 = 10 + c1 - 'A'; + else if (c1 >= 'a' && c1 <= 'f') + c1 = 10 + c1 - 'a'; + else {p++; continue;} + + if (c2 >= '0' && c2 <= '9') + c2 = c2 - '0'; + else if (c2 >= 'A' && c2 <= 'F') + c2 = 10 + c2 - 'A'; + else if (c2 >= 'a' && c2 <= 'f') + c2 = 10 + c2 - 'a'; + else {p++; continue;} + + *p = (c1<<4) | c2; + + memmove(p+1, p+3, strlen(p+3)+1); + p++; + } +} + +#ifdef VALGRIND +size_t valgrind_strlen(const char *s) +{ + size_t count; + for(count = 0; *s++; count++) + ; + return count; +} +#endif + + +/** + format a string into length-prefixed dotted domain format, as used in NBT + and in some ADS structures +**/ +_PUBLIC_ const char *str_format_nbt_domain(TALLOC_CTX *mem_ctx, const char *s) +{ + char *ret; + int i; + if (!s || !*s) { + return talloc_strdup(mem_ctx, ""); + } + ret = talloc_array(mem_ctx, char, strlen(s)+2); + if (!ret) { + return ret; + } + + memcpy(ret+1, s, strlen(s)+1); + ret[0] = '.'; + + for (i=0;ret[i];i++) { + if (ret[i] == '.') { + char *p = strchr(ret+i+1, '.'); + if (p) { + ret[i] = p-(ret+i+1); + } else { + ret[i] = strlen(ret+i+1); + } + } + } + + return ret; +} + +/** + * Add a string to an array of strings. + * + * num should be a pointer to an integer that holds the current + * number of elements in strings. It will be updated by this function. + */ +_PUBLIC_ bool add_string_to_array(TALLOC_CTX *mem_ctx, + const char *str, const char ***strings, int *num) +{ + char *dup_str = talloc_strdup(mem_ctx, str); + + *strings = talloc_realloc(mem_ctx, + *strings, + const char *, ((*num)+1)); + + if ((*strings == NULL) || (dup_str == NULL)) + return false; + + (*strings)[*num] = dup_str; + *num += 1; + + return true; +} + + + +/** + varient of strcmp() that handles NULL ptrs +**/ +_PUBLIC_ int strcmp_safe(const char *s1, const char *s2) +{ + if (s1 == s2) { + return 0; + } + if (s1 == NULL || s2 == NULL) { + return s1?-1:1; + } + return strcmp(s1, s2); +} + + +/** +return the number of bytes occupied by a buffer in ASCII format +the result includes the null termination +limited by 'n' bytes +**/ +_PUBLIC_ size_t ascii_len_n(const char *src, size_t n) +{ + size_t len; + + len = strnlen(src, n); + if (len+1 <= n) { + len += 1; + } + + return len; +} + + +/** + Return a string representing a CIFS attribute for a file. +**/ +_PUBLIC_ char *attrib_string(TALLOC_CTX *mem_ctx, uint32_t attrib) +{ + int i, len; + const struct { + char c; + uint16_t attr; + } attr_strs[] = { + {'V', FILE_ATTRIBUTE_VOLUME}, + {'D', FILE_ATTRIBUTE_DIRECTORY}, + {'A', FILE_ATTRIBUTE_ARCHIVE}, + {'H', FILE_ATTRIBUTE_HIDDEN}, + {'S', FILE_ATTRIBUTE_SYSTEM}, + {'N', FILE_ATTRIBUTE_NORMAL}, + {'R', FILE_ATTRIBUTE_READONLY}, + {'d', FILE_ATTRIBUTE_DEVICE}, + {'t', FILE_ATTRIBUTE_TEMPORARY}, + {'s', FILE_ATTRIBUTE_SPARSE}, + {'r', FILE_ATTRIBUTE_REPARSE_POINT}, + {'c', FILE_ATTRIBUTE_COMPRESSED}, + {'o', FILE_ATTRIBUTE_OFFLINE}, + {'n', FILE_ATTRIBUTE_NONINDEXED}, + {'e', FILE_ATTRIBUTE_ENCRYPTED} + }; + char *ret; + + ret = talloc_array(mem_ctx, char, ARRAY_SIZE(attr_strs)+1); + if (!ret) { + return NULL; + } + + for (len=i=0; i. +*/ + +#include "includes.h" +#include "system/locale.h" + +/** + * @file + * @brief String list manipulation + */ + +/** + build a null terminated list of strings from a input string and a + separator list. The separator list must contain characters less than + or equal to 0x2f for this to work correctly on multi-byte strings +*/ +_PUBLIC_ const char **str_list_make(TALLOC_CTX *mem_ctx, const char *string, const char *sep) +{ + int num_elements = 0; + const char **ret = NULL; + + if (sep == NULL) { + sep = LIST_SEP; + } + + ret = talloc_array(mem_ctx, const char *, 1); + if (ret == NULL) { + return NULL; + } + + while (string && *string) { + size_t len = strcspn(string, sep); + const char **ret2; + + if (len == 0) { + string += strspn(string, sep); + continue; + } + + ret2 = talloc_realloc(mem_ctx, ret, const char *, num_elements+2); + if (ret2 == NULL) { + talloc_free(ret); + return NULL; + } + ret = ret2; + + ret[num_elements] = talloc_strndup(ret, string, len); + if (ret[num_elements] == NULL) { + talloc_free(ret); + return NULL; + } + + num_elements++; + string += len; + } + + ret[num_elements] = NULL; + + return ret; +} + +/** + * build a null terminated list of strings from an argv-like input string + * Entries are seperated by spaces and can be enclosed by quotes. + * Does NOT support escaping + */ +_PUBLIC_ const char **str_list_make_shell(TALLOC_CTX *mem_ctx, const char *string, const char *sep) +{ + int num_elements = 0; + const char **ret = NULL; + + ret = talloc_array(mem_ctx, const char *, 1); + if (ret == NULL) { + return NULL; + } + + if (sep == NULL) + sep = " \t\n\r"; + + while (string && *string) { + size_t len = strcspn(string, sep); + char *element; + const char **ret2; + + if (len == 0) { + string += strspn(string, sep); + continue; + } + + if (*string == '\"') { + string++; + len = strcspn(string, "\""); + element = talloc_strndup(ret, string, len); + string += len + 1; + } else { + element = talloc_strndup(ret, string, len); + string += len; + } + + if (element == NULL) { + talloc_free(ret); + return NULL; + } + + ret2 = talloc_realloc(mem_ctx, ret, const char *, num_elements+2); + if (ret2 == NULL) { + talloc_free(ret); + return NULL; + } + ret = ret2; + + ret[num_elements] = element; + + num_elements++; + } + + ret[num_elements] = NULL; + + return ret; + +} + +/** + * join a list back to one string + */ +_PUBLIC_ char *str_list_join(TALLOC_CTX *mem_ctx, const char **list, char seperator) +{ + char *ret = NULL; + int i; + + if (list[0] == NULL) + return talloc_strdup(mem_ctx, ""); + + ret = talloc_strdup(mem_ctx, list[0]); + + for (i = 1; list[i]; i++) { + ret = talloc_asprintf_append_buffer(ret, "%c%s", seperator, list[i]); + } + + return ret; +} + +/** join a list back to one (shell-like) string; entries + * seperated by spaces, using quotes where necessary */ +_PUBLIC_ char *str_list_join_shell(TALLOC_CTX *mem_ctx, const char **list, char sep) +{ + char *ret = NULL; + int i; + + if (list[0] == NULL) + return talloc_strdup(mem_ctx, ""); + + if (strchr(list[0], ' ') || strlen(list[0]) == 0) + ret = talloc_asprintf(mem_ctx, "\"%s\"", list[0]); + else + ret = talloc_strdup(mem_ctx, list[0]); + + for (i = 1; list[i]; i++) { + if (strchr(list[i], ' ') || strlen(list[i]) == 0) + ret = talloc_asprintf_append_buffer(ret, "%c\"%s\"", sep, list[i]); + else + ret = talloc_asprintf_append_buffer(ret, "%c%s", sep, list[i]); + } + + return ret; +} + +/** + return the number of elements in a string list +*/ +_PUBLIC_ size_t str_list_length(const char **list) +{ + size_t ret; + for (ret=0;list && list[ret];ret++) /* noop */ ; + return ret; +} + + +/** + copy a string list +*/ +_PUBLIC_ const char **str_list_copy(TALLOC_CTX *mem_ctx, const char **list) +{ + int i; + const char **ret; + + if (list == NULL) + return NULL; + + ret = talloc_array(mem_ctx, const char *, str_list_length(list)+1); + if (ret == NULL) + return NULL; + + for (i=0;list && list[i];i++) { + ret[i] = talloc_strdup(ret, list[i]); + if (ret[i] == NULL) { + talloc_free(ret); + return NULL; + } + } + ret[i] = NULL; + return ret; +} + +/** + Return true if all the elements of the list match exactly. + */ +_PUBLIC_ bool str_list_equal(const char **list1, const char **list2) +{ + int i; + + if (list1 == NULL || list2 == NULL) { + return (list1 == list2); + } + + for (i=0;list1[i] && list2[i];i++) { + if (strcmp(list1[i], list2[i]) != 0) { + return false; + } + } + if (list1[i] || list2[i]) { + return false; + } + return true; +} + + +/** + add an entry to a string list +*/ +_PUBLIC_ const char **str_list_add(const char **list, const char *s) +{ + size_t len = str_list_length(list); + const char **ret; + + ret = talloc_realloc(NULL, list, const char *, len+2); + if (ret == NULL) return NULL; + + ret[len] = talloc_strdup(ret, s); + if (ret[len] == NULL) return NULL; + + ret[len+1] = NULL; + + return ret; +} + +/** + remove an entry from a string list +*/ +_PUBLIC_ void str_list_remove(const char **list, const char *s) +{ + int i; + + for (i=0;list[i];i++) { + if (strcmp(list[i], s) == 0) break; + } + if (!list[i]) return; + + for (;list[i];i++) { + list[i] = list[i+1]; + } +} + + +/** + return true if a string is in a list +*/ +_PUBLIC_ bool str_list_check(const char **list, const char *s) +{ + int i; + + for (i=0;list[i];i++) { + if (strcmp(list[i], s) == 0) return true; + } + return false; +} + +/** + return true if a string is in a list, case insensitively +*/ +_PUBLIC_ bool str_list_check_ci(const char **list, const char *s) +{ + int i; + + for (i=0;list[i];i++) { + if (strcasecmp(list[i], s) == 0) return true; + } + return false; +} + + diff --git a/lib/util/util_tdb.c b/lib/util/util_tdb.c new file mode 100644 index 0000000000..e89085a31b --- /dev/null +++ b/lib/util/util_tdb.c @@ -0,0 +1,546 @@ +/* + Unix SMB/CIFS implementation. + + tdb utility functions + + Copyright (C) Andrew Tridgell 1992-2006 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "../tdb/include/tdb.h" +#include "pstring.h" +#include "lib/util/util_tdb.h" + +/* these are little tdb utility functions that are meant to make + dealing with a tdb database a little less cumbersome in Samba */ + +/*************************************************************** + Make a TDB_DATA and keep the const warning in one place +****************************************************************/ + +static TDB_DATA make_tdb_data(const char *dptr, size_t dsize) +{ + TDB_DATA ret; + ret.dptr = discard_const_p(unsigned char, dptr); + ret.dsize = dsize; + return ret; +} + +/**************************************************************************** + Lock a chain by string. Return -1 if lock failed. +****************************************************************************/ + +int tdb_lock_bystring(struct tdb_context *tdb, const char *keyval) +{ + TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + + return tdb_chainlock(tdb, key); +} + +/**************************************************************************** + Unlock a chain by string. +****************************************************************************/ + +void tdb_unlock_bystring(struct tdb_context *tdb, const char *keyval) +{ + TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + + tdb_chainunlock(tdb, key); +} + +/**************************************************************************** + Read lock a chain by string. Return -1 if lock failed. +****************************************************************************/ + +int tdb_read_lock_bystring(struct tdb_context *tdb, const char *keyval) +{ + TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + + return tdb_chainlock_read(tdb, key); +} + +/**************************************************************************** + Read unlock a chain by string. +****************************************************************************/ + +void tdb_read_unlock_bystring(struct tdb_context *tdb, const char *keyval) +{ + TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); + + tdb_chainunlock_read(tdb, key); +} + + +/**************************************************************************** + Fetch a int32_t value by a arbitrary blob key, return -1 if not found. + Output is int32_t in native byte order. +****************************************************************************/ + +int32_t tdb_fetch_int32_byblob(struct tdb_context *tdb, const char *keyval, size_t len) +{ + TDB_DATA key = make_tdb_data(keyval, len); + TDB_DATA data; + int32_t ret; + + data = tdb_fetch(tdb, key); + if (!data.dptr || data.dsize != sizeof(int32_t)) { + SAFE_FREE(data.dptr); + return -1; + } + + ret = IVAL(data.dptr,0); + SAFE_FREE(data.dptr); + return ret; +} + +/**************************************************************************** + Fetch a int32_t value by string key, return -1 if not found. + Output is int32_t in native byte order. +****************************************************************************/ + +int32_t tdb_fetch_int32(struct tdb_context *tdb, const char *keystr) +{ + return tdb_fetch_int32_byblob(tdb, keystr, strlen(keystr) + 1); +} + +/**************************************************************************** + Store a int32_t value by an arbitary blob key, return 0 on success, -1 on failure. + Input is int32_t in native byte order. Output in tdb is in little-endian. +****************************************************************************/ + +int tdb_store_int32_byblob(struct tdb_context *tdb, const char *keystr, size_t len, int32_t v) +{ + TDB_DATA key = make_tdb_data(keystr, len); + TDB_DATA data; + int32_t v_store; + + SIVAL(&v_store,0,v); + data.dptr = (unsigned char *)&v_store; + data.dsize = sizeof(int32_t); + + return tdb_store(tdb, key, data, TDB_REPLACE); +} + +/**************************************************************************** + Store a int32_t value by string key, return 0 on success, -1 on failure. + Input is int32_t in native byte order. Output in tdb is in little-endian. +****************************************************************************/ + +int tdb_store_int32(struct tdb_context *tdb, const char *keystr, int32_t v) +{ + return tdb_store_int32_byblob(tdb, keystr, strlen(keystr) + 1, v); +} + +/**************************************************************************** + Fetch a uint32_t value by a arbitrary blob key, return -1 if not found. + Output is uint32_t in native byte order. +****************************************************************************/ + +bool tdb_fetch_uint32_byblob(struct tdb_context *tdb, const char *keyval, size_t len, uint32_t *value) +{ + TDB_DATA key = make_tdb_data(keyval, len); + TDB_DATA data; + + data = tdb_fetch(tdb, key); + if (!data.dptr || data.dsize != sizeof(uint32_t)) { + SAFE_FREE(data.dptr); + return false; + } + + *value = IVAL(data.dptr,0); + SAFE_FREE(data.dptr); + return true; +} + +/**************************************************************************** + Fetch a uint32_t value by string key, return -1 if not found. + Output is uint32_t in native byte order. +****************************************************************************/ + +bool tdb_fetch_uint32(struct tdb_context *tdb, const char *keystr, uint32_t *value) +{ + return tdb_fetch_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value); +} + +/**************************************************************************** + Store a uint32_t value by an arbitary blob key, return 0 on success, -1 on failure. + Input is uint32_t in native byte order. Output in tdb is in little-endian. +****************************************************************************/ + +bool tdb_store_uint32_byblob(struct tdb_context *tdb, const char *keystr, size_t len, uint32_t value) +{ + TDB_DATA key = make_tdb_data(keystr, len); + TDB_DATA data; + uint32_t v_store; + bool ret = true; + + SIVAL(&v_store, 0, value); + data.dptr = (unsigned char *)&v_store; + data.dsize = sizeof(uint32_t); + + if (tdb_store(tdb, key, data, TDB_REPLACE) == -1) + ret = false; + + return ret; +} + +/**************************************************************************** + Store a uint32_t value by string key, return 0 on success, -1 on failure. + Input is uint32_t in native byte order. Output in tdb is in little-endian. +****************************************************************************/ + +bool tdb_store_uint32(struct tdb_context *tdb, const char *keystr, uint32_t value) +{ + return tdb_store_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value); +} +/**************************************************************************** + Store a buffer by a null terminated string key. Return 0 on success, -1 + on failure. +****************************************************************************/ + +int tdb_store_bystring(struct tdb_context *tdb, const char *keystr, TDB_DATA data, int flags) +{ + TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); + + return tdb_store(tdb, key, data, flags); +} + +/**************************************************************************** + Fetch a buffer using a null terminated string key. Don't forget to call + free() on the result dptr. +****************************************************************************/ + +TDB_DATA tdb_fetch_bystring(struct tdb_context *tdb, const char *keystr) +{ + TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); + + return tdb_fetch(tdb, key); +} + +/**************************************************************************** + Delete an entry using a null terminated string key. +****************************************************************************/ + +int tdb_delete_bystring(struct tdb_context *tdb, const char *keystr) +{ + TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); + + return tdb_delete(tdb, key); +} + +/**************************************************************************** + Atomic integer change. Returns old value. To create, set initial value in *oldval. +****************************************************************************/ + +int32_t tdb_change_int32_atomic(struct tdb_context *tdb, const char *keystr, int32_t *oldval, int32_t change_val) +{ + int32_t val; + int32_t ret = -1; + + if (tdb_lock_bystring(tdb, keystr) == -1) + return -1; + + if ((val = tdb_fetch_int32(tdb, keystr)) == -1) { + /* The lookup failed */ + if (tdb_error(tdb) != TDB_ERR_NOEXIST) { + /* but not because it didn't exist */ + goto err_out; + } + + /* Start with 'old' value */ + val = *oldval; + + } else { + /* It worked, set return value (oldval) to tdb data */ + *oldval = val; + } + + /* Increment value for storage and return next time */ + val += change_val; + + if (tdb_store_int32(tdb, keystr, val) == -1) + goto err_out; + + ret = 0; + + err_out: + + tdb_unlock_bystring(tdb, keystr); + return ret; +} + +/**************************************************************************** + Atomic unsigned integer change. Returns old value. To create, set initial value in *oldval. +****************************************************************************/ + +bool tdb_change_uint32_atomic(struct tdb_context *tdb, const char *keystr, uint32_t *oldval, uint32_t change_val) +{ + uint32_t val; + bool ret = false; + + if (tdb_lock_bystring(tdb, keystr) == -1) + return false; + + if (!tdb_fetch_uint32(tdb, keystr, &val)) { + /* It failed */ + if (tdb_error(tdb) != TDB_ERR_NOEXIST) { + /* and not because it didn't exist */ + goto err_out; + } + + /* Start with 'old' value */ + val = *oldval; + + } else { + /* it worked, set return value (oldval) to tdb data */ + *oldval = val; + + } + + /* get a new value to store */ + val += change_val; + + if (!tdb_store_uint32(tdb, keystr, val)) + goto err_out; + + ret = true; + + err_out: + + tdb_unlock_bystring(tdb, keystr); + return ret; +} + +/**************************************************************************** + Allow tdb_delete to be used as a tdb_traversal_fn. +****************************************************************************/ + +int tdb_traverse_delete_fn(struct tdb_context *the_tdb, TDB_DATA key, TDB_DATA dbuf, + void *state) +{ + return tdb_delete(the_tdb, key); +} + + + +/**************************************************************************** + Useful pair of routines for packing/unpacking data consisting of + integers and strings. +****************************************************************************/ + +size_t tdb_pack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) +{ + va_list ap; + uint8_t bt; + uint16_t w; + uint32_t d; + int i; + void *p; + int len; + char *s; + char c; + char *buf0 = buf; + const char *fmt0 = fmt; + int bufsize0 = bufsize; + tdb_log_func log_fn = tdb_log_fn(tdb); + + va_start(ap, fmt); + + while (*fmt) { + switch ((c = *fmt++)) { + case 'b': /* unsigned 8-bit integer */ + len = 1; + bt = (uint8_t)va_arg(ap, int); + if (bufsize && bufsize >= len) + SSVAL(buf, 0, bt); + break; + case 'w': /* unsigned 16-bit integer */ + len = 2; + w = (uint16_t)va_arg(ap, int); + if (bufsize && bufsize >= len) + SSVAL(buf, 0, w); + break; + case 'd': /* signed 32-bit integer (standard int in most systems) */ + len = 4; + d = va_arg(ap, uint32_t); + if (bufsize && bufsize >= len) + SIVAL(buf, 0, d); + break; + case 'p': /* pointer */ + len = 4; + p = va_arg(ap, void *); + d = p?1:0; + if (bufsize && bufsize >= len) + SIVAL(buf, 0, d); + break; + case 'P': /* null-terminated string */ + s = va_arg(ap,char *); + w = strlen(s); + len = w + 1; + if (bufsize && bufsize >= len) + memcpy(buf, s, len); + break; + case 'f': /* null-terminated string */ + s = va_arg(ap,char *); + w = strlen(s); + len = w + 1; + if (bufsize && bufsize >= len) + memcpy(buf, s, len); + break; + case 'B': /* fixed-length string */ + i = va_arg(ap, int); + s = va_arg(ap, char *); + len = 4+i; + if (bufsize && bufsize >= len) { + SIVAL(buf, 0, i); + memcpy(buf+4, s, i); + } + break; + default: + log_fn(tdb, 0,"Unknown tdb_pack format %c in %s\n", + c, fmt); + len = 0; + break; + } + + buf += len; + if (bufsize) + bufsize -= len; + if (bufsize < 0) + bufsize = 0; + } + + va_end(ap); + + log_fn(tdb, 18,"tdb_pack(%s, %d) -> %d\n", + fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)); + + return PTR_DIFF(buf, buf0); +} + +/**************************************************************************** + Useful pair of routines for packing/unpacking data consisting of + integers and strings. +****************************************************************************/ + +int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) +{ + va_list ap; + uint8_t *bt; + uint16_t *w; + uint32_t *d; + int len; + int *i; + void **p; + char *s, **b, **ps; + char c; + char *buf0 = buf; + const char *fmt0 = fmt; + int bufsize0 = bufsize; + tdb_log_func log_fn = tdb_log_fn(tdb); + + va_start(ap, fmt); + + while (*fmt) { + switch ((c=*fmt++)) { + case 'b': + len = 1; + bt = va_arg(ap, uint8_t *); + if (bufsize < len) + goto no_space; + *bt = SVAL(buf, 0); + break; + case 'w': + len = 2; + w = va_arg(ap, uint16_t *); + if (bufsize < len) + goto no_space; + *w = SVAL(buf, 0); + break; + case 'd': + len = 4; + d = va_arg(ap, uint32_t *); + if (bufsize < len) + goto no_space; + *d = IVAL(buf, 0); + break; + case 'p': + len = 4; + p = va_arg(ap, void **); + if (bufsize < len) + goto no_space; + + /* + * This isn't a real pointer - only a token (1 or 0) + * to mark the fact a pointer is present. + */ + + *p = (void *)(IVAL(buf, 0) ? (void *)1 : NULL); + break; + case 'P': + /* Return a malloc'ed string. */ + ps = va_arg(ap,char ** ); + len = strlen((const char *)buf) + 1; + *ps = strdup((const char *)buf); + break; + case 'f': + s = va_arg(ap,char *); + len = strlen(buf) + 1; + if (bufsize < len || len > sizeof(fstring)) + goto no_space; + memcpy(s, buf, len); + break; + case 'B': + i = va_arg(ap, int *); + b = va_arg(ap, char **); + len = 4; + if (bufsize < len) + goto no_space; + *i = IVAL(buf, 0); + if (! *i) { + *b = NULL; + break; + } + len += *i; + if (bufsize < len) + goto no_space; + *b = (char *)malloc(*i); + if (! *b) + goto no_space; + memcpy(*b, buf+4, *i); + break; + default: + log_fn(tdb, 0, "Unknown tdb_unpack format %c in %s\n", + c, fmt); + + len = 0; + break; + } + + buf += len; + bufsize -= len; + } + + va_end(ap); + + log_fn(tdb, 18, "tdb_unpack(%s, %d) -> %d\n", + fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)); + + return PTR_DIFF(buf, buf0); + + no_space: + return -1; +} diff --git a/lib/util/wrap_xattr.c b/lib/util/wrap_xattr.c new file mode 100644 index 0000000000..955f39a7eb --- /dev/null +++ b/lib/util/wrap_xattr.c @@ -0,0 +1,120 @@ +/* + Unix SMB/CIFS implementation. + + POSIX NTVFS backend - xattr support using filesystem xattrs + + Copyright (C) Andrew Tridgell 2004 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "system/filesys.h" +#include "lib/util/wrap_xattr.h" + +#if defined(HAVE_XATTR_SUPPORT) && defined(XATTR_ADDITIONAL_OPTIONS) +static ssize_t _wrap_darwin_fgetxattr(int fd, const char *name, void *value, size_t size) +{ + return fgetxattr(fd, name, value, size, 0, 0); +} +static ssize_t _wrap_darwin_getxattr(const char *path, const char *name, void *value, size_t size) +{ + return getxattr(path, name, value, size, 0, 0); +} +static int _wrap_darwin_fsetxattr(int fd, const char *name, void *value, size_t size, int flags) +{ + return fsetxattr(fd, name, value, size, 0, flags); +} +static int _wrap_darwin_setxattr(const char *path, const char *name, void *value, size_t size, int flags) +{ + return setxattr(path, name, value, size, 0, flags); +} +static int _wrap_darwin_fremovexattr(int fd, const char *name) +{ + return fremovexattr(fd, name, 0); +} +static int _wrap_darwin_removexattr(const char *path, const char *name) +{ + return removexattr(path, name, 0); +} +#define fgetxattr _wrap_darwin_fgetxattr +#define getxattr _wrap_darwin_getxattr +#define fsetxattr _wrap_darwin_fsetxattr +#define setxattr _wrap_darwin_setxattr +#define fremovexattr _wrap_darwin_fremovexattr +#define removexattr _wrap_darwin_removexattr +#elif !defined(HAVE_XATTR_SUPPORT) +static ssize_t _none_fgetxattr(int fd, const char *name, void *value, size_t size) +{ + errno = ENOSYS; + return -1; +} +static ssize_t _none_getxattr(const char *path, const char *name, void *value, size_t size) +{ + errno = ENOSYS; + return -1; +} +static int _none_fsetxattr(int fd, const char *name, void *value, size_t size, int flags) +{ + errno = ENOSYS; + return -1; +} +static int _none_setxattr(const char *path, const char *name, void *value, size_t size, int flags) +{ + errno = ENOSYS; + return -1; +} +static int _none_fremovexattr(int fd, const char *name) +{ + errno = ENOSYS; + return -1; +} +static int _none_removexattr(const char *path, const char *name) +{ + errno = ENOSYS; + return -1; +} +#define fgetxattr _none_fgetxattr +#define getxattr _none_getxattr +#define fsetxattr _none_fsetxattr +#define setxattr _none_setxattr +#define fremovexattr _none_fremovexattr +#define removexattr _none_removexattr +#endif + +_PUBLIC_ ssize_t wrap_fgetxattr(int fd, const char *name, void *value, size_t size) +{ + return fgetxattr(fd, name, value, size); +} +_PUBLIC_ ssize_t wrap_getxattr(const char *path, const char *name, void *value, size_t size) +{ + return getxattr(path, name, value, size); +} +_PUBLIC_ int wrap_fsetxattr(int fd, const char *name, void *value, size_t size, int flags) +{ + return fsetxattr(fd, name, value, size, flags); +} +_PUBLIC_ int wrap_setxattr(const char *path, const char *name, void *value, size_t size, int flags) +{ + return setxattr(path, name, value, size, flags); +} +_PUBLIC_ int wrap_fremovexattr(int fd, const char *name) +{ + return fremovexattr(fd, name); +} +_PUBLIC_ int wrap_removexattr(const char *path, const char *name) +{ + return removexattr(path, name); +} + diff --git a/lib/util/wrap_xattr.h b/lib/util/wrap_xattr.h new file mode 100644 index 0000000000..64b28d250c --- /dev/null +++ b/lib/util/wrap_xattr.h @@ -0,0 +1,12 @@ +#ifndef __LIB_UTIL_WRAP_XATTR_H__ +#define __LIB_UTIL_WRAP_XATTR_H__ + +ssize_t wrap_fgetxattr(int fd, const char *name, void *value, size_t size); +ssize_t wrap_getxattr(const char *path, const char *name, void *value, size_t size); +int wrap_fsetxattr(int fd, const char *name, void *value, size_t size, int flags); +int wrap_setxattr(const char *path, const char *name, void *value, size_t size, int flags); +int wrap_fremovexattr(int fd, const char *name); +int wrap_removexattr(const char *path, const char *name); + +#endif /* __LIB_UTIL_WRAP_XATTR_H__ */ + diff --git a/lib/util/xattr.m4 b/lib/util/xattr.m4 new file mode 100644 index 0000000000..497809a47a --- /dev/null +++ b/lib/util/xattr.m4 @@ -0,0 +1,32 @@ +dnl ############################################ +dnl use flistxattr as the key function for having +dnl sufficient xattr support for posix xattr backend +AC_CHECK_HEADERS(sys/attributes.h attr/xattr.h sys/xattr.h) +AC_SEARCH_LIBS_EXT(flistxattr, [attr], XATTR_LIBS) +AC_CHECK_FUNC_EXT(flistxattr, $XATTR_LIBS) +SMB_EXT_LIB(XATTR,[${XATTR_LIBS}],[${XATTR_CFLAGS}],[${XATTR_CPPFLAGS}],[${XATTR_LDFLAGS}]) +if test x"$ac_cv_func_ext_flistxattr" = x"yes"; then + AC_CACHE_CHECK([whether xattr interface takes additional options], smb_attr_cv_xattr_add_opt, + [old_LIBS=$LIBS + LIBS="$LIBS $XATTRLIBS" + AC_TRY_COMPILE([ + #include + #if HAVE_ATTR_XATTR_H + #include + #elif HAVE_SYS_XATTR_H + #include + #endif + #ifndef NULL + #define NULL ((void *)0) + #endif + ],[ + getxattr(NULL, NULL, NULL, 0, 0, 0); + ],smb_attr_cv_xattr_add_opt=yes,smb_attr_cv_xattr_add_opt=no) + LIBS=$old_LIBS]) + if test x"$smb_attr_cv_xattr_add_opt" = x"yes"; then + AC_DEFINE(XATTR_ADDITIONAL_OPTIONS, 1, [xattr functions have additional options]) + fi + AC_DEFINE(HAVE_XATTR_SUPPORT,1,[Whether we have xattr support]) + SMB_ENABLE(XATTR,YES) +fi + diff --git a/lib/util/xfile.c b/lib/util/xfile.c new file mode 100644 index 0000000000..a016031a77 --- /dev/null +++ b/lib/util/xfile.c @@ -0,0 +1,389 @@ +/* + Unix SMB/CIFS implementation. + stdio replacement + Copyright (C) Andrew Tridgell 2001 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file + * @brief scalable FILE replacement + */ + +/* + stdio is very convenient, but on some systems the file descriptor + in FILE* is 8 bits, so it fails when more than 255 files are open. + + XFILE replaces stdio. It is less efficient, but at least it works + when you have lots of files open + + The main restriction on XFILE is that it doesn't support seeking, + and doesn't support O_RDWR. That keeps the code simple. +*/ + +#include "includes.h" +#include "system/filesys.h" + +#define XBUFSIZE BUFSIZ + +static XFILE _x_stdin = { 0, NULL, NULL, XBUFSIZE, 0, O_RDONLY, X_IOFBF, 0 }; +static XFILE _x_stdout = { 1, NULL, NULL, XBUFSIZE, 0, O_WRONLY, X_IOLBF, 0 }; +static XFILE _x_stderr = { 2, NULL, NULL, 0, 0, O_WRONLY, X_IONBF, 0 }; + +XFILE *x_stdin = &_x_stdin; +XFILE *x_stdout = &_x_stdout; +XFILE *x_stderr = &_x_stderr; + +#define X_FLAG_EOF 1 +#define X_FLAG_ERROR 2 +#define X_FLAG_EINVAL 3 + +/** simulate setvbuf() */ +int x_setvbuf(XFILE *f, char *buf, int mode, size_t size) +{ + x_fflush(f); + if (f->bufused) return -1; + + /* on files being read full buffering is the only option */ + if ((f->open_flags & O_ACCMODE) == O_RDONLY) { + mode = X_IOFBF; + } + + /* destroy any earlier buffer */ + SAFE_FREE(f->buf); + f->buf = 0; + f->bufsize = 0; + f->next = NULL; + f->bufused = 0; + f->buftype = mode; + + if (f->buftype == X_IONBF) return 0; + + /* if buffering then we need some size */ + if (size == 0) size = XBUFSIZE; + + f->bufsize = size; + f->bufused = 0; + + return 0; +} + +/* allocate the buffer */ +static int x_allocate_buffer(XFILE *f) +{ + if (f->buf) return 1; + if (f->bufsize == 0) return 0; + f->buf = (char *)malloc(f->bufsize); + if (!f->buf) return 0; + f->next = f->buf; + return 1; +} + + +/** this looks more like open() than fopen(), but that is quite deliberate. + I want programmers to *think* about O_EXCL, O_CREAT etc not just + get them magically added +*/ +XFILE *x_fopen(const char *fname, int flags, mode_t mode) +{ + XFILE *ret; + + ret = malloc_p(XFILE); + if (!ret) return NULL; + + memset(ret, 0, sizeof(XFILE)); + + if ((flags & O_ACCMODE) == O_RDWR) { + /* we don't support RDWR in XFILE - use file + descriptors instead */ + errno = EINVAL; + return NULL; + } + + ret->open_flags = flags; + + ret->fd = open(fname, flags, mode); + if (ret->fd == -1) { + SAFE_FREE(ret); + return NULL; + } + + x_setvbuf(ret, NULL, X_IOFBF, XBUFSIZE); + + return ret; +} + +/** simulate fclose() */ +int x_fclose(XFILE *f) +{ + int ret; + + /* make sure we flush any buffered data */ + x_fflush(f); + + ret = close(f->fd); + f->fd = -1; + if (f->buf) { + /* make sure data can't leak into a later malloc */ + memset(f->buf, 0, f->bufsize); + SAFE_FREE(f->buf); + } + /* check the file descriptor given to the function is NOT one of the static + * descriptor of this libreary or we will free unallocated memory + * --sss */ + if (f != x_stdin && f != x_stdout && f != x_stderr) { + SAFE_FREE(f); + } + return ret; +} + +/** simulate fwrite() */ +size_t x_fwrite(const void *p, size_t size, size_t nmemb, XFILE *f) +{ + ssize_t ret; + size_t total=0; + + /* we might be writing unbuffered */ + if (f->buftype == X_IONBF || + (!f->buf && !x_allocate_buffer(f))) { + ret = write(f->fd, p, size*nmemb); + if (ret == -1) return -1; + return ret/size; + } + + + while (total < size*nmemb) { + size_t n = f->bufsize - f->bufused; + n = MIN(n, (size*nmemb)-total); + + if (n == 0) { + /* it's full, flush it */ + x_fflush(f); + continue; + } + + memcpy(f->buf + f->bufused, total+(const char *)p, n); + f->bufused += n; + total += n; + } + + /* when line buffered we need to flush at the last linefeed. This can + flush a bit more than necessary, but that is harmless */ + if (f->buftype == X_IOLBF && f->bufused) { + int i; + for (i=(size*nmemb)-1; i>=0; i--) { + if (*(i+(const char *)p) == '\n') { + x_fflush(f); + break; + } + } + } + + return total/size; +} + +/** thank goodness for asprintf() */ + int x_vfprintf(XFILE *f, const char *format, va_list ap) +{ + char *p; + int len, ret; + va_list ap2; + + va_copy(ap2, ap); + len = vasprintf(&p, format, ap2); + va_end(ap2); + if (len <= 0) return len; + ret = x_fwrite(p, 1, len, f); + SAFE_FREE(p); + return ret; +} + + int x_fprintf(XFILE *f, const char *format, ...) +{ + va_list ap; + int ret; + + va_start(ap, format); + ret = x_vfprintf(f, format, ap); + va_end(ap); + return ret; +} + +/* at least fileno() is simple! */ +int x_fileno(XFILE *f) +{ + return f->fd; +} + +/** simulate fflush() */ +int x_fflush(XFILE *f) +{ + int ret; + + if (f->flags & X_FLAG_ERROR) return -1; + + if ((f->open_flags & O_ACCMODE) != O_WRONLY) { + errno = EINVAL; + return -1; + } + + if (f->bufused == 0) return 0; + + ret = write(f->fd, f->buf, f->bufused); + if (ret == -1) return -1; + + f->bufused -= ret; + if (f->bufused > 0) { + f->flags |= X_FLAG_ERROR; + memmove(f->buf, ret + (char *)f->buf, f->bufused); + return -1; + } + + return 0; +} + +/** simulate setbuffer() */ +void x_setbuffer(XFILE *f, char *buf, size_t size) +{ + x_setvbuf(f, buf, buf?X_IOFBF:X_IONBF, size); +} + +/** simulate setbuf() */ +void x_setbuf(XFILE *f, char *buf) +{ + x_setvbuf(f, buf, buf?X_IOFBF:X_IONBF, XBUFSIZE); +} + +/** simulate setlinebuf() */ +void x_setlinebuf(XFILE *f) +{ + x_setvbuf(f, NULL, X_IOLBF, 0); +} + + +/** simulate feof() */ +int x_feof(XFILE *f) +{ + if (f->flags & X_FLAG_EOF) return 1; + return 0; +} + +/** simulate ferror() */ +int x_ferror(XFILE *f) +{ + if (f->flags & X_FLAG_ERROR) return 1; + return 0; +} + +/* fill the read buffer */ +static void x_fillbuf(XFILE *f) +{ + int n; + + if (f->bufused) return; + + if (!f->buf && !x_allocate_buffer(f)) return; + + n = read(f->fd, f->buf, f->bufsize); + if (n <= 0) return; + f->bufused = n; + f->next = f->buf; +} + +/** simulate fgetc() */ +int x_fgetc(XFILE *f) +{ + int ret; + + if (f->flags & (X_FLAG_EOF | X_FLAG_ERROR)) return EOF; + + if (f->bufused == 0) x_fillbuf(f); + + if (f->bufused == 0) { + f->flags |= X_FLAG_EOF; + return EOF; + } + + ret = *(uint8_t *)(f->next); + f->next++; + f->bufused--; + return ret; +} + +/** simulate fread */ +size_t x_fread(void *p, size_t size, size_t nmemb, XFILE *f) +{ + size_t total = 0; + while (total < size*nmemb) { + int c = x_fgetc(f); + if (c == EOF) break; + (total+(char *)p)[0] = (char)c; + total++; + } + return total/size; +} + +/** simulate fgets() */ +char *x_fgets(char *s, int size, XFILE *stream) +{ + char *s0 = s; + int l = size; + while (l>1) { + int c = x_fgetc(stream); + if (c == EOF) break; + *s++ = (char)c; + l--; + if (c == '\n') break; + } + if (l==size || x_ferror(stream)) { + return 0; + } + *s = 0; + return s0; +} + +/** + * trivial seek, works only for SEEK_SET and SEEK_END if SEEK_CUR is + * set then an error is returned */ +off_t x_tseek(XFILE *f, off_t offset, int whence) +{ + if (f->flags & X_FLAG_ERROR) + return -1; + + /* only SEEK_SET and SEEK_END are supported */ + /* SEEK_CUR needs internal offset counter */ + if (whence != SEEK_SET && whence != SEEK_END) { + f->flags |= X_FLAG_EINVAL; + errno = EINVAL; + return -1; + } + + /* empty the buffer */ + switch (f->open_flags & O_ACCMODE) { + case O_RDONLY: + f->bufused = 0; + break; + case O_WRONLY: + if (x_fflush(f) != 0) + return -1; + break; + default: + errno = EINVAL; + return -1; + } + + f->flags &= ~X_FLAG_EOF; + return lseek(f->fd, offset, whence); +} diff --git a/lib/util/xfile.h b/lib/util/xfile.h new file mode 100644 index 0000000000..2cc369d8d8 --- /dev/null +++ b/lib/util/xfile.h @@ -0,0 +1,99 @@ +/* + Unix SMB/CIFS implementation. + stdio replacement + Copyright (C) Andrew Tridgell 2001 + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _XFILE_H_ +#define _XFILE_H_ +/* + see xfile.c for explanations +*/ + +typedef struct { + int fd; + char *buf; + char *next; + int bufsize; + int bufused; + int open_flags; + int buftype; + int flags; +} XFILE; + +extern XFILE *x_stdin, *x_stdout, *x_stderr; + +/* buffering type */ +#define X_IOFBF 0 +#define X_IOLBF 1 +#define X_IONBF 2 + +#define x_getc(f) x_fgetc(f) + +int x_vfprintf(XFILE *f, const char *format, va_list ap) PRINTF_ATTRIBUTE(2, 0); +int x_fprintf(XFILE *f, const char *format, ...) PRINTF_ATTRIBUTE(2, 3); + +/** simulate setvbuf() */ +int x_setvbuf(XFILE *f, char *buf, int mode, size_t size); + +/** this looks more like open() than fopen(), but that is quite deliberate. + I want programmers to *think* about O_EXCL, O_CREAT etc not just + get them magically added +*/ +XFILE *x_fopen(const char *fname, int flags, mode_t mode); + +/** simulate fclose() */ +int x_fclose(XFILE *f); + +/** simulate fwrite() */ +size_t x_fwrite(const void *p, size_t size, size_t nmemb, XFILE *f); + +/** thank goodness for asprintf() */ +int x_fileno(XFILE *f); + +/** simulate fflush() */ +int x_fflush(XFILE *f); + +/** simulate setbuffer() */ +void x_setbuffer(XFILE *f, char *buf, size_t size); + +/** simulate setbuf() */ +void x_setbuf(XFILE *f, char *buf); + +/** simulate setlinebuf() */ +void x_setlinebuf(XFILE *f); + +/** simulate feof() */ +int x_feof(XFILE *f); + +/** simulate ferror() */ +int x_ferror(XFILE *f); + +/** simulate fgetc() */ +int x_fgetc(XFILE *f); + +/** simulate fread */ +size_t x_fread(void *p, size_t size, size_t nmemb, XFILE *f); + +/** simulate fgets() */ +char *x_fgets(char *s, int size, XFILE *stream) ; + +/** + * trivial seek, works only for SEEK_SET and SEEK_END if SEEK_CUR is + * set then an error is returned */ +off_t x_tseek(XFILE *f, off_t offset, int whence); + +#endif /* _XFILE_H_ */ diff --git a/source4/Makefile b/source4/Makefile index cab82674d2..345c16ed6e 100644 --- a/source4/Makefile +++ b/source4/Makefile @@ -74,7 +74,7 @@ socketwrappersrcdir := ../lib/socket_wrapper nsswrappersrcdir := ../lib/nss_wrapper appwebsrcdir := lib/appweb libstreamsrcdir := lib/stream -libutilsrcdir := lib/util +libutilsrcdir := ../lib/util libtdrsrcdir := lib/tdr libdbwrapsrcdir := lib/dbwrap libcryptosrcdir := ../lib/crypto @@ -144,7 +144,7 @@ endif clean:: @find ../lib ../libcli -name '*.o' -o -name '*.hd' | xargs rm -f -DEFAULT_HEADERS = $(srcdir)/lib/util/dlinklist.h \ +DEFAULT_HEADERS = $(srcdir)/../lib/util/dlinklist.h \ $(srcdir)/version.h libraries:: $(STATIC_LIBS) $(SHARED_LIBS) diff --git a/source4/auth/credentials/credentials.h b/source4/auth/credentials/credentials.h index 79c50ae5af..52b10c633c 100644 --- a/source4/auth/credentials/credentials.h +++ b/source4/auth/credentials/credentials.h @@ -22,7 +22,7 @@ #ifndef __CREDENTIALS_H__ #define __CREDENTIALS_H__ -#include "util/data_blob.h" +#include "../lib/util/data_blob.h" #include "librpc/gen_ndr/misc.h" struct ccache_container; diff --git a/source4/configure.ac b/source4/configure.ac index 611b8dd104..62f9dc43a0 100644 --- a/source4/configure.ac +++ b/source4/configure.ac @@ -14,13 +14,13 @@ m4_include(build/m4/env.m4) m4_include(../lib/replace/samba.m4) m4_include(lib/smbreadline/readline.m4) m4_include(heimdal_build/config.m4) -m4_include(lib/util/fault.m4) -m4_include(lib/util/signal.m4) -m4_include(lib/util/util.m4) -m4_include(lib/util/fsusage.m4) -m4_include(lib/util/xattr.m4) -m4_include(lib/util/capability.m4) -m4_include(lib/util/time.m4) +m4_include(../lib/util/fault.m4) +m4_include(../lib/util/signal.m4) +m4_include(../lib/util/util.m4) +m4_include(../lib/util/fsusage.m4) +m4_include(../lib/util/xattr.m4) +m4_include(../lib/util/capability.m4) +m4_include(../lib/util/time.m4) m4_include(../lib/popt/samba.m4) m4_include(lib/charset/config.m4) m4_include(lib/socket/config.m4) diff --git a/source4/include/includes.h b/source4/include/includes.h index 750ebc4137..1386ea510b 100644 --- a/source4/include/includes.h +++ b/source4/include/includes.h @@ -42,12 +42,12 @@ #ifndef _PRINTF_ATTRIBUTE #define _PRINTF_ATTRIBUTE(a1, a2) PRINTF_ATTRIBUTE(a1, a2) #endif -#include "util/util.h" +#include "../lib/util/util.h" #include "libcli/util/error.h" /* String routines */ -#include "util/safe_string.h" +#include "../lib/util/safe_string.h" #if 0 /* darn, we can't do this now that we don't link the ldb tools to all the smb libs */ diff --git a/source4/lib/util/Doxyfile b/source4/lib/util/Doxyfile deleted file mode 100644 index 02e36a7af9..0000000000 --- a/source4/lib/util/Doxyfile +++ /dev/null @@ -1,24 +0,0 @@ -PROJECT_NAME = SAMBA_UTIL -OUTPUT_DIRECTORY = apidocs -BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = YES -OPTIMIZE_OUTPUT_FOR_C = YES -SORT_MEMBER_DOCS = YES -SORT_BRIEF_DOCS = NO -GENERATE_TODOLIST = YES -GENERATE_BUGLIST = YES -GENERATE_DEPRECATEDLIST= YES -SHOW_USED_FILES = NO -SHOW_DIRECTORIES = NO -WARNINGS = YES -WARN_IF_UNDOCUMENTED = YES -WARN_IF_DOC_ERROR = YES -WARN_NO_PARAMDOC = NO -WARN_FORMAT = "$file:$line: $text" -INPUT = . -FILE_PATTERNS = *.c *.h *.dox -GENERATE_HTML = YES -HTML_OUTPUT = html -GENERATE_MAN = YES -ALWAYS_DETAILED_SEC = YES -JAVADOC_AUTOBRIEF = YES diff --git a/source4/lib/util/asn1.c b/source4/lib/util/asn1.c deleted file mode 100644 index 4756c0640d..0000000000 --- a/source4/lib/util/asn1.c +++ /dev/null @@ -1,770 +0,0 @@ -/* - Unix SMB/CIFS implementation. - simple ASN1 routines - Copyright (C) Andrew Tridgell 2001 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" -#include "lib/util/asn1.h" - -/* allocate an asn1 structure */ -struct asn1_data *asn1_init(TALLOC_CTX *mem_ctx) -{ - struct asn1_data *ret = talloc_zero(mem_ctx, struct asn1_data); - if (ret == NULL) { - DEBUG(0,("asn1_init failed! out of memory\n")); - } - return ret; -} - -/* free an asn1 structure */ -void asn1_free(struct asn1_data *data) -{ - talloc_free(data); -} - -/* write to the ASN1 buffer, advancing the buffer pointer */ -bool asn1_write(struct asn1_data *data, const void *p, int len) -{ - if (data->has_error) return false; - if (data->length < data->ofs+len) { - uint8_t *newp; - newp = talloc_realloc(data, data->data, uint8_t, data->ofs+len); - if (!newp) { - asn1_free(data); - data->has_error = true; - return false; - } - data->data = newp; - data->length = data->ofs+len; - } - memcpy(data->data + data->ofs, p, len); - data->ofs += len; - return true; -} - -/* useful fn for writing a uint8_t */ -bool asn1_write_uint8(struct asn1_data *data, uint8_t v) -{ - return asn1_write(data, &v, 1); -} - -/* push a tag onto the asn1 data buffer. Used for nested structures */ -bool asn1_push_tag(struct asn1_data *data, uint8_t tag) -{ - struct nesting *nesting; - - asn1_write_uint8(data, tag); - nesting = talloc(data, struct nesting); - if (!nesting) { - data->has_error = true; - return false; - } - - nesting->start = data->ofs; - nesting->next = data->nesting; - data->nesting = nesting; - return asn1_write_uint8(data, 0xff); -} - -/* pop a tag */ -bool asn1_pop_tag(struct asn1_data *data) -{ - struct nesting *nesting; - size_t len; - - nesting = data->nesting; - - if (!nesting) { - data->has_error = true; - return false; - } - len = data->ofs - (nesting->start+1); - /* yes, this is ugly. We don't know in advance how many bytes the length - of a tag will take, so we assumed 1 byte. If we were wrong then we - need to correct our mistake */ - if (len > 0xFFFFFF) { - data->data[nesting->start] = 0x84; - if (!asn1_write_uint8(data, 0)) return false; - if (!asn1_write_uint8(data, 0)) return false; - if (!asn1_write_uint8(data, 0)) return false; - if (!asn1_write_uint8(data, 0)) return false; - memmove(data->data+nesting->start+5, data->data+nesting->start+1, len); - data->data[nesting->start+1] = (len>>24) & 0xFF; - data->data[nesting->start+2] = (len>>16) & 0xFF; - data->data[nesting->start+3] = (len>>8) & 0xFF; - data->data[nesting->start+4] = len&0xff; - } else if (len > 0xFFFF) { - data->data[nesting->start] = 0x83; - if (!asn1_write_uint8(data, 0)) return false; - if (!asn1_write_uint8(data, 0)) return false; - if (!asn1_write_uint8(data, 0)) return false; - memmove(data->data+nesting->start+4, data->data+nesting->start+1, len); - data->data[nesting->start+1] = (len>>16) & 0xFF; - data->data[nesting->start+2] = (len>>8) & 0xFF; - data->data[nesting->start+3] = len&0xff; - } else if (len > 255) { - data->data[nesting->start] = 0x82; - if (!asn1_write_uint8(data, 0)) return false; - if (!asn1_write_uint8(data, 0)) return false; - memmove(data->data+nesting->start+3, data->data+nesting->start+1, len); - data->data[nesting->start+1] = len>>8; - data->data[nesting->start+2] = len&0xff; - } else if (len > 127) { - data->data[nesting->start] = 0x81; - if (!asn1_write_uint8(data, 0)) return false; - memmove(data->data+nesting->start+2, data->data+nesting->start+1, len); - data->data[nesting->start+1] = len; - } else { - data->data[nesting->start] = len; - } - - data->nesting = nesting->next; - talloc_free(nesting); - return true; -} - -/* "i" is the one's complement representation, as is the normal result of an - * implicit signed->unsigned conversion */ - -static bool push_int_bigendian(struct asn1_data *data, unsigned int i, bool negative) -{ - uint8_t lowest = i & 0xFF; - - i = i >> 8; - if (i != 0) - if (!push_int_bigendian(data, i, negative)) - return false; - - if (data->nesting->start+1 == data->ofs) { - - /* We did not write anything yet, looking at the highest - * valued byte */ - - if (negative) { - /* Don't write leading 0xff's */ - if (lowest == 0xFF) - return true; - - if ((lowest & 0x80) == 0) { - /* The only exception for a leading 0xff is if - * the highest bit is 0, which would indicate - * a positive value */ - if (!asn1_write_uint8(data, 0xff)) - return false; - } - } else { - if (lowest & 0x80) { - /* The highest bit of a positive integer is 1, - * this would indicate a negative number. Push - * a 0 to indicate a positive one */ - if (!asn1_write_uint8(data, 0)) - return false; - } - } - } - - return asn1_write_uint8(data, lowest); -} - -/* write an Integer without the tag framing. Needed for example for the LDAP - * Abandon Operation */ - -bool asn1_write_implicit_Integer(struct asn1_data *data, int i) -{ - if (i == -1) { - /* -1 is special as it consists of all-0xff bytes. In - push_int_bigendian this is the only case that is not - properly handled, as all 0xff bytes would be handled as - leading ones to be ignored. */ - return asn1_write_uint8(data, 0xff); - } else { - return push_int_bigendian(data, i, i<0); - } -} - - -/* write an integer */ -bool asn1_write_Integer(struct asn1_data *data, int i) -{ - if (!asn1_push_tag(data, ASN1_INTEGER)) return false; - if (!asn1_write_implicit_Integer(data, i)) return false; - return asn1_pop_tag(data); -} - -bool ber_write_OID_String(DATA_BLOB *blob, const char *OID) -{ - uint_t v, v2; - const char *p = (const char *)OID; - char *newp; - int i; - - v = strtoul(p, &newp, 10); - if (newp[0] != '.') return false; - p = newp + 1; - - v2 = strtoul(p, &newp, 10); - if (newp[0] != '.') return false; - p = newp + 1; - - /*the ber representation can't use more space then the string one */ - *blob = data_blob(NULL, strlen(OID)); - if (!blob->data) return false; - - blob->data[0] = 40*v + v2; - - i = 1; - while (*p) { - v = strtoul(p, &newp, 10); - if (newp[0] == '.') { - p = newp + 1; - } else if (newp[0] == '\0') { - p = newp; - } else { - data_blob_free(blob); - return false; - } - if (v >= (1<<28)) blob->data[i++] = (0x80 | ((v>>28)&0x7f)); - if (v >= (1<<21)) blob->data[i++] = (0x80 | ((v>>21)&0x7f)); - if (v >= (1<<14)) blob->data[i++] = (0x80 | ((v>>14)&0x7f)); - if (v >= (1<<7)) blob->data[i++] = (0x80 | ((v>>7)&0x7f)); - blob->data[i++] = (v&0x7f); - } - - blob->length = i; - - return true; -} - -/* write an object ID to a ASN1 buffer */ -bool asn1_write_OID(struct asn1_data *data, const char *OID) -{ - DATA_BLOB blob; - - if (!asn1_push_tag(data, ASN1_OID)) return false; - - if (!ber_write_OID_String(&blob, OID)) { - data->has_error = true; - return false; - } - - if (!asn1_write(data, blob.data, blob.length)) { - data->has_error = true; - return false; - } - data_blob_free(&blob); - return asn1_pop_tag(data); -} - -/* write an octet string */ -bool asn1_write_OctetString(struct asn1_data *data, const void *p, size_t length) -{ - asn1_push_tag(data, ASN1_OCTET_STRING); - asn1_write(data, p, length); - asn1_pop_tag(data); - return !data->has_error; -} - -/* write a LDAP string */ -bool asn1_write_LDAPString(struct asn1_data *data, const char *s) -{ - asn1_write(data, s, strlen(s)); - return !data->has_error; -} - -/* write a LDAP string from a DATA_BLOB */ -bool asn1_write_DATA_BLOB_LDAPString(struct asn1_data *data, const DATA_BLOB *s) -{ - asn1_write(data, s->data, s->length); - return !data->has_error; -} - -/* write a general string */ -bool asn1_write_GeneralString(struct asn1_data *data, const char *s) -{ - asn1_push_tag(data, ASN1_GENERAL_STRING); - asn1_write_LDAPString(data, s); - asn1_pop_tag(data); - return !data->has_error; -} - -bool asn1_write_ContextSimple(struct asn1_data *data, uint8_t num, DATA_BLOB *blob) -{ - asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(num)); - asn1_write(data, blob->data, blob->length); - asn1_pop_tag(data); - return !data->has_error; -} - -/* write a BOOLEAN */ -bool asn1_write_BOOLEAN(struct asn1_data *data, bool v) -{ - asn1_push_tag(data, ASN1_BOOLEAN); - asn1_write_uint8(data, v ? 0xFF : 0); - asn1_pop_tag(data); - return !data->has_error; -} - -bool asn1_read_BOOLEAN(struct asn1_data *data, bool *v) -{ - uint8_t tmp = 0; - asn1_start_tag(data, ASN1_BOOLEAN); - asn1_read_uint8(data, &tmp); - if (tmp == 0xFF) { - *v = true; - } else { - *v = false; - } - asn1_end_tag(data); - return !data->has_error; -} - -/* check a BOOLEAN */ -bool asn1_check_BOOLEAN(struct asn1_data *data, bool v) -{ - uint8_t b = 0; - - asn1_read_uint8(data, &b); - if (b != ASN1_BOOLEAN) { - data->has_error = true; - return false; - } - asn1_read_uint8(data, &b); - if (b != v) { - data->has_error = true; - return false; - } - return !data->has_error; -} - - -/* load a struct asn1_data structure with a lump of data, ready to be parsed */ -bool asn1_load(struct asn1_data *data, DATA_BLOB blob) -{ - ZERO_STRUCTP(data); - data->data = talloc_memdup(data, blob.data, blob.length); - if (!data->data) { - data->has_error = true; - return false; - } - data->length = blob.length; - return true; -} - -/* Peek into an ASN1 buffer, not advancing the pointer */ -bool asn1_peek(struct asn1_data *data, void *p, int len) -{ - if (data->has_error) - return false; - - if (len < 0 || data->ofs + len < data->ofs || data->ofs + len < len) - return false; - - if (data->ofs + len > data->length) { - /* we need to mark the buffer as consumed, so the caller knows - this was an out of data error, and not a decode error */ - data->ofs = data->length; - return false; - } - - memcpy(p, data->data + data->ofs, len); - return true; -} - -/* read from a ASN1 buffer, advancing the buffer pointer */ -bool asn1_read(struct asn1_data *data, void *p, int len) -{ - if (!asn1_peek(data, p, len)) { - data->has_error = true; - return false; - } - - data->ofs += len; - return true; -} - -/* read a uint8_t from a ASN1 buffer */ -bool asn1_read_uint8(struct asn1_data *data, uint8_t *v) -{ - return asn1_read(data, v, 1); -} - -bool asn1_peek_uint8(struct asn1_data *data, uint8_t *v) -{ - return asn1_peek(data, v, 1); -} - -bool asn1_peek_tag(struct asn1_data *data, uint8_t tag) -{ - uint8_t b; - - if (asn1_tag_remaining(data) <= 0) { - return false; - } - - if (!asn1_peek_uint8(data, &b)) - return false; - - return (b == tag); -} - -/* start reading a nested asn1 structure */ -bool asn1_start_tag(struct asn1_data *data, uint8_t tag) -{ - uint8_t b; - struct nesting *nesting; - - if (!asn1_read_uint8(data, &b)) - return false; - - if (b != tag) { - data->has_error = true; - return false; - } - nesting = talloc(data, struct nesting); - if (!nesting) { - data->has_error = true; - return false; - } - - if (!asn1_read_uint8(data, &b)) { - return false; - } - - if (b & 0x80) { - int n = b & 0x7f; - if (!asn1_read_uint8(data, &b)) - return false; - nesting->taglen = b; - while (n > 1) { - if (!asn1_read_uint8(data, &b)) - return false; - nesting->taglen = (nesting->taglen << 8) | b; - n--; - } - } else { - nesting->taglen = b; - } - nesting->start = data->ofs; - nesting->next = data->nesting; - data->nesting = nesting; - if (asn1_tag_remaining(data) == -1) { - return false; - } - return !data->has_error; -} - -/* stop reading a tag */ -bool asn1_end_tag(struct asn1_data *data) -{ - struct nesting *nesting; - - /* make sure we read it all */ - if (asn1_tag_remaining(data) != 0) { - data->has_error = true; - return false; - } - - nesting = data->nesting; - - if (!nesting) { - data->has_error = true; - return false; - } - - data->nesting = nesting->next; - talloc_free(nesting); - return true; -} - -/* work out how many bytes are left in this nested tag */ -int asn1_tag_remaining(struct asn1_data *data) -{ - int remaining; - if (data->has_error) { - return -1; - } - - if (!data->nesting) { - data->has_error = true; - return -1; - } - remaining = data->nesting->taglen - (data->ofs - data->nesting->start); - if (remaining > (data->length - data->ofs)) { - data->has_error = true; - return -1; - } - return remaining; -} - -/* read an object ID from a data blob */ -bool ber_read_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, const char **OID) -{ - int i; - uint8_t *b; - uint_t v; - char *tmp_oid = NULL; - - if (blob.length < 2) return false; - - b = blob.data; - - tmp_oid = talloc_asprintf(mem_ctx, "%u", b[0]/40); - if (!tmp_oid) goto nomem; - tmp_oid = talloc_asprintf_append_buffer(tmp_oid, ".%u", b[0]%40); - if (!tmp_oid) goto nomem; - - for(i = 1, v = 0; i < blob.length; i++) { - v = (v<<7) | (b[i]&0x7f); - if ( ! (b[i] & 0x80)) { - tmp_oid = talloc_asprintf_append_buffer(tmp_oid, ".%u", v); - v = 0; - } - if (!tmp_oid) goto nomem; - } - - if (v != 0) { - talloc_free(tmp_oid); - return false; - } - - *OID = tmp_oid; - return true; - -nomem: - return false; -} - -/* read an object ID from a ASN1 buffer */ -bool asn1_read_OID(struct asn1_data *data, TALLOC_CTX *mem_ctx, const char **OID) -{ - DATA_BLOB blob; - int len; - - if (!asn1_start_tag(data, ASN1_OID)) return false; - - len = asn1_tag_remaining(data); - if (len < 0) { - data->has_error = true; - return false; - } - - blob = data_blob(NULL, len); - if (!blob.data) { - data->has_error = true; - return false; - } - - asn1_read(data, blob.data, len); - asn1_end_tag(data); - if (data->has_error) { - data_blob_free(&blob); - return false; - } - - if (!ber_read_OID_String(mem_ctx, blob, OID)) { - data->has_error = true; - data_blob_free(&blob); - return false; - } - - data_blob_free(&blob); - return true; -} - -/* check that the next object ID is correct */ -bool asn1_check_OID(struct asn1_data *data, const char *OID) -{ - const char *id; - - if (!asn1_read_OID(data, data, &id)) return false; - - if (strcmp(id, OID) != 0) { - talloc_free(discard_const(id)); - data->has_error = true; - return false; - } - talloc_free(discard_const(id)); - return true; -} - -/* read a LDAPString from a ASN1 buffer */ -bool asn1_read_LDAPString(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **s) -{ - int len; - len = asn1_tag_remaining(data); - if (len < 0) { - data->has_error = true; - return false; - } - *s = talloc_array(mem_ctx, char, len+1); - if (! *s) { - data->has_error = true; - return false; - } - asn1_read(data, *s, len); - (*s)[len] = 0; - return !data->has_error; -} - - -/* read a GeneralString from a ASN1 buffer */ -bool asn1_read_GeneralString(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **s) -{ - if (!asn1_start_tag(data, ASN1_GENERAL_STRING)) return false; - if (!asn1_read_LDAPString(data, mem_ctx, s)) return false; - return asn1_end_tag(data); -} - - -/* read a octet string blob */ -bool asn1_read_OctetString(struct asn1_data *data, TALLOC_CTX *mem_ctx, DATA_BLOB *blob) -{ - int len; - ZERO_STRUCTP(blob); - if (!asn1_start_tag(data, ASN1_OCTET_STRING)) return false; - len = asn1_tag_remaining(data); - if (len < 0) { - data->has_error = true; - return false; - } - *blob = data_blob_talloc(mem_ctx, NULL, len+1); - if (!blob->data) { - data->has_error = true; - return false; - } - asn1_read(data, blob->data, len); - asn1_end_tag(data); - blob->length--; - blob->data[len] = 0; - - if (data->has_error) { - data_blob_free(blob); - *blob = data_blob(NULL, 0); - return false; - } - return true; -} - -bool asn1_read_ContextSimple(struct asn1_data *data, uint8_t num, DATA_BLOB *blob) -{ - int len; - ZERO_STRUCTP(blob); - if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(num))) return false; - len = asn1_tag_remaining(data); - if (len < 0) { - data->has_error = true; - return false; - } - *blob = data_blob(NULL, len); - if ((len != 0) && (!blob->data)) { - data->has_error = true; - return false; - } - asn1_read(data, blob->data, len); - asn1_end_tag(data); - return !data->has_error; -} - -/* read an integer without tag*/ -bool asn1_read_implicit_Integer(struct asn1_data *data, int *i) -{ - uint8_t b; - *i = 0; - - while (!data->has_error && asn1_tag_remaining(data)>0) { - if (!asn1_read_uint8(data, &b)) return false; - *i = (*i << 8) + b; - } - return !data->has_error; - -} - -/* read an integer */ -bool asn1_read_Integer(struct asn1_data *data, int *i) -{ - *i = 0; - - if (!asn1_start_tag(data, ASN1_INTEGER)) return false; - if (!asn1_read_implicit_Integer(data, i)) return false; - return asn1_end_tag(data); -} - -/* read an integer */ -bool asn1_read_enumerated(struct asn1_data *data, int *v) -{ - *v = 0; - - if (!asn1_start_tag(data, ASN1_ENUMERATED)) return false; - while (!data->has_error && asn1_tag_remaining(data)>0) { - uint8_t b; - asn1_read_uint8(data, &b); - *v = (*v << 8) + b; - } - return asn1_end_tag(data); -} - -/* check a enumerated value is correct */ -bool asn1_check_enumerated(struct asn1_data *data, int v) -{ - uint8_t b; - if (!asn1_start_tag(data, ASN1_ENUMERATED)) return false; - asn1_read_uint8(data, &b); - asn1_end_tag(data); - - if (v != b) - data->has_error = false; - - return !data->has_error; -} - -/* write an enumerated value to the stream */ -bool asn1_write_enumerated(struct asn1_data *data, uint8_t v) -{ - if (!asn1_push_tag(data, ASN1_ENUMERATED)) return false; - asn1_write_uint8(data, v); - asn1_pop_tag(data); - return !data->has_error; -} - -/* - check if a ASN.1 blob is a full tag -*/ -NTSTATUS asn1_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size) -{ - struct asn1_data *asn1 = asn1_init(NULL); - int size; - - NT_STATUS_HAVE_NO_MEMORY(asn1); - - asn1->data = blob.data; - asn1->length = blob.length; - asn1_start_tag(asn1, tag); - if (asn1->has_error) { - talloc_free(asn1); - return STATUS_MORE_ENTRIES; - } - size = asn1_tag_remaining(asn1) + asn1->ofs; - - talloc_free(asn1); - - if (size > blob.length) { - return STATUS_MORE_ENTRIES; - } - - *packet_size = size; - return NT_STATUS_OK; -} diff --git a/source4/lib/util/asn1.h b/source4/lib/util/asn1.h deleted file mode 100644 index 34aa1e2cb9..0000000000 --- a/source4/lib/util/asn1.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - Unix SMB/CIFS implementation. - simple ASN1 code - Copyright (C) Andrew Tridgell 2001 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _ASN_1_H -#define _ASN_1_H - -struct nesting { - off_t start; - size_t taglen; /* for parsing */ - struct nesting *next; -}; - -struct asn1_data { - uint8_t *data; - size_t length; - off_t ofs; - struct nesting *nesting; - bool has_error; -}; - -#define ASN1_APPLICATION(x) ((x)+0x60) -#define ASN1_APPLICATION_SIMPLE(x) ((x)+0x40) -#define ASN1_SEQUENCE(x) ((x)+0x30) -#define ASN1_CONTEXT(x) ((x)+0xa0) -#define ASN1_CONTEXT_SIMPLE(x) ((x)+0x80) -#define ASN1_GENERAL_STRING 0x1b -#define ASN1_OCTET_STRING 0x4 -#define ASN1_OID 0x6 -#define ASN1_BOOLEAN 0x1 -#define ASN1_INTEGER 0x2 -#define ASN1_ENUMERATED 0xa -#define ASN1_SET 0x31 - -#define ASN1_MAX_OIDS 20 - -#include "lib/util/asn1_proto.h" - -#endif /* _ASN_1_H */ diff --git a/source4/lib/util/attr.h b/source4/lib/util/attr.h deleted file mode 100644 index f64b272a67..0000000000 --- a/source4/lib/util/attr.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Samba utility functions - Copyright (C) Jelmer Vernooij 2007 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef __UTIL_ATTR_H__ -#define __UTIL_ATTR_H__ - -#ifdef __GNUC__ -/** gcc attribute used on function parameters so that it does not emit - * warnings about them being unused. **/ -# define UNUSED(param) param __attribute__ ((unused)) -#else -# define UNUSED(param) param -/** Feel free to add definitions for other compilers here. */ -#endif - -#ifdef HAVE_VISIBILITY_ATTR -# define _PUBLIC_ __attribute__((visibility("default"))) -#else -# define _PUBLIC_ -#endif - -#ifndef _DEPRECATED_ -#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 ) -#define _DEPRECATED_ __attribute__ ((deprecated)) -#else -#define _DEPRECATED_ -#endif -#endif - -#ifndef _WARN_UNUSED_RESULT_ -#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 ) -#define _WARN_UNUSED_RESULT_ __attribute__ ((warn_unused_result)) -#else -#define _WARN_UNUSED_RESULT_ -#endif -#endif - -#ifndef _NORETURN_ -#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 ) -#define _NORETURN_ __attribute__ ((noreturn)) -#else -#define _NORETURN_ -#endif -#endif - -#ifndef _PURE_ -#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1) -#define _PURE_ __attribute__((pure)) -#else -#define _PURE_ -#endif -#endif - -#ifndef NONNULL -#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1) -#define NONNULL(param) param __attribute__((nonnull)) -#else -#define NONNULL(param) param -#endif -#endif - -#ifndef PRINTF_ATTRIBUTE -#if __GNUC__ >= 3 -/** Use gcc attribute to check printf fns. a1 is the 1-based index of - * the parameter containing the format, and a2 the index of the first - * argument. Note that some gcc 2.x versions don't handle this - * properly **/ -#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) -#else -#define PRINTF_ATTRIBUTE(a1, a2) -#endif -#endif - -#endif /* __UTIL_ATTR_H__ */ diff --git a/source4/lib/util/become_daemon.c b/source4/lib/util/become_daemon.c deleted file mode 100644 index 034114eade..0000000000 --- a/source4/lib/util/become_daemon.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Samba utility functions - Copyright (C) Andrew Tridgell 1992-1998 - Copyright (C) Jeremy Allison 2001-2002 - Copyright (C) Simo Sorce 2001 - Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003. - Copyright (C) James J Myers 2003 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" -#include "system/filesys.h" -#include "system/locale.h" - -/******************************************************************* - Close the low 3 fd's and open dev/null in their place. -********************************************************************/ -static void close_low_fds(bool stderr_too) -{ -#ifndef VALGRIND - int fd; - int i; - - close(0); - close(1); - - if (stderr_too) - close(2); - - /* try and use up these file descriptors, so silly - library routines writing to stdout etc won't cause havoc */ - for (i=0;i<3;i++) { - if (i == 2 && !stderr_too) - continue; - - fd = open("/dev/null",O_RDWR,0); - if (fd < 0) - fd = open("/dev/null",O_WRONLY,0); - if (fd < 0) { - DEBUG(0,("Can't open /dev/null\n")); - return; - } - if (fd != i) { - DEBUG(0,("Didn't get file descriptor %d\n",i)); - return; - } - } -#endif -} - -/** - Become a daemon, discarding the controlling terminal. -**/ - -_PUBLIC_ void become_daemon(bool Fork) -{ - if (Fork) { - if (fork()) { - _exit(0); - } - } - - /* detach from the terminal */ -#ifdef HAVE_SETSID - setsid(); -#elif defined(TIOCNOTTY) - { - int i = open("/dev/tty", O_RDWR, 0); - if (i != -1) { - ioctl(i, (int) TIOCNOTTY, (char *)0); - close(i); - } - } -#endif /* HAVE_SETSID */ - - /* Close fd's 0,1,2. Needed if started by rsh */ - close_low_fds(false); /* Don't close stderr, let the debug system - attach it to the logfile */ -} - diff --git a/source4/lib/util/byteorder.h b/source4/lib/util/byteorder.h deleted file mode 100644 index 894beccabf..0000000000 --- a/source4/lib/util/byteorder.h +++ /dev/null @@ -1,231 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SMB Byte handling - Copyright (C) Andrew Tridgell 1992-1998 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _BYTEORDER_H -#define _BYTEORDER_H - -/* - This file implements macros for machine independent short and - int manipulation - -Here is a description of this file that I emailed to the samba list once: - -> I am confused about the way that byteorder.h works in Samba. I have -> looked at it, and I would have thought that you might make a distinction -> between LE and BE machines, but you only seem to distinguish between 386 -> and all other architectures. -> -> Can you give me a clue? - -sure. - -The distinction between 386 and other architectures is only there as -an optimisation. You can take it out completely and it will make no -difference. The routines (macros) in byteorder.h are totally byteorder -independent. The 386 optimsation just takes advantage of the fact that -the x86 processors don't care about alignment, so we don't have to -align ints on int boundaries etc. If there are other processors out -there that aren't alignment sensitive then you could also define -CAREFUL_ALIGNMENT=0 on those processors as well. - -Ok, now to the macros themselves. I'll take a simple example, say we -want to extract a 2 byte integer from a SMB packet and put it into a -type called uint16_t that is in the local machines byte order, and you -want to do it with only the assumption that uint16_t is _at_least_ 16 -bits long (this last condition is very important for architectures -that don't have any int types that are 2 bytes long) - -You do this: - -#define CVAL(buf,pos) (((uint8_t *)(buf))[pos]) -#define PVAL(buf,pos) ((uint_t)CVAL(buf,pos)) -#define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8) - -then to extract a uint16_t value at offset 25 in a buffer you do this: - -char *buffer = foo_bar(); -uint16_t xx = SVAL(buffer,25); - -We are using the byteoder independence of the ANSI C bitshifts to do -the work. A good optimising compiler should turn this into efficient -code, especially if it happens to have the right byteorder :-) - -I know these macros can be made a bit tidier by removing some of the -casts, but you need to look at byteorder.h as a whole to see the -reasoning behind them. byteorder.h defines the following macros: - -SVAL(buf,pos) - extract a 2 byte SMB value -IVAL(buf,pos) - extract a 4 byte SMB value -BVAL(buf,pos) - extract a 8 byte SMB value -SVALS(buf,pos) - signed version of SVAL() -IVALS(buf,pos) - signed version of IVAL() -BVALS(buf,pos) - signed version of BVAL() - -SSVAL(buf,pos,val) - put a 2 byte SMB value into a buffer -SIVAL(buf,pos,val) - put a 4 byte SMB value into a buffer -SBVAL(buf,pos,val) - put a 8 byte SMB value into a buffer -SSVALS(buf,pos,val) - signed version of SSVAL() -SIVALS(buf,pos,val) - signed version of SIVAL() -SBVALS(buf,pos,val) - signed version of SBVAL() - -RSVAL(buf,pos) - like SVAL() but for NMB byte ordering -RSVALS(buf,pos) - like SVALS() but for NMB byte ordering -RIVAL(buf,pos) - like IVAL() but for NMB byte ordering -RIVALS(buf,pos) - like IVALS() but for NMB byte ordering -RSSVAL(buf,pos,val) - like SSVAL() but for NMB ordering -RSIVAL(buf,pos,val) - like SIVAL() but for NMB ordering -RSIVALS(buf,pos,val) - like SIVALS() but for NMB ordering - -it also defines lots of intermediate macros, just ignore those :-) - -*/ - - -/* - on powerpc we can use the magic instructions to load/store - in little endian -*/ -#if (defined(__powerpc__) && defined(__GNUC__)) -static __inline__ uint16_t ld_le16(const uint16_t *addr) -{ - uint16_t val; - __asm__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr)); - return val; -} - -static __inline__ void st_le16(uint16_t *addr, const uint16_t val) -{ - __asm__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr)); -} - -static __inline__ uint32_t ld_le32(const uint32_t *addr) -{ - uint32_t val; - __asm__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr)); - return val; -} - -static __inline__ void st_le32(uint32_t *addr, const uint32_t val) -{ - __asm__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr)); -} -#define HAVE_ASM_BYTEORDER 1 -#else -#define HAVE_ASM_BYTEORDER 0 -#endif - - - -#undef CAREFUL_ALIGNMENT - -/* we know that the 386 can handle misalignment and has the "right" - byteorder */ -#if defined(__i386__) -#define CAREFUL_ALIGNMENT 0 -#endif - -#ifndef CAREFUL_ALIGNMENT -#define CAREFUL_ALIGNMENT 1 -#endif - -#define CVAL(buf,pos) ((uint_t)(((const uint8_t *)(buf))[pos])) -#define CVAL_NC(buf,pos) (((uint8_t *)(buf))[pos]) /* Non-const version of CVAL */ -#define PVAL(buf,pos) (CVAL(buf,pos)) -#define SCVAL(buf,pos,val) (CVAL_NC(buf,pos) = (val)) - -#if HAVE_ASM_BYTEORDER - -#define _PTRPOS(buf,pos) (((const uint8_t *)buf)+(pos)) -#define SVAL(buf,pos) ld_le16((const uint16_t *)_PTRPOS(buf,pos)) -#define IVAL(buf,pos) ld_le32((const uint32_t *)_PTRPOS(buf,pos)) -#define SSVAL(buf,pos,val) st_le16((uint16_t *)_PTRPOS(buf,pos), val) -#define SIVAL(buf,pos,val) st_le32((uint32_t *)_PTRPOS(buf,pos), val) -#define SVALS(buf,pos) ((int16_t)SVAL(buf,pos)) -#define IVALS(buf,pos) ((int32_t)IVAL(buf,pos)) -#define SSVALS(buf,pos,val) SSVAL((buf),(pos),((int16_t)(val))) -#define SIVALS(buf,pos,val) SIVAL((buf),(pos),((int32_t)(val))) - -#elif CAREFUL_ALIGNMENT - -#define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8) -#define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16) -#define SSVALX(buf,pos,val) (CVAL_NC(buf,pos)=(uint8_t)((val)&0xFF),CVAL_NC(buf,pos+1)=(uint8_t)((val)>>8)) -#define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16)) -#define SVALS(buf,pos) ((int16_t)SVAL(buf,pos)) -#define IVALS(buf,pos) ((int32_t)IVAL(buf,pos)) -#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((uint16_t)(val))) -#define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32_t)(val))) -#define SSVALS(buf,pos,val) SSVALX((buf),(pos),((int16_t)(val))) -#define SIVALS(buf,pos,val) SIVALX((buf),(pos),((int32_t)(val))) - -#else /* not CAREFUL_ALIGNMENT */ - -/* this handles things for architectures like the 386 that can handle - alignment errors */ -/* - WARNING: This section is dependent on the length of int16_t and int32_t - being correct -*/ - -/* get single value from an SMB buffer */ -#define SVAL(buf,pos) (*(const uint16_t *)((const char *)(buf) + (pos))) -#define SVAL_NC(buf,pos) (*(uint16_t *)((char *)(buf) + (pos))) /* Non const version of above. */ -#define IVAL(buf,pos) (*(const uint32_t *)((const char *)(buf) + (pos))) -#define IVAL_NC(buf,pos) (*(uint32_t *)((char *)(buf) + (pos))) /* Non const version of above. */ -#define SVALS(buf,pos) (*(const int16_t *)((const char *)(buf) + (pos))) -#define SVALS_NC(buf,pos) (*(int16_t *)((char *)(buf) + (pos))) /* Non const version of above. */ -#define IVALS(buf,pos) (*(const int32_t *)((const char *)(buf) + (pos))) -#define IVALS_NC(buf,pos) (*(int32_t *)((char *)(buf) + (pos))) /* Non const version of above. */ - -/* store single value in an SMB buffer */ -#define SSVAL(buf,pos,val) SVAL_NC(buf,pos)=((uint16_t)(val)) -#define SIVAL(buf,pos,val) IVAL_NC(buf,pos)=((uint32_t)(val)) -#define SSVALS(buf,pos,val) SVALS_NC(buf,pos)=((int16_t)(val)) -#define SIVALS(buf,pos,val) IVALS_NC(buf,pos)=((int32_t)(val)) - -#endif /* not CAREFUL_ALIGNMENT */ - -/* now the reverse routines - these are used in nmb packets (mostly) */ -#define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF)) -#define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16))) - -#define RSVAL(buf,pos) SREV(SVAL(buf,pos)) -#define RSVALS(buf,pos) SREV(SVALS(buf,pos)) -#define RIVAL(buf,pos) IREV(IVAL(buf,pos)) -#define RIVALS(buf,pos) IREV(IVALS(buf,pos)) -#define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val)) -#define RSSVALS(buf,pos,val) SSVALS(buf,pos,SREV(val)) -#define RSIVAL(buf,pos,val) SIVAL(buf,pos,IREV(val)) -#define RSIVALS(buf,pos,val) SIVALS(buf,pos,IREV(val)) - -/* Alignment macros. */ -#define ALIGN4(p,base) ((p) + ((4 - (PTR_DIFF((p), (base)) & 3)) & 3)) -#define ALIGN2(p,base) ((p) + ((2 - (PTR_DIFF((p), (base)) & 1)) & 1)) - - -/* macros for accessing SMB protocol elements */ -#define VWV(vwv) ((vwv)*2) - -/* 64 bit macros */ -#define BVAL(p, ofs) (IVAL(p,ofs) | (((uint64_t)IVAL(p,(ofs)+4)) << 32)) -#define BVALS(p, ofs) ((int64_t)BVAL(p,ofs)) -#define SBVAL(p, ofs, v) (SIVAL(p,ofs,(v)&0xFFFFFFFF), SIVAL(p,(ofs)+4,((uint64_t)(v))>>32)) -#define SBVALS(p, ofs, v) (SBVAL(p,ofs,(uint64_t)v)) - -#endif /* _BYTEORDER_H */ diff --git a/source4/lib/util/capability.c b/source4/lib/util/capability.c deleted file mode 100644 index 2d13826c14..0000000000 --- a/source4/lib/util/capability.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Copyright (C) Andrew Tridgell 1992-1998 - Copyright (C) Jeremy Allison 1998-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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file - * @brief Capabilities functions - **/ - -/* - capabilities fns - will be needed when we enable kernel oplocks -*/ - -#include "includes.h" -#include "system/network.h" -#include "system/wait.h" -#include "system/filesys.h" - - -#if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES) -/************************************************************************** - Try and abstract process capabilities (for systems that have them). -****************************************************************************/ -static bool set_process_capability( uint32_t cap_flag, bool enable ) -{ - if(cap_flag == KERNEL_OPLOCK_CAPABILITY) { - cap_t cap = cap_get_proc(); - - if (cap == NULL) { - DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n", - strerror(errno))); - return false; - } - - if(enable) - cap->cap_effective |= CAP_NETWORK_MGT; - else - cap->cap_effective &= ~CAP_NETWORK_MGT; - - if (cap_set_proc(cap) == -1) { - DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n", - strerror(errno))); - cap_free(cap); - return false; - } - - cap_free(cap); - - DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n")); - } - return true; -} - -/************************************************************************** - Try and abstract inherited process capabilities (for systems that have them). -****************************************************************************/ - -static bool set_inherited_process_capability( uint32_t cap_flag, bool enable ) -{ - if(cap_flag == KERNEL_OPLOCK_CAPABILITY) { - cap_t cap = cap_get_proc(); - - if (cap == NULL) { - DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n", - strerror(errno))); - return false; - } - - if(enable) - cap->cap_inheritable |= CAP_NETWORK_MGT; - else - cap->cap_inheritable &= ~CAP_NETWORK_MGT; - - if (cap_set_proc(cap) == -1) { - DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n", - strerror(errno))); - cap_free(cap); - return false; - } - - cap_free(cap); - - DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n")); - } - return true; -} -#endif diff --git a/source4/lib/util/capability.m4 b/source4/lib/util/capability.m4 deleted file mode 100644 index 2a95a607d5..0000000000 --- a/source4/lib/util/capability.m4 +++ /dev/null @@ -1,17 +0,0 @@ -AC_CACHE_CHECK([for irix specific capabilities],samba_cv_HAVE_IRIX_SPECIFIC_CAPABILITIES,[ -AC_TRY_RUN([#include -#include -main() { - cap_t cap; - if ((cap = cap_get_proc()) == NULL) - exit(1); - cap->cap_effective |= CAP_NETWORK_MGT; - cap->cap_inheritable |= CAP_NETWORK_MGT; - cap_set_proc(cap); - exit(0); -} -], -samba_cv_HAVE_IRIX_SPECIFIC_CAPABILITIES=yes,samba_cv_HAVE_IRIX_SPECIFIC_CAPABILITIES=no,samba_cv_HAVE_IRIX_SPECIFIC_CAPABILITIES=cross)]) -if test x"$samba_cv_HAVE_IRIX_SPECIFIC_CAPABILITIES" = x"yes"; then - AC_DEFINE(HAVE_IRIX_SPECIFIC_CAPABILITIES,1,[Whether IRIX specific capabilities are available]) -fi diff --git a/source4/lib/util/config.mk b/source4/lib/util/config.mk deleted file mode 100644 index 925713a53c..0000000000 --- a/source4/lib/util/config.mk +++ /dev/null @@ -1,71 +0,0 @@ -[SUBSYSTEM::LIBSAMBA-UTIL] -PUBLIC_DEPENDENCIES = \ - LIBTALLOC LIBCRYPTO \ - SOCKET_WRAPPER LIBREPLACE_NETWORK \ - CHARSET EXECINFO - -LIBSAMBA-UTIL_OBJ_FILES = $(addprefix $(libutilsrcdir)/, \ - xfile.o \ - debug.o \ - fault.o \ - signal.o \ - system.o \ - time.o \ - genrand.o \ - dprintf.o \ - util_str.o \ - util_strlist.o \ - util_file.o \ - data_blob.o \ - util.o \ - fsusage.o \ - ms_fnmatch.o \ - mutex.o \ - idtree.o \ - become_daemon.o \ - params.o) - -PUBLIC_HEADERS += $(addprefix $(libutilsrcdir)/, util.h \ - attr.h \ - byteorder.h \ - data_blob.h \ - debug.h \ - mutex.h \ - safe_string.h \ - time.h \ - util_ldb.h \ - xfile.h) - -[SUBSYSTEM::ASN1_UTIL] - -ASN1_UTIL_OBJ_FILES = $(libutilsrcdir)/asn1.o - -$(eval $(call proto_header_template,$(libutilsrcdir)/asn1_proto.h,$(ASN1_UTIL_OBJ_FILES:.o=.c))) - -[SUBSYSTEM::UNIX_PRIVS] - -UNIX_PRIVS_OBJ_FILES = $(libutilsrcdir)/unix_privs.o - -$(eval $(call proto_header_template,$(libutilsrcdir)/unix_privs.h,$(UNIX_PRIVS_OBJ_FILES:.o=.c))) - -################################################ -# Start SUBSYSTEM WRAP_XATTR -[SUBSYSTEM::WRAP_XATTR] -PUBLIC_DEPENDENCIES = XATTR -# -# End SUBSYSTEM WRAP_XATTR -################################################ - -WRAP_XATTR_OBJ_FILES = $(libutilsrcdir)/wrap_xattr.o - -[SUBSYSTEM::UTIL_TDB] -PUBLIC_DEPENDENCIES = LIBTDB - -UTIL_TDB_OBJ_FILES = $(libutilsrcdir)/util_tdb.o - -$(eval $(call proto_header_template,$(libutilsrcdir)/util_tdb.h,$(UTIL_TDB_OBJ_FILES:.o=.c))) - -[SUBSYSTEM::UTIL_LDB] -PUBLIC_DEPENDENCIES = LIBLDB - -UTIL_LDB_OBJ_FILES = $(libutilsrcdir)/util_ldb.o diff --git a/source4/lib/util/data_blob.c b/source4/lib/util/data_blob.c deleted file mode 100644 index 57b34b7ae7..0000000000 --- a/source4/lib/util/data_blob.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Easy management of byte-length data - Copyright (C) Andrew Tridgell 2001 - Copyright (C) Andrew Bartlett 2001 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" - -/** - * @file - * @brief Manipulation of arbitrary data blobs - **/ - -/** - construct a data blob, must be freed with data_blob_free() - you can pass NULL for p and get a blank data blob -**/ -_PUBLIC_ DATA_BLOB data_blob_named(const void *p, size_t length, const char *name) -{ - DATA_BLOB ret; - - if (p == NULL && length == 0) { - ZERO_STRUCT(ret); - return ret; - } - - if (p) { - ret.data = (uint8_t *)talloc_memdup(NULL, p, length); - } else { - ret.data = talloc_array(NULL, uint8_t, length); - } - if (ret.data == NULL) { - ret.length = 0; - return ret; - } - talloc_set_name_const(ret.data, name); - ret.length = length; - return ret; -} - -/** - construct a data blob, using supplied TALLOC_CTX -**/ -_PUBLIC_ DATA_BLOB data_blob_talloc_named(TALLOC_CTX *mem_ctx, const void *p, size_t length, const char *name) -{ - DATA_BLOB ret = data_blob_named(p, length, name); - - if (ret.data) { - talloc_steal(mem_ctx, ret.data); - } - return ret; -} - - -/** - reference a data blob, to the supplied TALLOC_CTX. - Returns a NULL DATA_BLOB on failure -**/ -_PUBLIC_ DATA_BLOB data_blob_talloc_reference(TALLOC_CTX *mem_ctx, DATA_BLOB *blob) -{ - DATA_BLOB ret = *blob; - - ret.data = talloc_reference(mem_ctx, blob->data); - - if (!ret.data) { - return data_blob(NULL, 0); - } - return ret; -} - -/** - construct a zero data blob, using supplied TALLOC_CTX. - use this sparingly as it initialises data - better to initialise - yourself if you want specific data in the blob -**/ -_PUBLIC_ DATA_BLOB data_blob_talloc_zero(TALLOC_CTX *mem_ctx, size_t length) -{ - DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, length); - data_blob_clear(&blob); - return blob; -} - -/** -free a data blob -**/ -_PUBLIC_ void data_blob_free(DATA_BLOB *d) -{ - if (d) { - talloc_free(d->data); - d->data = NULL; - d->length = 0; - } -} - -/** -clear a DATA_BLOB's contents -**/ -_PUBLIC_ void data_blob_clear(DATA_BLOB *d) -{ - if (d->data) { - memset(d->data, 0, d->length); - } -} - -/** -free a data blob and clear its contents -**/ -_PUBLIC_ void data_blob_clear_free(DATA_BLOB *d) -{ - data_blob_clear(d); - data_blob_free(d); -} - - -/** -check if two data blobs are equal -**/ -_PUBLIC_ int data_blob_cmp(const DATA_BLOB *d1, const DATA_BLOB *d2) -{ - int ret; - if (d1->data == NULL && d2->data != NULL) { - return -1; - } - if (d1->data != NULL && d2->data == NULL) { - return 1; - } - if (d1->data == d2->data) { - return d1->length - d2->length; - } - ret = memcmp(d1->data, d2->data, MIN(d1->length, d2->length)); - if (ret == 0) { - return d1->length - d2->length; - } - return ret; -} - -/** -print the data_blob as hex string -**/ -_PUBLIC_ char *data_blob_hex_string(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob) -{ - int i; - char *hex_string; - - hex_string = talloc_array(mem_ctx, char, (blob->length*2)+1); - if (!hex_string) { - return NULL; - } - - for (i = 0; i < blob->length; i++) - slprintf(&hex_string[i*2], 3, "%02X", blob->data[i]); - - hex_string[(blob->length*2)] = '\0'; - return hex_string; -} - -/** - useful for constructing data blobs in test suites, while - avoiding const warnings -**/ -_PUBLIC_ DATA_BLOB data_blob_string_const(const char *str) -{ - DATA_BLOB blob; - blob.data = discard_const_p(uint8_t, str); - blob.length = str ? strlen(str) : 0; - return blob; -} - -/** - * Create a new data blob from const data - */ - -_PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length) -{ - DATA_BLOB blob; - blob.data = discard_const_p(uint8_t, p); - blob.length = length; - return blob; -} - - -/** - realloc a data_blob -**/ -_PUBLIC_ bool data_blob_realloc(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, size_t length) -{ - blob->data = talloc_realloc(mem_ctx, blob->data, uint8_t, length); - if (blob->data == NULL) - return false; - blob->length = length; - return true; -} - - -/** - append some data to a data blob -**/ -_PUBLIC_ bool data_blob_append(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, - const void *p, size_t length) -{ - size_t old_len = blob->length; - size_t new_len = old_len + length; - if (new_len < length || new_len < old_len) { - return false; - } - - if ((const uint8_t *)p + length < (const uint8_t *)p) { - return false; - } - - if (!data_blob_realloc(mem_ctx, blob, new_len)) { - return false; - } - - memcpy(blob->data + old_len, p, length); - return true; -} - diff --git a/source4/lib/util/data_blob.h b/source4/lib/util/data_blob.h deleted file mode 100644 index e9dca67772..0000000000 --- a/source4/lib/util/data_blob.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - Unix SMB/CIFS implementation. - DATA BLOB - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* This is a public header file that is installed as part of Samba. - * If you remove any functions or change their signature, update - * the so version number. */ - -#ifndef _SAMBA_DATABLOB_H_ -#define _SAMBA_DATABLOB_H_ - -#ifndef _PUBLIC_ -#define _PUBLIC_ -#endif - -#include -#include - -/* used to hold an arbitrary blob of data */ -typedef struct datablob { - uint8_t *data; - size_t length; -} DATA_BLOB; - -struct data_blob_list_item { - struct data_blob_list_item *prev,*next; - DATA_BLOB blob; -}; - -/* by making struct ldb_val and DATA_BLOB the same, we can simplify - a fair bit of code */ -#define ldb_val datablob - -#define data_blob(ptr, size) data_blob_named(ptr, size, "DATA_BLOB: "__location__) -#define data_blob_talloc(ctx, ptr, size) data_blob_talloc_named(ctx, ptr, size, "DATA_BLOB: "__location__) -#define data_blob_dup_talloc(ctx, blob) data_blob_talloc_named(ctx, (blob)->data, (blob)->length, "DATA_BLOB: "__location__) - -/** - construct a data blob, must be freed with data_blob_free() - you can pass NULL for p and get a blank data blob -**/ -_PUBLIC_ DATA_BLOB data_blob_named(const void *p, size_t length, const char *name); - -/** - construct a data blob, using supplied TALLOC_CTX -**/ -_PUBLIC_ DATA_BLOB data_blob_talloc_named(TALLOC_CTX *mem_ctx, const void *p, size_t length, const char *name); - -/** - reference a data blob, to the supplied TALLOC_CTX. - Returns a NULL DATA_BLOB on failure -**/ -_PUBLIC_ DATA_BLOB data_blob_talloc_reference(TALLOC_CTX *mem_ctx, DATA_BLOB *blob); - -/** - construct a zero data blob, using supplied TALLOC_CTX. - use this sparingly as it initialises data - better to initialise - yourself if you want specific data in the blob -**/ -_PUBLIC_ DATA_BLOB data_blob_talloc_zero(TALLOC_CTX *mem_ctx, size_t length); - -/** -free a data blob -**/ -_PUBLIC_ void data_blob_free(DATA_BLOB *d); - -/** -clear a DATA_BLOB's contents -**/ -_PUBLIC_ void data_blob_clear(DATA_BLOB *d); - -/** -free a data blob and clear its contents -**/ -_PUBLIC_ void data_blob_clear_free(DATA_BLOB *d); - -/** -check if two data blobs are equal -**/ -_PUBLIC_ int data_blob_cmp(const DATA_BLOB *d1, const DATA_BLOB *d2); - -/** -print the data_blob as hex string -**/ -_PUBLIC_ char *data_blob_hex_string(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob); - -/** - useful for constructing data blobs in test suites, while - avoiding const warnings -**/ -_PUBLIC_ DATA_BLOB data_blob_string_const(const char *str); - -/** - * Create a new data blob from const data - */ -_PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length); - -/** - realloc a data_blob -**/ -_PUBLIC_ bool data_blob_realloc(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, size_t length); - -/** - append some data to a data blob -**/ -_PUBLIC_ bool data_blob_append(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, - const void *p, size_t length); - -#endif /* _SAMBA_DATABLOB_H_ */ diff --git a/source4/lib/util/debug.c b/source4/lib/util/debug.c deleted file mode 100644 index b6edb908c7..0000000000 --- a/source4/lib/util/debug.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Samba debug functions - Copyright (C) Andrew Tridgell 2003 - Copyright (C) James J Myers 2003 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" -#include "system/filesys.h" -#include "system/time.h" -#include "dynconfig/dynconfig.h" - -/** - * @file - * @brief Debug logging - **/ - -/** - * this global variable determines what messages are printed - */ -int _debug_level = 0; -_PUBLIC_ int *debug_level = &_debug_level; -int *DEBUGLEVEL_CLASS = NULL; /* For samba 3 */ - -/* the registered mutex handlers */ -static struct { - const char *name; - struct debug_ops ops; -} debug_handlers; - -/* state variables for the debug system */ -static struct { - int fd; - enum debug_logtype logtype; - const char *prog_name; -} state; - -static bool reopen_logs_scheduled; -static bool check_reopen_logs(void) -{ - if (state.fd == 0 || reopen_logs_scheduled) { - reopen_logs_scheduled = false; - reopen_logs(); - } - - if (state.fd <= 0) - return false; - - return true; -} - -_PUBLIC_ void debug_schedule_reopen_logs(void) -{ - reopen_logs_scheduled = true; -} - -static void log_timestring(int level, const char *location, const char *func) -{ - char *t = NULL; - char *s = NULL; - - if (!check_reopen_logs()) return; - - if (state.logtype != DEBUG_FILE) return; - - t = timestring(NULL, time(NULL)); - if (!t) return; - - asprintf(&s, "[%s, %d %s:%s()]\n", t, level, location, func); - talloc_free(t); - if (!s) return; - - write(state.fd, s, strlen(s)); - free(s); -} - -/** - the backend for debug messages. Note that the DEBUG() macro has already - ensured that the log level has been met before this is called -*/ -_PUBLIC_ void dbghdr(int level, const char *location, const char *func) -{ - log_timestring(level, location, func); - log_task_id(); -} - - -_PUBLIC_ void dbghdrclass(int level, int class, const char *location, const char *func) -{ - /* Simple wrapper, Samba 4 doesn't do debug classes */ - dbghdr(level, location, func); -} - -/** - the backend for debug messages. Note that the DEBUG() macro has already - ensured that the log level has been met before this is called - - @note You should never have to call this function directly. Call the DEBUG() - macro instead. -*/ -_PUBLIC_ void dbgtext(const char *format, ...) -{ - va_list ap; - char *s = NULL; - - if (!check_reopen_logs()) return; - - va_start(ap, format); - vasprintf(&s, format, ap); - va_end(ap); - - write(state.fd, s, strlen(s)); - free(s); -} - -_PUBLIC_ const char *logfile = NULL; - -/** - reopen the log file (usually called because the log file name might have changed) -*/ -_PUBLIC_ void reopen_logs(void) -{ - char *fname = NULL; - int old_fd = state.fd; - - switch (state.logtype) { - case DEBUG_STDOUT: - state.fd = 1; - break; - - case DEBUG_STDERR: - state.fd = 2; - break; - - case DEBUG_FILE: - if (logfile && (*logfile) == '/') { - fname = strdup(logfile); - } else { - asprintf(&fname, "%s/%s.log", dyn_LOGFILEBASE, state.prog_name); - } - if (fname) { - int newfd = open(fname, O_CREAT|O_APPEND|O_WRONLY, 0600); - if (newfd == -1) { - DEBUG(1, ("Failed to open new logfile: %s\n", fname)); - old_fd = -1; - } else { - state.fd = newfd; - } - free(fname); - } else { - DEBUG(1, ("Failed to find name for file-based logfile!\n")); - } - - break; - } - - if (old_fd > 2) { - close(old_fd); - } -} - -/** - control the name of the logfile and whether logging will be to stdout, stderr - or a file -*/ -_PUBLIC_ void setup_logging(const char *prog_name, enum debug_logtype new_logtype) -{ - if (state.logtype < new_logtype) { - state.logtype = new_logtype; - } - if (prog_name) { - state.prog_name = prog_name; - } - reopen_logs(); -} - -/** - return a string constant containing n tabs - no more than 10 tabs are returned -*/ -_PUBLIC_ const char *do_debug_tab(int n) -{ - const char *tabs[] = {"", "\t", "\t\t", "\t\t\t", "\t\t\t\t", "\t\t\t\t\t", - "\t\t\t\t\t\t", "\t\t\t\t\t\t\t", "\t\t\t\t\t\t\t\t", - "\t\t\t\t\t\t\t\t\t", "\t\t\t\t\t\t\t\t\t\t"}; - return tabs[MIN(n, 10)]; -} - - -/** - log suspicious usage - print comments and backtrace -*/ -_PUBLIC_ void log_suspicious_usage(const char *from, const char *info) -{ - if (!debug_handlers.ops.log_suspicious_usage) return; - - debug_handlers.ops.log_suspicious_usage(from, info); -} - - -/** - print suspicious usage - print comments and backtrace -*/ -_PUBLIC_ void print_suspicious_usage(const char* from, const char* info) -{ - if (!debug_handlers.ops.print_suspicious_usage) return; - - debug_handlers.ops.print_suspicious_usage(from, info); -} - -_PUBLIC_ uint32_t get_task_id(void) -{ - if (debug_handlers.ops.get_task_id) { - return debug_handlers.ops.get_task_id(); - } - return getpid(); -} - -_PUBLIC_ void log_task_id(void) -{ - if (!debug_handlers.ops.log_task_id) return; - - if (!check_reopen_logs()) return; - - debug_handlers.ops.log_task_id(state.fd); -} - -/** - register a set of debug handlers. -*/ -_PUBLIC_ void register_debug_handlers(const char *name, struct debug_ops *ops) -{ - debug_handlers.name = name; - debug_handlers.ops = *ops; -} diff --git a/source4/lib/util/debug.h b/source4/lib/util/debug.h deleted file mode 100644 index 8f4fa2a8fc..0000000000 --- a/source4/lib/util/debug.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Samba debug defines - Copyright (C) Andrew Tridgell 2003 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file - * @brief Debugging macros - */ - -/* the debug operations structure - contains function pointers to - various debug implementations of each operation */ -struct debug_ops { - /* function to log (using DEBUG) suspicious usage of data structure */ - void (*log_suspicious_usage)(const char* from, const char* info); - - /* function to log (using printf) suspicious usage of data structure. - * To be used in circumstances when using DEBUG would cause loop. */ - void (*print_suspicious_usage)(const char* from, const char* info); - - /* function to return process/thread id */ - uint32_t (*get_task_id)(void); - - /* function to log process/thread id */ - void (*log_task_id)(int fd); -}; - -#define DEBUGLEVEL *debug_level -extern int DEBUGLEVEL; - -#define debug_ctx() (_debug_ctx?_debug_ctx:(_debug_ctx=talloc_new(NULL))) - -#define DEBUGLVL(level) ((level) <= DEBUGLEVEL) -#define _DEBUG(level, body, header) do { \ - if (DEBUGLVL(level)) { \ - void* _debug_ctx=NULL; \ - if (header) { \ - dbghdr(level, __location__, __FUNCTION__); \ - } \ - dbgtext body; \ - talloc_free(_debug_ctx); \ - } \ -} while (0) -/** - * Write to the debug log. - */ -#define DEBUG(level, body) _DEBUG(level, body, true) -/** - * Add data to an existing debug log entry. - */ -#define DEBUGADD(level, body) _DEBUG(level, body, false) - -/** - * Obtain indentation string for the debug log. - * - * Level specified by n. - */ -#define DEBUGTAB(n) do_debug_tab(n) - -/** Possible destinations for the debug log */ -enum debug_logtype {DEBUG_STDOUT = 0, DEBUG_FILE = 1, DEBUG_STDERR = 2}; - -/** - the backend for debug messages. Note that the DEBUG() macro has already - ensured that the log level has been met before this is called -*/ -_PUBLIC_ void dbghdr(int level, const char *location, const char *func); - -/** - reopen the log file (usually called because the log file name might have changed) -*/ -_PUBLIC_ void reopen_logs(void); - -/** - * this global variable determines what messages are printed - */ -_PUBLIC_ void debug_schedule_reopen_logs(void); - -/** - control the name of the logfile and whether logging will be to stdout, stderr - or a file -*/ -_PUBLIC_ void setup_logging(const char *prog_name, enum debug_logtype new_logtype); - -/** - return a string constant containing n tabs - no more than 10 tabs are returned -*/ -_PUBLIC_ const char *do_debug_tab(int n); - -/** - log suspicious usage - print comments and backtrace -*/ -_PUBLIC_ void log_suspicious_usage(const char *from, const char *info); - -/** - print suspicious usage - print comments and backtrace -*/ -_PUBLIC_ void print_suspicious_usage(const char* from, const char* info); -_PUBLIC_ uint32_t get_task_id(void); -_PUBLIC_ void log_task_id(void); - -/** - register a set of debug handlers. -*/ -_PUBLIC_ void register_debug_handlers(const char *name, struct debug_ops *ops); - -/** - the backend for debug messages. Note that the DEBUG() macro has already - ensured that the log level has been met before this is called - - @note You should never have to call this function directly. Call the DEBUG() - macro instead. -*/ -_PUBLIC_ void dbgtext(const char *format, ...) PRINTF_ATTRIBUTE(1,2); diff --git a/source4/lib/util/dlinklist.h b/source4/lib/util/dlinklist.h deleted file mode 100644 index 5624124459..0000000000 --- a/source4/lib/util/dlinklist.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - Unix SMB/CIFS implementation. - some simple double linked list macros - Copyright (C) Andrew Tridgell 1998 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* To use these macros you must have a structure containing a next and - prev pointer */ - -#ifndef _DLINKLIST_H -#define _DLINKLIST_H - - -/* hook into the front of the list */ -#define DLIST_ADD(list, p) \ -do { \ - if (!(list)) { \ - (list) = (p); \ - (p)->next = (p)->prev = NULL; \ - } else { \ - (list)->prev = (p); \ - (p)->next = (list); \ - (p)->prev = NULL; \ - (list) = (p); \ - }\ -} while (0) - -/* remove an element from a list - element doesn't have to be in list. */ -#define DLIST_REMOVE(list, p) \ -do { \ - if ((p) == (list)) { \ - (list) = (p)->next; \ - if (list) (list)->prev = NULL; \ - } else { \ - if ((p)->prev) (p)->prev->next = (p)->next; \ - if ((p)->next) (p)->next->prev = (p)->prev; \ - } \ - if ((p) != (list)) (p)->next = (p)->prev = NULL; \ -} while (0) - -/* promote an element to the top of the list */ -#define DLIST_PROMOTE(list, p) \ -do { \ - DLIST_REMOVE(list, p); \ - DLIST_ADD(list, p); \ -} while (0) - -/* hook into the end of the list - needs a tmp pointer */ -#define DLIST_ADD_END(list, p, type) \ -do { \ - if (!(list)) { \ - (list) = (p); \ - (p)->next = (p)->prev = NULL; \ - } else { \ - type tmp; \ - for (tmp = (list); tmp->next; tmp = tmp->next) ; \ - tmp->next = (p); \ - (p)->next = NULL; \ - (p)->prev = tmp; \ - } \ -} while (0) - -/* insert 'p' after the given element 'el' in a list. If el is NULL then - this is the same as a DLIST_ADD() */ -#define DLIST_ADD_AFTER(list, p, el) \ -do { \ - if (!(list) || !(el)) { \ - DLIST_ADD(list, p); \ - } else { \ - p->prev = el; \ - p->next = el->next; \ - el->next = p; \ - if (p->next) p->next->prev = p; \ - }\ -} while (0) - -/* demote an element to the end of the list, needs a tmp pointer */ -#define DLIST_DEMOTE(list, p, tmp) \ -do { \ - DLIST_REMOVE(list, p); \ - DLIST_ADD_END(list, p, tmp); \ -} while (0) - -/* concatenate two lists - putting all elements of the 2nd list at the - end of the first list */ -#define DLIST_CONCATENATE(list1, list2, type) \ -do { \ - if (!(list1)) { \ - (list1) = (list2); \ - } else { \ - type tmp; \ - for (tmp = (list1); tmp->next; tmp = tmp->next) ; \ - tmp->next = (list2); \ - if (list2) { \ - (list2)->prev = tmp; \ - } \ - } \ -} while (0) - -#endif /* _DLINKLIST_H */ diff --git a/source4/lib/util/dprintf.c b/source4/lib/util/dprintf.c deleted file mode 100644 index e4f02758eb..0000000000 --- a/source4/lib/util/dprintf.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - Unix SMB/CIFS implementation. - display print functions - Copyright (C) Andrew Tridgell 2001 - Copyright (C) Jelmer Vernooij 2007 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - - -/* - this module provides functions for printing internal strings in the - "display charset". - - This charset may be quite different from the chosen unix charset. - - Eventually these functions will need to take care of column count constraints - - The d_ prefix on print functions in Samba refers to the display character set - conversion -*/ - -#include "includes.h" -#include "system/locale.h" -#include "param/param.h" - -static smb_iconv_t display_cd = (smb_iconv_t)-1; - -void d_set_iconv(smb_iconv_t cd) -{ - display_cd = cd; -} - -_PUBLIC_ int d_vfprintf(FILE *f, const char *format, va_list ap) -{ - char *p, *p2; - int ret, clen; - va_list ap2; - - /* If there's nothing to convert, take a shortcut */ - if (display_cd == (smb_iconv_t)-1) { - return vfprintf(f, format, ap); - } - - /* do any message translations */ - va_copy(ap2, ap); - ret = vasprintf(&p, format, ap2); - va_end(ap2); - - if (ret <= 0) return ret; - - clen = convert_string_talloc_descriptor(NULL, display_cd, p, ret, (void **)&p2); - if (clen == -1) { - /* the string can't be converted - do the best we can, - filling in non-printing chars with '?' */ - int i; - for (i=0;i. -*/ - -#include "includes.h" -#include "version.h" -#include "system/wait.h" -#include "system/filesys.h" - -/** - * @file - * @brief Fault handling - */ - -/* the registered fault handler */ -static struct { - const char *name; - void (*fault_handler)(int sig); -} fault_handlers; - -static const char *progname; - -#ifdef HAVE_BACKTRACE -#include -#elif HAVE_LIBEXC_H -#include -#endif - -/** - * Write backtrace to debug log - */ -_PUBLIC_ void call_backtrace(void) -{ -#ifdef HAVE_BACKTRACE -#ifndef BACKTRACE_STACK_SIZE -#define BACKTRACE_STACK_SIZE 64 -#endif - void *backtrace_stack[BACKTRACE_STACK_SIZE]; - size_t backtrace_size; - char **backtrace_strings; - - /* get the backtrace (stack frames) */ - backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE); - backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size); - - DEBUG(0, ("BACKTRACE: %lu stack frames:\n", - (unsigned long)backtrace_size)); - - if (backtrace_strings) { - int i; - - for (i = 0; i < backtrace_size; i++) - DEBUGADD(0, (" #%u %s\n", i, backtrace_strings[i])); - - /* Leak the backtrace_strings, rather than risk what free() might do */ - } - -#elif HAVE_LIBEXC - -#define NAMESIZE 32 /* Arbitrary */ -#ifndef BACKTRACE_STACK_SIZE -#define BACKTRACE_STACK_SIZE 64 -#endif - - /* The IRIX libexc library provides an API for unwinding the stack. See - * libexc(3) for details. Apparantly trace_back_stack leaks memory, but - * since we are about to abort anyway, it hardly matters. - * - * Note that if we paniced due to a SIGSEGV or SIGBUS (or similar) this - * will fail with a nasty message upon failing to open the /proc entry. - */ - { - uint64_t addrs[BACKTRACE_STACK_SIZE]; - char * names[BACKTRACE_STACK_SIZE]; - char namebuf[BACKTRACE_STACK_SIZE * NAMESIZE]; - - int i; - int levels; - - ZERO_ARRAY(addrs); - ZERO_ARRAY(names); - ZERO_ARRAY(namebuf); - - for (i = 0; i < BACKTRACE_STACK_SIZE; i++) { - names[i] = namebuf + (i * NAMESIZE); - } - - levels = trace_back_stack(0, addrs, names, - BACKTRACE_STACK_SIZE, NAMESIZE); - - DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels)); - for (i = 0; i < levels; i++) { - DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i])); - } - } -#undef NAMESIZE -#endif -} - -_PUBLIC_ const char *panic_action = NULL; - -/** - Something really nasty happened - panic ! -**/ -_PUBLIC_ _NORETURN_ void smb_panic(const char *why) -{ - int result; - - if (panic_action && *panic_action) { - char pidstr[20]; - char cmdstring[200]; - safe_strcpy(cmdstring, panic_action, sizeof(cmdstring)); - snprintf(pidstr, sizeof(pidstr), "%u", getpid()); - all_string_sub(cmdstring, "%PID%", pidstr, sizeof(cmdstring)); - if (progname) { - all_string_sub(cmdstring, "%PROG%", progname, sizeof(cmdstring)); - } - DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmdstring)); - result = system(cmdstring); - - if (result == -1) - DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n", - strerror(errno))); - else - DEBUG(0, ("smb_panic(): action returned status %d\n", - WEXITSTATUS(result))); - } - DEBUG(0,("PANIC: %s\n", why)); - - call_backtrace(); - -#ifdef SIGABRT - CatchSignal(SIGABRT,SIGNAL_CAST SIG_DFL); -#endif - abort(); -} - -/** -report a fault -**/ -_NORETURN_ static void fault_report(int sig) -{ - static int counter; - - if (counter) _exit(1); - - DEBUG(0,("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n")); - DEBUG(0,("INTERNAL ERROR: Signal %d in pid %d (%s)",sig,(int)getpid(),SAMBA_VERSION_STRING)); - DEBUG(0,("\nPlease read the file BUGS.txt in the distribution\n")); - DEBUG(0,("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n")); - - smb_panic("internal error"); - - exit(1); -} - -/** -catch serious errors -**/ -_NORETURN_ static void sig_fault(int sig) -{ - if (fault_handlers.fault_handler) { - /* we have a fault handler, call it. It may not return. */ - fault_handlers.fault_handler(sig); - } - /* If it returns or doesn't exist, use regular reporter */ - fault_report(sig); -} - -/** -setup our fault handlers -**/ -_PUBLIC_ void fault_setup(const char *pname) -{ - if (progname == NULL) { - progname = pname; - } -#ifdef SIGSEGV - CatchSignal(SIGSEGV,SIGNAL_CAST sig_fault); -#endif -#ifdef SIGBUS - CatchSignal(SIGBUS,SIGNAL_CAST sig_fault); -#endif -#ifdef SIGABRT - CatchSignal(SIGABRT,SIGNAL_CAST sig_fault); -#endif -#ifdef SIGFPE - CatchSignal(SIGFPE,SIGNAL_CAST sig_fault); -#endif -} - -/** - register a fault handler. - Should only be called once in the execution of smbd. -*/ -_PUBLIC_ bool register_fault_handler(const char *name, - void (*fault_handler)(int sig)) -{ - if (fault_handlers.name != NULL) { - /* it's already registered! */ - DEBUG(2,("fault handler '%s' already registered - failed '%s'\n", - fault_handlers.name, name)); - return false; - } - - fault_handlers.name = name; - fault_handlers.fault_handler = fault_handler; - - DEBUG(2,("fault handler '%s' registered\n", name)); - return true; -} diff --git a/source4/lib/util/fault.m4 b/source4/lib/util/fault.m4 deleted file mode 100644 index b24e63641c..0000000000 --- a/source4/lib/util/fault.m4 +++ /dev/null @@ -1,5 +0,0 @@ -AC_CHECK_HEADERS(execinfo.h) -AC_SEARCH_LIBS_EXT(backtrace, [execinfo], EXECINFO_LIBS) -AC_CHECK_FUNC_EXT(backtrace, $EXECINFO_LIBS) -SMB_EXT_LIB(EXECINFO,[${EXECINFO_LIBS}]) -SMB_ENABLE(EXECINFO) diff --git a/source4/lib/util/fsusage.c b/source4/lib/util/fsusage.c deleted file mode 100644 index 43c8787216..0000000000 --- a/source4/lib/util/fsusage.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - Unix SMB/CIFS implementation. - functions to calculate the free disk space - Copyright (C) Andrew Tridgell 1998-2000 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" -#include "system/filesys.h" - -/** - * @file - * @brief Utility functions for getting the amount of free disk space - */ - -/* Return the number of TOSIZE-byte blocks used by - BLOCKS FROMSIZE-byte blocks, rounding away from zero. -*/ -static uint64_t adjust_blocks(uint64_t blocks, uint64_t fromsize, uint64_t tosize) -{ - if (fromsize == tosize) /* e.g., from 512 to 512 */ - return blocks; - else if (fromsize > tosize) /* e.g., from 2048 to 512 */ - return blocks * (fromsize / tosize); - else /* e.g., from 256 to 512 */ - return (blocks + 1) / (tosize / fromsize); -} - -/** - * Retrieve amount of free disk space. - * this does all of the system specific guff to get the free disk space. - * It is derived from code in the GNU fileutils package, but has been - * considerably mangled for use here - * - * results are returned in *dfree and *dsize, in 512 byte units -*/ -_PUBLIC_ int sys_fsusage(const char *path, uint64_t *dfree, uint64_t *dsize) -{ -#ifdef STAT_STATFS3_OSF1 -#define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_fsize, (uint64_t)512) - struct statfs fsd; - - if (statfs (path, &fsd, sizeof (struct statfs)) != 0) - return -1; -#endif /* STAT_STATFS3_OSF1 */ - -#ifdef STAT_STATFS2_FS_DATA /* Ultrix */ -#define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)1024, (uint64_t)512) - struct fs_data fsd; - - if (statfs (path, &fsd) != 1) - return -1; - - (*dsize) = CONVERT_BLOCKS (fsd.fd_req.btot); - (*dfree) = CONVERT_BLOCKS (fsd.fd_req.bfreen); -#endif /* STAT_STATFS2_FS_DATA */ - -#ifdef STAT_STATFS2_BSIZE /* 4.3BSD, SunOS 4, HP-UX, AIX */ -#define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_bsize, (uint64_t)512) - struct statfs fsd; - - if (statfs (path, &fsd) < 0) - return -1; - -#ifdef STATFS_TRUNCATES_BLOCK_COUNTS - /* In SunOS 4.1.2, 4.1.3, and 4.1.3_U1, the block counts in the - struct statfs are truncated to 2GB. These conditions detect that - truncation, presumably without botching the 4.1.1 case, in which - the values are not truncated. The correct counts are stored in - undocumented spare fields. */ - if (fsd.f_blocks == 0x1fffff && fsd.f_spare[0] > 0) { - fsd.f_blocks = fsd.f_spare[0]; - fsd.f_bfree = fsd.f_spare[1]; - fsd.f_bavail = fsd.f_spare[2]; - } -#endif /* STATFS_TRUNCATES_BLOCK_COUNTS */ -#endif /* STAT_STATFS2_BSIZE */ - - -#ifdef STAT_STATFS2_FSIZE /* 4.4BSD */ -#define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_fsize, (uint64_t)512) - - struct statfs fsd; - - if (statfs (path, &fsd) < 0) - return -1; -#endif /* STAT_STATFS2_FSIZE */ - -#ifdef STAT_STATFS4 /* SVR3, Dynix, Irix, AIX */ -# if _AIX || defined(_CRAY) -# define CONVERT_BLOCKS(B) adjust_blocks ((uint64_t)(B), (uint64_t)fsd.f_bsize, (uint64_t)512) -# ifdef _CRAY -# define f_bavail f_bfree -# endif -# else -# define CONVERT_BLOCKS(B) ((uint64_t)B) -# ifndef _SEQUENT_ /* _SEQUENT_ is DYNIX/ptx */ -# ifndef DOLPHIN /* DOLPHIN 3.8.alfa/7.18 has f_bavail */ -# define f_bavail f_bfree -# endif -# endif -# endif - - struct statfs fsd; - - if (statfs (path, &fsd, sizeof fsd, 0) < 0) - return -1; - /* Empirically, the block counts on most SVR3 and SVR3-derived - systems seem to always be in terms of 512-byte blocks, - no matter what value f_bsize has. */ - -#endif /* STAT_STATFS4 */ - -#if defined(STAT_STATVFS) || defined(STAT_STATVFS64) /* SVR4 */ -# define CONVERT_BLOCKS(B) \ - adjust_blocks ((uint64_t)(B), fsd.f_frsize ? (uint64_t)fsd.f_frsize : (uint64_t)fsd.f_bsize, (uint64_t)512) - -#ifdef STAT_STATVFS64 - struct statvfs64 fsd; - if (statvfs64(path, &fsd) < 0) return -1; -#else - struct statvfs fsd; - if (statvfs(path, &fsd) < 0) return -1; -#endif - - /* f_frsize isn't guaranteed to be supported. */ - -#endif /* STAT_STATVFS */ - -#ifndef CONVERT_BLOCKS - /* we don't have any dfree code! */ - return -1; -#else -#if !defined(STAT_STATFS2_FS_DATA) - /* !Ultrix */ - (*dsize) = CONVERT_BLOCKS (fsd.f_blocks); - (*dfree) = CONVERT_BLOCKS (fsd.f_bavail); -#endif /* not STAT_STATFS2_FS_DATA */ -#endif - - return 0; -} diff --git a/source4/lib/util/fsusage.m4 b/source4/lib/util/fsusage.m4 deleted file mode 100644 index 6d5d13fe25..0000000000 --- a/source4/lib/util/fsusage.m4 +++ /dev/null @@ -1,190 +0,0 @@ -################################################# -# these tests are taken from the GNU fileutils package -AC_CHECKING(how to get filesystem space usage) -AC_CHECK_HEADERS(sys/statfs.h sys/statvfs.h sys/vfs.h) - -AC_CHECK_HEADERS(sys/mount.h, , , [AC_INCLUDES_DEFAULT -#ifdef HAVE_SYS_PARAM_H -#include -#endif]) - -space=no - -# Test for statvfs64. -if test $space = no; then - # SVR4 - AC_CACHE_CHECK([statvfs64 function (SVR4)], fu_cv_sys_stat_statvfs64, - [AC_TRY_RUN([ -#if defined(HAVE_UNISTD_H) -#include -#endif -#include -#include - main () - { - struct statvfs64 fsd; - exit (statvfs64 (".", &fsd)); - }], - fu_cv_sys_stat_statvfs64=yes, - fu_cv_sys_stat_statvfs64=no, - fu_cv_sys_stat_statvfs64=cross)]) - if test $fu_cv_sys_stat_statvfs64 = yes; then - space=yes - AC_DEFINE(STAT_STATVFS64,1,[Whether statvfs64() is available]) - fi -fi - -# Perform only the link test since it seems there are no variants of the -# statvfs function. This check is more than just AC_CHECK_FUNCS(statvfs) -# because that got a false positive on SCO OSR5. Adding the declaration -# of a `struct statvfs' causes this test to fail (as it should) on such -# systems. That system is reported to work fine with STAT_STATFS4 which -# is what it gets when this test fails. -if test $space = no; then - # SVR4 - AC_CACHE_CHECK([statvfs function (SVR4)], fu_cv_sys_stat_statvfs, - [AC_TRY_LINK([#include -#include ], - [struct statvfs fsd; statvfs (0, &fsd);], - fu_cv_sys_stat_statvfs=yes, - fu_cv_sys_stat_statvfs=no)]) - if test $fu_cv_sys_stat_statvfs = yes; then - space=yes - AC_DEFINE(STAT_STATVFS,1,[Whether statvfs() is available]) - fi -fi - -if test $space = no; then - # DEC Alpha running OSF/1 - AC_MSG_CHECKING([for 3-argument statfs function (DEC OSF/1)]) - AC_CACHE_VAL(fu_cv_sys_stat_statfs3_osf1, - [AC_TRY_RUN([ -#include -#include -#include - main () - { - struct statfs fsd; - fsd.f_fsize = 0; - exit (statfs (".", &fsd, sizeof (struct statfs))); - }], - fu_cv_sys_stat_statfs3_osf1=yes, - fu_cv_sys_stat_statfs3_osf1=no, - fu_cv_sys_stat_statfs3_osf1=no)]) - AC_MSG_RESULT($fu_cv_sys_stat_statfs3_osf1) - if test $fu_cv_sys_stat_statfs3_osf1 = yes; then - space=yes - AC_DEFINE(STAT_STATFS3_OSF1,1,[Whether statfs requires 3 arguments]) - fi -fi - -if test $space = no; then -# AIX - AC_MSG_CHECKING([for two-argument statfs with statfs.bsize dnl -member (AIX, 4.3BSD)]) - AC_CACHE_VAL(fu_cv_sys_stat_statfs2_bsize, - [AC_TRY_RUN([ -#ifdef HAVE_SYS_PARAM_H -#include -#endif -#ifdef HAVE_SYS_MOUNT_H -#include -#endif -#ifdef HAVE_SYS_VFS_H -#include -#endif - main () - { - struct statfs fsd; - fsd.f_bsize = 0; - exit (statfs (".", &fsd)); - }], - fu_cv_sys_stat_statfs2_bsize=yes, - fu_cv_sys_stat_statfs2_bsize=no, - fu_cv_sys_stat_statfs2_bsize=no)]) - AC_MSG_RESULT($fu_cv_sys_stat_statfs2_bsize) - if test $fu_cv_sys_stat_statfs2_bsize = yes; then - space=yes - AC_DEFINE(STAT_STATFS2_BSIZE,1,[Whether statfs requires two arguments and struct statfs has bsize property]) - fi -fi - -if test $space = no; then -# SVR3 - AC_MSG_CHECKING([for four-argument statfs (AIX-3.2.5, SVR3)]) - AC_CACHE_VAL(fu_cv_sys_stat_statfs4, - [AC_TRY_RUN([#include -#include - main () - { - struct statfs fsd; - exit (statfs (".", &fsd, sizeof fsd, 0)); - }], - fu_cv_sys_stat_statfs4=yes, - fu_cv_sys_stat_statfs4=no, - fu_cv_sys_stat_statfs4=no)]) - AC_MSG_RESULT($fu_cv_sys_stat_statfs4) - if test $fu_cv_sys_stat_statfs4 = yes; then - space=yes - AC_DEFINE(STAT_STATFS4,1,[Whether statfs requires 4 arguments]) - fi -fi - -if test $space = no; then -# 4.4BSD and NetBSD - AC_MSG_CHECKING([for two-argument statfs with statfs.fsize dnl -member (4.4BSD and NetBSD)]) - AC_CACHE_VAL(fu_cv_sys_stat_statfs2_fsize, - [AC_TRY_RUN([#include -#ifdef HAVE_SYS_PARAM_H -#include -#endif -#ifdef HAVE_SYS_MOUNT_H -#include -#endif - main () - { - struct statfs fsd; - fsd.f_fsize = 0; - exit (statfs (".", &fsd)); - }], - fu_cv_sys_stat_statfs2_fsize=yes, - fu_cv_sys_stat_statfs2_fsize=no, - fu_cv_sys_stat_statfs2_fsize=no)]) - AC_MSG_RESULT($fu_cv_sys_stat_statfs2_fsize) - if test $fu_cv_sys_stat_statfs2_fsize = yes; then - space=yes - AC_DEFINE(STAT_STATFS2_FSIZE,1,[Whether statfs requires 2 arguments and struct statfs has fsize]) - fi -fi - -if test $space = no; then - # Ultrix - AC_MSG_CHECKING([for two-argument statfs with struct fs_data (Ultrix)]) - AC_CACHE_VAL(fu_cv_sys_stat_fs_data, - [AC_TRY_RUN([#include -#ifdef HAVE_SYS_PARAM_H -#include -#endif -#ifdef HAVE_SYS_MOUNT_H -#include -#endif -#ifdef HAVE_SYS_FS_TYPES_H -#include -#endif - main () - { - struct fs_data fsd; - /* Ultrix's statfs returns 1 for success, - 0 for not mounted, -1 for failure. */ - exit (statfs (".", &fsd) != 1); - }], - fu_cv_sys_stat_fs_data=yes, - fu_cv_sys_stat_fs_data=no, - fu_cv_sys_stat_fs_data=no)]) - AC_MSG_RESULT($fu_cv_sys_stat_fs_data) - if test $fu_cv_sys_stat_fs_data = yes; then - space=yes - AC_DEFINE(STAT_STATFS2_FS_DATA,1,[Whether statfs requires 2 arguments and struct fs_data is available]) - fi -fi diff --git a/source4/lib/util/genrand.c b/source4/lib/util/genrand.c deleted file mode 100644 index cd1823a9a0..0000000000 --- a/source4/lib/util/genrand.c +++ /dev/null @@ -1,361 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Functions to create reasonable random numbers for crypto use. - - Copyright (C) Jeremy Allison 2001 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" -#include "system/filesys.h" -#include "../lib/crypto/crypto.h" -#include "system/locale.h" - -/** - * @file - * @brief Random number generation - */ - -static unsigned char hash[258]; -static uint32_t counter; - -static bool done_reseed = false; -static unsigned int bytes_since_reseed = 0; - -static int urand_fd = -1; - -static void (*reseed_callback)(void *userdata, int *newseed); -static void *reseed_callback_userdata = NULL; - -/** - Copy any user given reseed data. -**/ - -_PUBLIC_ void set_rand_reseed_callback(void (*fn)(void *, int *), void *userdata) -{ - reseed_callback = fn; - reseed_callback_userdata = userdata; - set_need_random_reseed(); -} - -/** - * Tell the random number generator it needs to reseed. - */ -_PUBLIC_ void set_need_random_reseed(void) -{ - done_reseed = false; - bytes_since_reseed = 0; -} - -static void get_rand_reseed_data(int *reseed_data) -{ - if (reseed_callback) { - reseed_callback(reseed_callback_userdata, reseed_data); - } else { - *reseed_data = 0; - } -} - -/**************************************************************** - Setup the seed. -*****************************************************************/ - -static void seed_random_stream(unsigned char *seedval, size_t seedlen) -{ - unsigned char j = 0; - size_t ind; - - for (ind = 0; ind < 256; ind++) - hash[ind] = (unsigned char)ind; - - for( ind = 0; ind < 256; ind++) { - unsigned char tc; - - j += (hash[ind] + seedval[ind%seedlen]); - - tc = hash[ind]; - hash[ind] = hash[j]; - hash[j] = tc; - } - - hash[256] = 0; - hash[257] = 0; -} - -/**************************************************************** - Get datasize bytes worth of random data. -*****************************************************************/ - -static void get_random_stream(unsigned char *data, size_t datasize) -{ - unsigned char index_i = hash[256]; - unsigned char index_j = hash[257]; - size_t ind; - - for( ind = 0; ind < datasize; ind++) { - unsigned char tc; - unsigned char t; - - index_i++; - index_j += hash[index_i]; - - tc = hash[index_i]; - hash[index_i] = hash[index_j]; - hash[index_j] = tc; - - t = hash[index_i] + hash[index_j]; - data[ind] = hash[t]; - } - - hash[256] = index_i; - hash[257] = index_j; -} - -/**************************************************************** - Get a 16 byte hash from the contents of a file. - - Note that the hash is initialised, because the extra entropy is not - worth the valgrind pain. -*****************************************************************/ - -static void do_filehash(const char *fname, unsigned char *the_hash) -{ - unsigned char buf[1011]; /* deliberate weird size */ - unsigned char tmp_md4[16]; - int fd, n; - - ZERO_STRUCT(tmp_md4); - - fd = open(fname,O_RDONLY,0); - if (fd == -1) - return; - - while ((n = read(fd, (char *)buf, sizeof(buf))) > 0) { - mdfour(tmp_md4, buf, n); - for (n=0;n<16;n++) - the_hash[n] ^= tmp_md4[n]; - } - close(fd); -} - -/************************************************************** - Try and get a good random number seed. Try a number of - different factors. Firstly, try /dev/urandom - use if exists. - - We use /dev/urandom as a read of /dev/random can block if - the entropy pool dries up. This leads clients to timeout - or be very slow on connect. - - If we can't use /dev/urandom then seed the stream random generator - above... -**************************************************************/ - -static int do_reseed(bool use_fd, int fd) -{ - unsigned char seed_inbuf[40]; - uint32_t v1, v2; struct timeval tval; pid_t mypid; - int reseed_data = 0; - - if (use_fd) { - if (fd == -1) { - fd = open( "/dev/urandom", O_RDONLY,0); - } - if (fd != -1 - && (read(fd, seed_inbuf, sizeof(seed_inbuf)) == sizeof(seed_inbuf))) { - seed_random_stream(seed_inbuf, sizeof(seed_inbuf)); - return fd; - } - } - - /* Add in some secret file contents */ - - do_filehash("/etc/shadow", &seed_inbuf[0]); - - /* - * Add the counter, time of day, and pid. - */ - - GetTimeOfDay(&tval); - mypid = getpid(); - v1 = (counter++) + mypid + tval.tv_sec; - v2 = (counter++) * mypid + tval.tv_usec; - - SIVAL(seed_inbuf, 32, v1 ^ IVAL(seed_inbuf, 32)); - SIVAL(seed_inbuf, 36, v2 ^ IVAL(seed_inbuf, 36)); - - /* - * Add any user-given reseed data. - */ - - get_rand_reseed_data(&reseed_data); - if (reseed_data) { - size_t i; - for (i = 0; i < sizeof(seed_inbuf); i++) - seed_inbuf[i] ^= ((char *)(&reseed_data))[i % sizeof(reseed_data)]; - } - - seed_random_stream(seed_inbuf, sizeof(seed_inbuf)); - - return -1; -} - -/** - Interface to the (hopefully) good crypto random number generator. - Will use our internal PRNG if more than 40 bytes of random generation - has been requested, otherwise tries to read from /dev/random -**/ -_PUBLIC_ void generate_random_buffer(uint8_t *out, int len) -{ - unsigned char md4_buf[64]; - unsigned char tmp_buf[16]; - unsigned char *p; - - if(!done_reseed) { - bytes_since_reseed += len; - - /* Magic constant to try and avoid reading 40 bytes - * and setting up the PRNG if the app only ever wants - * a few bytes */ - if (bytes_since_reseed < 40) { - if (urand_fd == -1) { - urand_fd = open( "/dev/urandom", O_RDONLY,0); - } - if(urand_fd != -1 && (read(urand_fd, out, len) == len)) { - return; - } - } - - urand_fd = do_reseed(true, urand_fd); - done_reseed = true; - } - - /* - * Generate random numbers in chunks of 64 bytes, - * then md4 them & copy to the output buffer. - * This way the raw state of the stream is never externally - * seen. - */ - - p = out; - while(len > 0) { - int copy_len = len > 16 ? 16 : len; - - get_random_stream(md4_buf, sizeof(md4_buf)); - mdfour(tmp_buf, md4_buf, sizeof(md4_buf)); - memcpy(p, tmp_buf, copy_len); - p += copy_len; - len -= copy_len; - } -} - -/** - Interface to the (hopefully) good crypto random number generator. - Will always use /dev/urandom if available. -**/ -_PUBLIC_ void generate_secret_buffer(uint8_t *out, int len) -{ - if (urand_fd == -1) { - urand_fd = open( "/dev/urandom", O_RDONLY,0); - } - if(urand_fd != -1 && (read(urand_fd, out, len) == len)) { - return; - } - - generate_random_buffer(out, len); -} - -/** - generate a single random uint32_t -**/ -_PUBLIC_ uint32_t generate_random(void) -{ - uint8_t v[4]; - generate_random_buffer(v, 4); - return IVAL(v, 0); -} - - -/** - very basic password quality checker -**/ -_PUBLIC_ bool check_password_quality(const char *s) -{ - int has_digit=0, has_capital=0, has_lower=0, has_special=0, has_high=0; - while (*s) { - if (isdigit((unsigned char)*s)) { - has_digit |= 1; - } else if (isupper((unsigned char)*s)) { - has_capital |= 1; - } else if (islower((unsigned char)*s)) { - has_lower |= 1; - } else if (isascii((unsigned char)*s)) { - has_special |= 1; - } else { - has_high++; - } - s++; - } - - return ((has_digit + has_lower + has_capital + has_special) >= 3 - || (has_high > strlen(s)/2)); -} - -/** - Use the random number generator to generate a random string. -**/ - -_PUBLIC_ char *generate_random_str_list(TALLOC_CTX *mem_ctx, size_t len, const char *list) -{ - size_t i; - size_t list_len = strlen(list); - - char *retstr = talloc_array(mem_ctx, char, len + 1); - if (!retstr) return NULL; - - generate_random_buffer((uint8_t *)retstr, len); - for (i = 0; i < len; i++) { - retstr[i] = list[retstr[i] % list_len]; - } - retstr[i] = '\0'; - - return retstr; -} - -/** - * Generate a random text string consisting of the specified length. - * The returned string will be allocated. - * - * Characters used are: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#., - */ - -_PUBLIC_ char *generate_random_str(TALLOC_CTX *mem_ctx, size_t len) -{ - char *retstr; - const char *c_list = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#.,"; - -again: - retstr = generate_random_str_list(mem_ctx, len, c_list); - if (!retstr) return NULL; - - /* we need to make sure the random string passes basic quality tests - or it might be rejected by windows as a password */ - if (len >= 7 && !check_password_quality(retstr)) { - talloc_free(retstr); - goto again; - } - - return retstr; -} diff --git a/source4/lib/util/idtree.c b/source4/lib/util/idtree.c deleted file mode 100644 index 193922973f..0000000000 --- a/source4/lib/util/idtree.c +++ /dev/null @@ -1,403 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - very efficient functions to manage mapping a id (such as a fnum) to - a pointer. This is used for fnum and search id allocation. - - Copyright (C) Andrew Tridgell 2004 - - This code is derived from lib/idr.c in the 2.6 Linux kernel, which was - written by Jim Houston jim.houston@ccur.com, and is - Copyright (C) 2002 by Concurrent Computer Corporation - - 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 - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* - see the section marked "public interface" below for documentation -*/ - -/** - * @file - */ - -#include "includes.h" - -#define IDR_BITS 5 -#define IDR_FULL 0xfffffffful -#if 0 /* unused */ -#define TOP_LEVEL_FULL (IDR_FULL >> 30) -#endif -#define IDR_SIZE (1 << IDR_BITS) -#define IDR_MASK ((1 << IDR_BITS)-1) -#define MAX_ID_SHIFT (sizeof(int)*8 - 1) -#define MAX_ID_BIT (1U << MAX_ID_SHIFT) -#define MAX_ID_MASK (MAX_ID_BIT - 1) -#define MAX_LEVEL (MAX_ID_SHIFT + IDR_BITS - 1) / IDR_BITS -#define IDR_FREE_MAX MAX_LEVEL + MAX_LEVEL - -#define set_bit(bit, v) (v) |= (1<<(bit)) -#define clear_bit(bit, v) (v) &= ~(1<<(bit)) -#define test_bit(bit, v) ((v) & (1<<(bit))) - -struct idr_layer { - uint32_t bitmap; - struct idr_layer *ary[IDR_SIZE]; - int count; -}; - -struct idr_context { - struct idr_layer *top; - struct idr_layer *id_free; - int layers; - int id_free_cnt; -}; - -static struct idr_layer *alloc_layer(struct idr_context *idp) -{ - struct idr_layer *p; - - if (!(p = idp->id_free)) - return NULL; - idp->id_free = p->ary[0]; - idp->id_free_cnt--; - p->ary[0] = NULL; - return p; -} - -static int find_next_bit(uint32_t bm, int maxid, int n) -{ - while (nary[0] = idp->id_free; - idp->id_free = p; - idp->id_free_cnt++; -} - -static int idr_pre_get(struct idr_context *idp) -{ - while (idp->id_free_cnt < IDR_FREE_MAX) { - struct idr_layer *new = talloc_zero(idp, struct idr_layer); - if(new == NULL) - return (0); - free_layer(idp, new); - } - return 1; -} - -static int sub_alloc(struct idr_context *idp, void *ptr, int *starting_id) -{ - int n, m, sh; - struct idr_layer *p, *new; - struct idr_layer *pa[MAX_LEVEL]; - int l, id, oid; - uint32_t bm; - - memset(pa, 0, sizeof(pa)); - - id = *starting_id; -restart: - p = idp->top; - l = idp->layers; - pa[l--] = NULL; - while (1) { - /* - * We run around this while until we reach the leaf node... - */ - n = (id >> (IDR_BITS*l)) & IDR_MASK; - bm = ~p->bitmap; - m = find_next_bit(bm, IDR_SIZE, n); - if (m == IDR_SIZE) { - /* no space available go back to previous layer. */ - l++; - oid = id; - id = (id | ((1 << (IDR_BITS*l))-1)) + 1; - - /* if already at the top layer, we need to grow */ - if (!(p = pa[l])) { - *starting_id = id; - return -2; - } - - /* If we need to go up one layer, continue the - * loop; otherwise, restart from the top. - */ - sh = IDR_BITS * (l + 1); - if (oid >> sh == id >> sh) - continue; - else - goto restart; - } - if (m != n) { - sh = IDR_BITS*l; - id = ((id >> sh) ^ n ^ m) << sh; - } - if ((id >= MAX_ID_BIT) || (id < 0)) - return -1; - if (l == 0) - break; - /* - * Create the layer below if it is missing. - */ - if (!p->ary[m]) { - if (!(new = alloc_layer(idp))) - return -1; - p->ary[m] = new; - p->count++; - } - pa[l--] = p; - p = p->ary[m]; - } - /* - * We have reached the leaf node, plant the - * users pointer and return the raw id. - */ - p->ary[m] = (struct idr_layer *)ptr; - set_bit(m, p->bitmap); - p->count++; - /* - * If this layer is full mark the bit in the layer above - * to show that this part of the radix tree is full. - * This may complete the layer above and require walking - * up the radix tree. - */ - n = id; - while (p->bitmap == IDR_FULL) { - if (!(p = pa[++l])) - break; - n = n >> IDR_BITS; - set_bit((n & IDR_MASK), p->bitmap); - } - return(id); -} - -static int idr_get_new_above_int(struct idr_context *idp, void *ptr, int starting_id) -{ - struct idr_layer *p, *new; - int layers, v, id; - - idr_pre_get(idp); - - id = starting_id; -build_up: - p = idp->top; - layers = idp->layers; - if (!p) { - if (!(p = alloc_layer(idp))) - return -1; - layers = 1; - } - /* - * Add a new layer to the top of the tree if the requested - * id is larger than the currently allocated space. - */ - while ((layers < MAX_LEVEL) && (id >= (1 << (layers*IDR_BITS)))) { - layers++; - if (!p->count) - continue; - if (!(new = alloc_layer(idp))) { - /* - * The allocation failed. If we built part of - * the structure tear it down. - */ - for (new = p; p && p != idp->top; new = p) { - p = p->ary[0]; - new->ary[0] = NULL; - new->bitmap = new->count = 0; - free_layer(idp, new); - } - return -1; - } - new->ary[0] = p; - new->count = 1; - if (p->bitmap == IDR_FULL) - set_bit(0, new->bitmap); - p = new; - } - idp->top = p; - idp->layers = layers; - v = sub_alloc(idp, ptr, &id); - if (v == -2) - goto build_up; - return(v); -} - -static int sub_remove(struct idr_context *idp, int shift, int id) -{ - struct idr_layer *p = idp->top; - struct idr_layer **pa[MAX_LEVEL]; - struct idr_layer ***paa = &pa[0]; - int n; - - *paa = NULL; - *++paa = &idp->top; - - while ((shift > 0) && p) { - n = (id >> shift) & IDR_MASK; - clear_bit(n, p->bitmap); - *++paa = &p->ary[n]; - p = p->ary[n]; - shift -= IDR_BITS; - } - n = id & IDR_MASK; - if (p != NULL && test_bit(n, p->bitmap)) { - clear_bit(n, p->bitmap); - p->ary[n] = NULL; - while(*paa && ! --((**paa)->count)){ - free_layer(idp, **paa); - **paa-- = NULL; - } - if ( ! *paa ) - idp->layers = 0; - return 0; - } - return -1; -} - -static void *_idr_find(struct idr_context *idp, int id) -{ - int n; - struct idr_layer *p; - - n = idp->layers * IDR_BITS; - p = idp->top; - /* - * This tests to see if bits outside the current tree are - * present. If so, tain't one of ours! - */ - if ((id & ~(~0 << MAX_ID_SHIFT)) >> (n + IDR_BITS)) - return NULL; - - /* Mask off upper bits we don't use for the search. */ - id &= MAX_ID_MASK; - - while (n >= IDR_BITS && p) { - n -= IDR_BITS; - p = p->ary[(id >> n) & IDR_MASK]; - } - return((void *)p); -} - -static int _idr_remove(struct idr_context *idp, int id) -{ - struct idr_layer *p; - - /* Mask off upper bits we don't use for the search. */ - id &= MAX_ID_MASK; - - if (sub_remove(idp, (idp->layers - 1) * IDR_BITS, id) == -1) { - return -1; - } - - if ( idp->top && idp->top->count == 1 && - (idp->layers > 1) && - idp->top->ary[0]) { - /* We can drop a layer */ - p = idp->top->ary[0]; - idp->top->bitmap = idp->top->count = 0; - free_layer(idp, idp->top); - idp->top = p; - --idp->layers; - } - while (idp->id_free_cnt >= IDR_FREE_MAX) { - p = alloc_layer(idp); - talloc_free(p); - } - return 0; -} - -/************************************************************************ - this is the public interface -**************************************************************************/ - -/** - initialise a idr tree. The context return value must be passed to - all subsequent idr calls. To destroy the idr tree use talloc_free() - on this context - */ -_PUBLIC_ struct idr_context *idr_init(TALLOC_CTX *mem_ctx) -{ - return talloc_zero(mem_ctx, struct idr_context); -} - -/** - allocate the next available id, and assign 'ptr' into its slot. - you can retrieve later this pointer using idr_find() -*/ -_PUBLIC_ int idr_get_new(struct idr_context *idp, void *ptr, int limit) -{ - int ret = idr_get_new_above_int(idp, ptr, 0); - if (ret > limit) { - idr_remove(idp, ret); - return -1; - } - return ret; -} - -/** - allocate a new id, giving the first available value greater than or - equal to the given starting id -*/ -_PUBLIC_ int idr_get_new_above(struct idr_context *idp, void *ptr, int starting_id, int limit) -{ - int ret = idr_get_new_above_int(idp, ptr, starting_id); - if (ret > limit) { - idr_remove(idp, ret); - return -1; - } - return ret; -} - -/** - allocate a new id randomly in the given range -*/ -_PUBLIC_ int idr_get_new_random(struct idr_context *idp, void *ptr, int limit) -{ - int id; - - /* first try a random starting point in the whole range, and if that fails, - then start randomly in the bottom half of the range. This can only - fail if the range is over half full */ - id = idr_get_new_above(idp, ptr, 1+(generate_random() % limit), limit); - if (id == -1) { - id = idr_get_new_above(idp, ptr, 1+(generate_random()%(limit/2)), limit); - } - - return id; -} - -/** - find a pointer value previously set with idr_get_new given an id -*/ -_PUBLIC_ void *idr_find(struct idr_context *idp, int id) -{ - return _idr_find(idp, id); -} - -/** - remove an id from the idr tree -*/ -_PUBLIC_ int idr_remove(struct idr_context *idp, int id) -{ - int ret; - ret = _idr_remove((struct idr_context *)idp, id); - if (ret != 0) { - DEBUG(0,("WARNING: attempt to remove unset id %d in idtree\n", id)); - } - return ret; -} diff --git a/source4/lib/util/mainpage.dox b/source4/lib/util/mainpage.dox deleted file mode 100644 index 464151e771..0000000000 --- a/source4/lib/util/mainpage.dox +++ /dev/null @@ -1,11 +0,0 @@ -/** - -\mainpage util - -\section Introduction - -This library contains convenience functions that are used heavily -throughout Samba. None of these functions are SMB or Samba-specific. -It's a bit to Samba what GLib is to the GNOME folks. - -*/ diff --git a/source4/lib/util/ms_fnmatch.c b/source4/lib/util/ms_fnmatch.c deleted file mode 100644 index 5e04ec1f4b..0000000000 --- a/source4/lib/util/ms_fnmatch.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - Unix SMB/CIFS implementation. - filename matching routine - Copyright (C) Andrew Tridgell 1992-2004 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* - This module was originally based on fnmatch.c copyright by the Free - Software Foundation. It bears little (if any) resemblence to that - code now -*/ - -/** - * @file - * @brief MS-style Filename matching - */ - -#include "includes.h" -#include "param/param.h" - -static int null_match(const char *p) -{ - for (;*p;p++) { - if (*p != '*' && - *p != '<' && - *p != '"' && - *p != '>') return -1; - } - return 0; -} - -/* - the max_n structure is purely for efficiency, it doesn't contribute - to the matching algorithm except by ensuring that the algorithm does - not grow exponentially -*/ -struct max_n { - const char *predot; - const char *postdot; -}; - - -/* - p and n are the pattern and string being matched. The max_n array is - an optimisation only. The ldot pointer is NULL if the string does - not contain a '.', otherwise it points at the last dot in 'n'. -*/ -static int ms_fnmatch_core(const char *p, const char *n, - struct max_n *max_n, const char *ldot) -{ - codepoint_t c, c2; - int i; - size_t size, size_n; - struct smb_iconv_convenience *iconv_convenience = lp_iconv_convenience(global_loadparm); - - while ((c = next_codepoint(iconv_convenience, p, &size))) { - p += size; - - switch (c) { - case '*': - /* a '*' matches zero or more characters of any type */ - if (max_n->predot && max_n->predot <= n) { - return null_match(p); - } - for (i=0; n[i]; i += size_n) { - next_codepoint(iconv_convenience, n+i, &size_n); - if (ms_fnmatch_core(p, n+i, max_n+1, ldot) == 0) { - return 0; - } - } - if (!max_n->predot || max_n->predot > n) max_n->predot = n; - return null_match(p); - - case '<': - /* a '<' matches zero or more characters of - any type, but stops matching at the last - '.' in the string. */ - if (max_n->predot && max_n->predot <= n) { - return null_match(p); - } - if (max_n->postdot && max_n->postdot <= n && n <= ldot) { - return -1; - } - for (i=0; n[i]; i += size_n) { - next_codepoint(iconv_convenience, n+i, &size_n); - if (ms_fnmatch_core(p, n+i, max_n+1, ldot) == 0) return 0; - if (n+i == ldot) { - if (ms_fnmatch_core(p, n+i+size_n, max_n+1, ldot) == 0) return 0; - if (!max_n->postdot || max_n->postdot > n) max_n->postdot = n; - return -1; - } - } - if (!max_n->predot || max_n->predot > n) max_n->predot = n; - return null_match(p); - - case '?': - /* a '?' matches any single character */ - if (! *n) { - return -1; - } - next_codepoint(iconv_convenience, n, &size_n); - n += size_n; - break; - - case '>': - /* a '?' matches any single character, but - treats '.' specially */ - if (n[0] == '.') { - if (! n[1] && null_match(p) == 0) { - return 0; - } - break; - } - if (! *n) return null_match(p); - next_codepoint(iconv_convenience, n, &size_n); - n += size_n; - break; - - case '"': - /* a bit like a soft '.' */ - if (*n == 0 && null_match(p) == 0) { - return 0; - } - if (*n != '.') return -1; - next_codepoint(iconv_convenience, n, &size_n); - n += size_n; - break; - - default: - c2 = next_codepoint(iconv_convenience, n, &size_n); - if (c != c2 && codepoint_cmpi(c, c2) != 0) { - return -1; - } - n += size_n; - break; - } - } - - if (! *n) { - return 0; - } - - return -1; -} - -int ms_fnmatch(const char *pattern, const char *string, enum protocol_types protocol) -{ - int ret, count, i; - struct max_n *max_n = NULL; - - if (strcmp(string, "..") == 0) { - string = "."; - } - - if (strpbrk(pattern, "<>*?\"") == NULL) { - /* this is not just an optimisation - it is essential - for LANMAN1 correctness */ - return strcasecmp_m(pattern, string); - } - - if (protocol <= PROTOCOL_LANMAN2) { - char *p = talloc_strdup(NULL, pattern); - if (p == NULL) { - return -1; - } - /* - for older negotiated protocols it is possible to - translate the pattern to produce a "new style" - pattern that exactly matches w2k behaviour - */ - for (i=0;p[i];i++) { - if (p[i] == '?') { - p[i] = '>'; - } else if (p[i] == '.' && - (p[i+1] == '?' || - p[i+1] == '*' || - p[i+1] == 0)) { - p[i] = '"'; - } else if (p[i] == '*' && - p[i+1] == '.') { - p[i] = '<'; - } - } - ret = ms_fnmatch(p, string, PROTOCOL_NT1); - talloc_free(p); - return ret; - } - - for (count=i=0;pattern[i];i++) { - if (pattern[i] == '*' || pattern[i] == '<') count++; - } - - max_n = talloc_zero_array(NULL, struct max_n, count); - if (max_n == NULL) { - return -1; - } - - ret = ms_fnmatch_core(pattern, string, max_n, strrchr(string, '.')); - - talloc_free(max_n); - - return ret; -} - - -/** a generic fnmatch function - uses for non-CIFS pattern matching */ -int gen_fnmatch(const char *pattern, const char *string) -{ - return ms_fnmatch(pattern, string, PROTOCOL_NT1); -} diff --git a/source4/lib/util/mutex.c b/source4/lib/util/mutex.c deleted file mode 100644 index 4d0df68eed..0000000000 --- a/source4/lib/util/mutex.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Samba mutex/lock functions - Copyright (C) Andrew Tridgell 2003 - Copyright (C) James J Myers 2003 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "includes.h" -#include "mutex.h" - -/** - * @file - * @brief Mutex utility functions - */ - -/* the registered mutex handlers */ -static struct { - const char *name; - struct mutex_ops ops; -} mutex_handlers; - -/* read/write lock routines */ - - -/** - register a set of mutex/rwlock handlers. - Should only be called once in the execution of smbd. -*/ -_PUBLIC_ bool register_mutex_handlers(const char *name, struct mutex_ops *ops) -{ - if (mutex_handlers.name != NULL) { - /* it's already registered! */ - DEBUG(2,("mutex handler '%s' already registered - failed '%s'\n", - mutex_handlers.name, name)); - return false; - } - - mutex_handlers.name = name; - mutex_handlers.ops = *ops; - - DEBUG(2,("mutex handler '%s' registered\n", name)); - return true; -} - diff --git a/source4/lib/util/mutex.h b/source4/lib/util/mutex.h deleted file mode 100644 index bf845906f2..0000000000 --- a/source4/lib/util/mutex.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef _MUTEX_H_ -#define _MUTEX_H_ -/* - Unix SMB/CIFS implementation. - Samba mutex functions - Copyright (C) Andrew Tridgell 2003 - Copyright (C) James J Myers 2003 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file - * @brief Mutex operations - */ - -struct mutex_ops; - -/* To add a new read/write lock, add it to enum rwlock_id - */ -enum rwlock_id { RWLOCK_SMBD, /* global smbd lock */ - - RWLOCK_MAX /* this MUST be kept last */ -}; - -#define MUTEX_LOCK_BY_ID(mutex_index) smb_mutex_lock_by_id(mutex_index, #mutex_index) -#define MUTEX_UNLOCK_BY_ID(mutex_index) smb_mutex_unlock_by_id(mutex_index, #mutex_index) -#define MUTEX_INIT(mutex, name) smb_mutex_init(mutex, #name) -#define MUTEX_DESTROY(mutex, name) smb_mutex_destroy(mutex, #name) -#define MUTEX_LOCK(mutex, name) smb_mutex_lock(mutex, #name) -#define MUTEX_UNLOCK(mutex, name) smb_mutex_unlock(mutex, #name) - -#define RWLOCK_INIT(rwlock, name) smb_rwlock_init(rwlock, #name) -#define RWLOCK_DESTROY(rwlock, name) smb_rwlock_destroy(rwlock, #name) -#define RWLOCK_LOCK_WRITE(rwlock, name) smb_rwlock_lock_write(rwlock, #name) -#define RWLOCK_LOCK_READ(rwlock, name) smb_rwlock_lock_read(rwlock, #name) -#define RWLOCK_UNLOCK(rwlock, name) smb_rwlock_unlock(rwlock, #name) - - - -/* this null typedef ensures we get the types right and avoids the - pitfalls of void* */ -typedef struct smb_mutex { - void *mutex; -} smb_mutex_t; -typedef struct { - void *rwlock; -} smb_rwlock_t; - -/* the mutex model operations structure - contains function pointers to - the model-specific implementations of each operation */ -struct mutex_ops { - int (*mutex_init)(smb_mutex_t *mutex, const char *name); - int (*mutex_lock)(smb_mutex_t *mutex, const char *name); - int (*mutex_unlock)(smb_mutex_t *mutex, const char *name); - int (*mutex_destroy)(smb_mutex_t *mutex, const char *name); - int (*rwlock_init)(smb_rwlock_t *rwlock, const char *name); - int (*rwlock_lock_write)(smb_rwlock_t *rwlock, const char *name); - int (*rwlock_lock_read)(smb_rwlock_t *rwlock, const char *name); - int (*rwlock_unlock)(smb_rwlock_t *rwlock, const char *name); - int (*rwlock_destroy)(smb_rwlock_t *rwlock, const char *name); -}; - -#endif /* endif _MUTEX_H_ */ diff --git a/source4/lib/util/params.c b/source4/lib/util/params.c deleted file mode 100644 index 3a9e2b9505..0000000000 --- a/source4/lib/util/params.c +++ /dev/null @@ -1,587 +0,0 @@ -/* -------------------------------------------------------------------------- ** - * Microsoft Network Services for Unix, AKA., Andrew Tridgell's SAMBA. - * - * This module Copyright (C) 1990-1998 Karl Auer - * - * Rewritten almost completely by Christopher R. Hertel - * at the University of Minnesota, September, 1997. - * This module Copyright (C) 1997-1998 by the University of Minnesota - * -------------------------------------------------------------------------- ** - * - * 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 3 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - * - * -------------------------------------------------------------------------- ** - * - * Module name: params - * - * -------------------------------------------------------------------------- ** - * - * This module performs lexical analysis and initial parsing of a - * Windows-like parameter file. It recognizes and handles four token - * types: section-name, parameter-name, parameter-value, and - * end-of-file. Comments and line continuation are handled - * internally. - * - * The entry point to the module is function pm_process(). This - * function opens the source file, calls the Parse() function to parse - * the input, and then closes the file when either the EOF is reached - * or a fatal error is encountered. - * - * A sample parameter file might look like this: - * - * [section one] - * parameter one = value string - * parameter two = another value - * [section two] - * new parameter = some value or t'other - * - * The parameter file is divided into sections by section headers: - * section names enclosed in square brackets (eg. [section one]). - * Each section contains parameter lines, each of which consist of a - * parameter name and value delimited by an equal sign. Roughly, the - * syntax is: - * - * :== {
} EOF - * - *
:==
{ } - * - *
:== '[' NAME ']' - * - * :== NAME '=' VALUE '\n' - * - * Blank lines and comment lines are ignored. Comment lines are lines - * beginning with either a semicolon (';') or a pound sign ('#'). - * - * All whitespace in section names and parameter names is compressed - * to single spaces. Leading and trailing whitespace is stipped from - * both names and values. - * - * Only the first equals sign in a parameter line is significant. - * Parameter values may contain equals signs, square brackets and - * semicolons. Internal whitespace is retained in parameter values, - * with the exception of the '\r' character, which is stripped for - * historic reasons. Parameter names may not start with a left square - * bracket, an equal sign, a pound sign, or a semicolon, because these - * are used to identify other tokens. - * - * -------------------------------------------------------------------------- ** - */ - -#include "includes.h" -#include "system/locale.h" - -/* -------------------------------------------------------------------------- ** - * Constants... - */ - -#define BUFR_INC 1024 - - -/* we can't use FILE* due to the 256 fd limit - use this cheap hack - instead */ -typedef struct { - char *buf; - char *p; - size_t size; - char *bufr; - int bSize; -} myFILE; - -static int mygetc(myFILE *f) -{ - if (f->p >= f->buf+f->size) return EOF; - /* be sure to return chars >127 as positive values */ - return (int)( *(f->p++) & 0x00FF ); -} - -static void myfile_close(myFILE *f) -{ - talloc_free(f); -} - -/* -------------------------------------------------------------------------- ** - * Functions... - */ - -static int EatWhitespace( myFILE *InFile ) - /* ------------------------------------------------------------------------ ** - * Scan past whitespace (see ctype(3C)) and return the first non-whitespace - * character, or newline, or EOF. - * - * Input: InFile - Input source. - * - * Output: The next non-whitespace character in the input stream. - * - * Notes: Because the config files use a line-oriented grammar, we - * explicitly exclude the newline character from the list of - * whitespace characters. - * - Note that both EOF (-1) and the nul character ('\0') are - * considered end-of-file markers. - * - * ------------------------------------------------------------------------ ** - */ - { - int c; - - for( c = mygetc( InFile ); isspace( c ) && ('\n' != c); c = mygetc( InFile ) ) - ; - return( c ); - } /* EatWhitespace */ - -static int EatComment( myFILE *InFile ) - /* ------------------------------------------------------------------------ ** - * Scan to the end of a comment. - * - * Input: InFile - Input source. - * - * Output: The character that marks the end of the comment. Normally, - * this will be a newline, but it *might* be an EOF. - * - * Notes: Because the config files use a line-oriented grammar, we - * explicitly exclude the newline character from the list of - * whitespace characters. - * - Note that both EOF (-1) and the nul character ('\0') are - * considered end-of-file markers. - * - * ------------------------------------------------------------------------ ** - */ - { - int c; - - for( c = mygetc( InFile ); ('\n'!=c) && (EOF!=c) && (c>0); c = mygetc( InFile ) ) - ; - return( c ); - } /* EatComment */ - -/***************************************************************************** - * Scan backards within a string to discover if the last non-whitespace - * character is a line-continuation character ('\\'). - * - * Input: line - A pointer to a buffer containing the string to be - * scanned. - * pos - This is taken to be the offset of the end of the - * string. This position is *not* scanned. - * - * Output: The offset of the '\\' character if it was found, or -1 to - * indicate that it was not. - * - *****************************************************************************/ - -static int Continuation(char *line, int pos ) -{ - pos--; - while( (pos >= 0) && isspace((int)line[pos])) - pos--; - - return (((pos >= 0) && ('\\' == line[pos])) ? pos : -1 ); -} - - -static bool Section( myFILE *InFile, bool (*sfunc)(const char *, void *), void *userdata ) - /* ------------------------------------------------------------------------ ** - * Scan a section name, and pass the name to function sfunc(). - * - * Input: InFile - Input source. - * sfunc - Pointer to the function to be called if the section - * name is successfully read. - * - * Output: true if the section name was read and true was returned from - * . false if failed or if a lexical error was - * encountered. - * - * ------------------------------------------------------------------------ ** - */ - { - int c; - int i; - int end; - const char *func = "params.c:Section() -"; - - i = 0; /* is the offset of the next free byte in bufr[] and */ - end = 0; /* is the current "end of string" offset. In most */ - /* cases these will be the same, but if the last */ - /* character written to bufr[] is a space, then */ - /* will be one less than . */ - - c = EatWhitespace( InFile ); /* We've already got the '['. Scan */ - /* past initial white space. */ - - while( (EOF != c) && (c > 0) ) - { - - /* Check that the buffer is big enough for the next character. */ - if( i > (InFile->bSize - 2) ) - { - char *tb; - - tb = talloc_realloc(InFile, InFile->bufr, char, InFile->bSize + BUFR_INC); - if( NULL == tb ) - { - DEBUG(0, ("%s Memory re-allocation failure.", func) ); - return( false ); - } - InFile->bufr = tb; - InFile->bSize += BUFR_INC; - } - - /* Handle a single character. */ - switch( c ) - { - case ']': /* Found the closing bracket. */ - InFile->bufr[end] = '\0'; - if( 0 == end ) /* Don't allow an empty name. */ - { - DEBUG(0, ("%s Empty section name in configuration file.\n", func )); - return( false ); - } - if( !sfunc(InFile->bufr,userdata) ) /* Got a valid name. Deal with it. */ - return( false ); - (void)EatComment( InFile ); /* Finish off the line. */ - return( true ); - - case '\n': /* Got newline before closing ']'. */ - i = Continuation( InFile->bufr, i ); /* Check for line continuation. */ - if( i < 0 ) - { - InFile->bufr[end] = '\0'; - DEBUG(0, ("%s Badly formed line in configuration file: %s\n", - func, InFile->bufr )); - return( false ); - } - end = ( (i > 0) && (' ' == InFile->bufr[i - 1]) ) ? (i - 1) : (i); - c = mygetc( InFile ); /* Continue with next line. */ - break; - - default: /* All else are a valid name chars. */ - if( isspace( c ) ) /* One space per whitespace region. */ - { - InFile->bufr[end] = ' '; - i = end + 1; - c = EatWhitespace( InFile ); - } - else /* All others copy verbatim. */ - { - InFile->bufr[i++] = c; - end = i; - c = mygetc( InFile ); - } - } - } - - /* We arrive here if we've met the EOF before the closing bracket. */ - DEBUG(0, ("%s Unexpected EOF in the configuration file\n", func)); - return( false ); - } /* Section */ - -static bool Parameter( myFILE *InFile, bool (*pfunc)(const char *, const char *, void *), int c, void *userdata ) - /* ------------------------------------------------------------------------ ** - * Scan a parameter name and value, and pass these two fields to pfunc(). - * - * Input: InFile - The input source. - * pfunc - A pointer to the function that will be called to - * process the parameter, once it has been scanned. - * c - The first character of the parameter name, which - * would have been read by Parse(). Unlike a comment - * line or a section header, there is no lead-in - * character that can be discarded. - * - * Output: true if the parameter name and value were scanned and processed - * successfully, else false. - * - * Notes: This function is in two parts. The first loop scans the - * parameter name. Internal whitespace is compressed, and an - * equal sign (=) terminates the token. Leading and trailing - * whitespace is discarded. The second loop scans the parameter - * value. When both have been successfully identified, they are - * passed to pfunc() for processing. - * - * ------------------------------------------------------------------------ ** - */ - { - int i = 0; /* Position within bufr. */ - int end = 0; /* bufr[end] is current end-of-string. */ - int vstart = 0; /* Starting position of the parameter value. */ - const char *func = "params.c:Parameter() -"; - - /* Read the parameter name. */ - while( 0 == vstart ) /* Loop until we've found the start of the value. */ - { - - if( i > (InFile->bSize - 2) ) /* Ensure there's space for next char. */ - { - char *tb; - - tb = talloc_realloc(InFile, InFile->bufr, char, InFile->bSize + BUFR_INC ); - if( NULL == tb ) - { - DEBUG(0, ("%s Memory re-allocation failure.", func) ); - return( false ); - } - InFile->bufr = tb; - InFile->bSize += BUFR_INC; - } - - switch( c ) - { - case '=': /* Equal sign marks end of param name. */ - if( 0 == end ) /* Don't allow an empty name. */ - { - DEBUG(0, ("%s Invalid parameter name in config. file.\n", func )); - return( false ); - } - InFile->bufr[end++] = '\0'; /* Mark end of string & advance. */ - i = end; /* New string starts here. */ - vstart = end; /* New string is parameter value. */ - InFile->bufr[i] = '\0'; /* New string is nul, for now. */ - break; - - case '\n': /* Find continuation char, else error. */ - i = Continuation( InFile->bufr, i ); - if( i < 0 ) - { - InFile->bufr[end] = '\0'; - DEBUG(1,("%s Ignoring badly formed line in configuration file: %s\n", - func, InFile->bufr )); - return( true ); - } - end = ( (i > 0) && (' ' == InFile->bufr[i - 1]) ) ? (i - 1) : (i); - c = mygetc( InFile ); /* Read past eoln. */ - break; - - case '\0': /* Shouldn't have EOF within param name. */ - case EOF: - InFile->bufr[i] = '\0'; - DEBUG(1,("%s Unexpected end-of-file at: %s\n", func, InFile->bufr )); - return( true ); - - default: - if( isspace( c ) ) /* One ' ' per whitespace region. */ - { - InFile->bufr[end] = ' '; - i = end + 1; - c = EatWhitespace( InFile ); - } - else /* All others verbatim. */ - { - InFile->bufr[i++] = c; - end = i; - c = mygetc( InFile ); - } - } - } - - /* Now parse the value. */ - c = EatWhitespace( InFile ); /* Again, trim leading whitespace. */ - while( (EOF !=c) && (c > 0) ) - { - - if( i > (InFile->bSize - 2) ) /* Make sure there's enough room. */ - { - char *tb; - - tb = talloc_realloc(InFile, InFile->bufr, char, InFile->bSize + BUFR_INC ); - if( NULL == tb ) - { - DEBUG(0, ("%s Memory re-allocation failure.", func) ); - return( false ); - } - InFile->bufr = tb; - InFile->bSize += BUFR_INC; - } - - switch( c ) - { - case '\r': /* Explicitly remove '\r' because the older */ - c = mygetc( InFile ); /* version called fgets_slash() which also */ - break; /* removes them. */ - - case '\n': /* Marks end of value unless there's a '\'. */ - i = Continuation( InFile->bufr, i ); - if( i < 0 ) - c = 0; - else - { - for( end = i; (end >= 0) && isspace((int)InFile->bufr[end]); end-- ) - ; - c = mygetc( InFile ); - } - break; - - default: /* All others verbatim. Note that spaces do */ - InFile->bufr[i++] = c; /* not advance . This allows trimming */ - if( !isspace( c ) ) /* of whitespace at the end of the line. */ - end = i; - c = mygetc( InFile ); - break; - } - } - InFile->bufr[end] = '\0'; /* End of value. */ - - return( pfunc( InFile->bufr, &InFile->bufr[vstart], userdata ) ); /* Pass name & value to pfunc(). */ - } /* Parameter */ - -static bool Parse( myFILE *InFile, - bool (*sfunc)(const char *, void *), - bool (*pfunc)(const char *, const char *, void *), - void *userdata ) - /* ------------------------------------------------------------------------ ** - * Scan & parse the input. - * - * Input: InFile - Input source. - * sfunc - Function to be called when a section name is scanned. - * See Section(). - * pfunc - Function to be called when a parameter is scanned. - * See Parameter(). - * - * Output: true if the file was successfully scanned, else false. - * - * Notes: The input can be viewed in terms of 'lines'. There are four - * types of lines: - * Blank - May contain whitespace, otherwise empty. - * Comment - First non-whitespace character is a ';' or '#'. - * The remainder of the line is ignored. - * Section - First non-whitespace character is a '['. - * Parameter - The default case. - * - * ------------------------------------------------------------------------ ** - */ - { - int c; - - c = EatWhitespace( InFile ); - while( (EOF != c) && (c > 0) ) - { - switch( c ) - { - case '\n': /* Blank line. */ - c = EatWhitespace( InFile ); - break; - - case ';': /* Comment line. */ - case '#': - c = EatComment( InFile ); - break; - - case '[': /* Section Header. */ - if( !Section( InFile, sfunc, userdata ) ) - return( false ); - c = EatWhitespace( InFile ); - break; - - case '\\': /* Bogus backslash. */ - c = EatWhitespace( InFile ); - break; - - default: /* Parameter line. */ - if( !Parameter( InFile, pfunc, c, userdata ) ) - return( false ); - c = EatWhitespace( InFile ); - break; - } - } - return( true ); - } /* Parse */ - -static myFILE *OpenConfFile( const char *FileName ) - /* ------------------------------------------------------------------------ ** - * Open a configuration file. - * - * Input: FileName - The pathname of the config file to be opened. - * - * Output: A pointer of type (char **) to the lines of the file - * - * ------------------------------------------------------------------------ ** - */ - { - const char *func = "params.c:OpenConfFile() -"; - myFILE *ret; - - ret = talloc(talloc_autofree_context(), myFILE); - if (!ret) return NULL; - - ret->buf = file_load(FileName, &ret->size, ret); - if( NULL == ret->buf ) - { - DEBUG( 1, - ("%s Unable to open configuration file \"%s\":\n\t%s\n", - func, FileName, strerror(errno)) ); - talloc_free(ret); - return NULL; - } - - ret->p = ret->buf; - ret->bufr = NULL; - ret->bSize = 0; - return( ret ); - } /* OpenConfFile */ - -bool pm_process( const char *FileName, - bool (*sfunc)(const char *, void *), - bool (*pfunc)(const char *, const char *, void *), - void *userdata) - /* ------------------------------------------------------------------------ ** - * Process the named parameter file. - * - * Input: FileName - The pathname of the parameter file to be opened. - * sfunc - A pointer to a function that will be called when - * a section name is discovered. - * pfunc - A pointer to a function that will be called when - * a parameter name and value are discovered. - * - * Output: TRUE if the file was successfully parsed, else FALSE. - * - * ------------------------------------------------------------------------ ** - */ - { - int result; - myFILE *InFile; - const char *func = "params.c:pm_process() -"; - - InFile = OpenConfFile( FileName ); /* Open the config file. */ - if( NULL == InFile ) - return( false ); - - DEBUG( 3, ("%s Processing configuration file \"%s\"\n", func, FileName) ); - - if( NULL != InFile->bufr ) /* If we already have a buffer */ - result = Parse( InFile, sfunc, pfunc, userdata ); /* (recursive call), then just */ - /* use it. */ - - else /* If we don't have a buffer */ - { /* allocate one, then parse, */ - InFile->bSize = BUFR_INC; /* then free. */ - InFile->bufr = talloc_array(InFile, char, InFile->bSize ); - if( NULL == InFile->bufr ) - { - DEBUG(0,("%s memory allocation failure.\n", func)); - myfile_close(InFile); - return( false ); - } - result = Parse( InFile, sfunc, pfunc, userdata ); - InFile->bufr = NULL; - InFile->bSize = 0; - } - - myfile_close(InFile); - - if( !result ) /* Generic failure. */ - { - DEBUG(0,("%s Failed. Error returned from params.c:parse().\n", func)); - return( false ); - } - - return( true ); /* Generic success. */ - } /* pm_process */ - -/* -------------------------------------------------------------------------- */ diff --git a/source4/lib/util/safe_string.h b/source4/lib/util/safe_string.h deleted file mode 100644 index a6c052f874..0000000000 --- a/source4/lib/util/safe_string.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Safe string handling routines. - Copyright (C) Andrew Tridgell 1994-1998 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _SAFE_STRING_H -#define _SAFE_STRING_H - -#ifndef _SPLINT_ /* http://www.splint.org */ -/* Some macros to ensure people don't use buffer overflow vulnerable string - functions. */ - -#ifdef strcpy -#undef strcpy -#endif /* strcpy */ -#define strcpy(dest,src) __ERROR__XX__NEVER_USE_STRCPY___; - -#ifdef strcat -#undef strcat -#endif /* strcat */ -#define strcat(dest,src) __ERROR__XX__NEVER_USE_STRCAT___; - -#ifdef sprintf -#undef sprintf -#endif /* sprintf */ -#define sprintf __ERROR__XX__NEVER_USE_SPRINTF__; - -#endif /* !_SPLINT_ */ - -#endif diff --git a/source4/lib/util/signal.c b/source4/lib/util/signal.c deleted file mode 100644 index ead947eb5e..0000000000 --- a/source4/lib/util/signal.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - Unix SMB/CIFS implementation. - signal handling functions - - Copyright (C) Andrew Tridgell 1998 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" -#include "system/wait.h" - -/** - * @file - * @brief Signal handling - */ - -/**************************************************************************** - Catch child exits and reap the child zombie status. -****************************************************************************/ - -static void sig_cld(int signum) -{ - while (waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0) - ; - - /* - * Turns out it's *really* important not to - * restore the signal handler here if we have real POSIX - * signal handling. If we do, then we get the signal re-delivered - * immediately - hey presto - instant loop ! JRA. - */ - -#if !defined(HAVE_SIGACTION) - CatchSignal(SIGCLD, sig_cld); -#endif -} - -/**************************************************************************** -catch child exits - leave status; -****************************************************************************/ - -static void sig_cld_leave_status(int signum) -{ - /* - * Turns out it's *really* important not to - * restore the signal handler here if we have real POSIX - * signal handling. If we do, then we get the signal re-delivered - * immediately - hey presto - instant loop ! JRA. - */ - -#if !defined(HAVE_SIGACTION) - CatchSignal(SIGCLD, sig_cld_leave_status); -#endif -} - -/** - Block sigs. -**/ - -void BlockSignals(bool block, int signum) -{ -#ifdef HAVE_SIGPROCMASK - sigset_t set; - sigemptyset(&set); - sigaddset(&set,signum); - sigprocmask(block?SIG_BLOCK:SIG_UNBLOCK,&set,NULL); -#elif defined(HAVE_SIGBLOCK) - if (block) { - sigblock(sigmask(signum)); - } else { - sigsetmask(siggetmask() & ~sigmask(signum)); - } -#else - /* yikes! This platform can't block signals? */ - static int done; - if (!done) { - DEBUG(0,("WARNING: No signal blocking available\n")); - done=1; - } -#endif -} - -/** - Catch a signal. This should implement the following semantics: - - 1) The handler remains installed after being called. - 2) The signal should be blocked during handler execution. -**/ - -void (*CatchSignal(int signum,void (*handler)(int )))(int) -{ -#ifdef HAVE_SIGACTION - struct sigaction act; - struct sigaction oldact; - - ZERO_STRUCT(act); - - act.sa_handler = handler; -#ifdef SA_RESTART - /* - * We *want* SIGALRM to interrupt a system call. - */ - if(signum != SIGALRM) - act.sa_flags = SA_RESTART; -#endif - sigemptyset(&act.sa_mask); - sigaddset(&act.sa_mask,signum); - sigaction(signum,&act,&oldact); - return oldact.sa_handler; -#else /* !HAVE_SIGACTION */ - /* FIXME: need to handle sigvec and systems with broken signal() */ - return signal(signum, handler); -#endif -} - -/** - Ignore SIGCLD via whatever means is necessary for this OS. -**/ - -void CatchChild(void) -{ - CatchSignal(SIGCLD, sig_cld); -} - -/** - Catch SIGCLD but leave the child around so it's status can be reaped. -**/ - -void CatchChildLeaveStatus(void) -{ - CatchSignal(SIGCLD, sig_cld_leave_status); -} diff --git a/source4/lib/util/signal.m4 b/source4/lib/util/signal.m4 deleted file mode 100644 index c6d7f72f68..0000000000 --- a/source4/lib/util/signal.m4 +++ /dev/null @@ -1 +0,0 @@ -AC_CHECK_FUNCS(sigprocmask sigblock sigaction) diff --git a/source4/lib/util/system.c b/source4/lib/util/system.c deleted file mode 100644 index 9bd1800233..0000000000 --- a/source4/lib/util/system.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Samba system utilities - Copyright (C) Andrew Tridgell 1992-1998 - Copyright (C) Jeremy Allison 1998-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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" -#include "system/network.h" -#include "system/filesys.h" - -/* - The idea is that this file will eventually have wrappers around all - important system calls in samba. The aims are: - - - to enable easier porting by putting OS dependent stuff in here - - - to allow for hooks into other "pseudo-filesystems" - - - to allow easier integration of things like the japanese extensions - - - to support the philosophy of Samba to expose the features of - the OS within the SMB model. In general whatever file/printer/variable - expansions/etc make sense to the OS should be acceptable to Samba. -*/ - -/************************************************************************** -A wrapper for gethostbyname() that tries avoids looking up hostnames -in the root domain, which can cause dial-on-demand links to come up for no -apparent reason. -****************************************************************************/ - -_PUBLIC_ struct hostent *sys_gethostbyname(const char *name) -{ -#ifdef REDUCE_ROOT_DNS_LOOKUPS - char query[256], hostname[256]; - char *domain; - - /* Does this name have any dots in it? If so, make no change */ - - if (strchr(name, '.')) - return(gethostbyname(name)); - - /* Get my hostname, which should have domain name - attached. If not, just do the gethostname on the - original string. - */ - - gethostname(hostname, sizeof(hostname) - 1); - hostname[sizeof(hostname) - 1] = 0; - if ((domain = strchr(hostname, '.')) == NULL) - return(gethostbyname(name)); - - /* Attach domain name to query and do modified query. - If names too large, just do gethostname on the - original string. - */ - - if((strlen(name) + strlen(domain)) >= sizeof(query)) - return(gethostbyname(name)); - - slprintf(query, sizeof(query)-1, "%s%s", name, domain); - return(gethostbyname(query)); -#else /* REDUCE_ROOT_DNS_LOOKUPS */ - return(gethostbyname(name)); -#endif /* REDUCE_ROOT_DNS_LOOKUPS */ -} - -_PUBLIC_ struct in_addr sys_inet_makeaddr(int net, int host) -{ - struct in_addr in; - struct in_addr in2; - in = inet_makeaddr(net, host); - in2.s_addr = in.s_addr; - return in2; -} - diff --git a/source4/lib/util/tests/file.c b/source4/lib/util/tests/file.c deleted file mode 100644 index 3377e833dc..0000000000 --- a/source4/lib/util/tests/file.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - util_file testing - - Copyright (C) Jelmer Vernooij 2005 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" -#include "system/filesys.h" -#include "torture/torture.h" - -#define TEST_FILENAME "utilfile.test" -#define TEST_LINE1 "This is list line 1..." -#define TEST_LINE2 ".. and this is line 2" -#define TEST_LINE3 "and end of the file" - -#define TEST_DATA TEST_LINE1 "\n" TEST_LINE2 "\n" TEST_LINE3 - -static bool test_file_load_save(struct torture_context *tctx) -{ - size_t len; - char *data; - TALLOC_CTX *mem_ctx = tctx; - - torture_assert(tctx, file_save(TEST_FILENAME, TEST_DATA, strlen(TEST_DATA)), - "saving file"); - - torture_assert_file_contains_text(tctx, TEST_FILENAME, TEST_DATA, - "file contents"); - - data = file_load(TEST_FILENAME, &len, mem_ctx); - torture_assert(tctx, data, "loading file"); - - torture_assert_int_equal(tctx, len, strlen(TEST_DATA), "Length"); - - torture_assert_mem_equal(tctx, data, TEST_DATA, len, "Contents"); - - unlink(TEST_FILENAME); - return true; -} - - -static bool test_afdgets(struct torture_context *tctx) -{ - int fd; - char *line; - TALLOC_CTX *mem_ctx = tctx; - - torture_assert(tctx, file_save(TEST_FILENAME, (const void *)TEST_DATA, - strlen(TEST_DATA)), - "saving file"); - - fd = open(TEST_FILENAME, O_RDONLY); - - torture_assert(tctx, fd != -1, "opening file"); - - line = afdgets(fd, mem_ctx, 8); - torture_assert(tctx, strcmp(line, TEST_LINE1) == 0, "line 1 mismatch"); - - line = afdgets(fd, mem_ctx, 8); - torture_assert(tctx, strcmp(line, TEST_LINE2) == 0, "line 2 mismatch"); - - line = afdgets(fd, mem_ctx, 8); - torture_assert(tctx, strcmp(line, TEST_LINE3) == 0, "line 3 mismatch"); - - close(fd); - - unlink(TEST_FILENAME); - return true; -} - -struct torture_suite *torture_local_util_file(TALLOC_CTX *mem_ctx) -{ - struct torture_suite *suite = torture_suite_create(mem_ctx, "FILE"); - - torture_suite_add_simple_test(suite, "file_load_save", - test_file_load_save); - - torture_suite_add_simple_test(suite, "afdgets", - test_afdgets); - - return suite; -} diff --git a/source4/lib/util/tests/genrand.c b/source4/lib/util/tests/genrand.c deleted file mode 100644 index 5fe229c089..0000000000 --- a/source4/lib/util/tests/genrand.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - local testing of random data routines. - - Copyright (C) Jelmer Vernooij - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" -#include "torture/torture.h" - -static void dummy_reseed(void *userdata, int *d) -{ - *d = 42; -} - -static bool test_reseed_callback(struct torture_context *tctx) -{ - set_rand_reseed_callback(dummy_reseed, NULL); - return true; -} - -static bool test_check_password_quality(struct torture_context *tctx) -{ - torture_assert(tctx, !check_password_quality(""), "empty password"); - torture_assert(tctx, !check_password_quality("a"), "one char password"); - torture_assert(tctx, !check_password_quality("aaaaaaaaaaaa"), "same char password"); - torture_assert(tctx, !check_password_quality("BLA"), "multiple upcases password"); - torture_assert(tctx, !check_password_quality("123"), "digits only"); - torture_assert(tctx, check_password_quality("A2e"), "valid"); - torture_assert(tctx, check_password_quality("BA2eLi443"), "valid"); - return true; -} - -static bool test_generate_random_str(struct torture_context *tctx) -{ - TALLOC_CTX *mem_ctx = talloc_init(__FUNCTION__); - char *r = generate_random_str(mem_ctx, 10); - torture_assert_int_equal(tctx, strlen(r), 10, "right length generated"); - r = generate_random_str(mem_ctx, 5); - torture_assert_int_equal(tctx, strlen(r), 5, "right length generated"); - return true; -} - -struct torture_suite *torture_local_genrand(TALLOC_CTX *mem_ctx) -{ - struct torture_suite *suite = torture_suite_create(mem_ctx, "GENRAND"); - torture_suite_add_simple_test(suite, "reseed_callback", test_reseed_callback); - torture_suite_add_simple_test(suite, "check_password_quality", test_check_password_quality); - torture_suite_add_simple_test(suite, "generate_random_str", test_generate_random_str); - return suite; -} diff --git a/source4/lib/util/tests/idtree.c b/source4/lib/util/tests/idtree.c deleted file mode 100644 index d89fb8c489..0000000000 --- a/source4/lib/util/tests/idtree.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - local testing of idtree routines. - - Copyright (C) Andrew Tridgell 2004 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" -#include "torture/torture.h" - -static bool torture_local_idtree_simple(struct torture_context *tctx) -{ - struct idr_context *idr; - int i, ret; - int *ids; - int *present; - extern int torture_numops; - int n = torture_numops; - TALLOC_CTX *mem_ctx = tctx; - - idr = idr_init(mem_ctx); - - ids = talloc_zero_array(mem_ctx, int, n); - present = talloc_zero_array(mem_ctx, int, n); - - for (i=0;i 2007 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" -#include "torture/torture.h" - -static bool test_string_sub_simple(struct torture_context *tctx) -{ - char tmp[100]; - safe_strcpy(tmp, "foobar", sizeof(tmp)); - string_sub(tmp, "foo", "bar", sizeof(tmp)); - torture_assert_str_equal(tctx, tmp, "barbar", "invalid sub"); - return true; -} - -static bool test_string_sub_multiple(struct torture_context *tctx) -{ - char tmp[100]; - safe_strcpy(tmp, "fooblafoo", sizeof(tmp)); - string_sub(tmp, "foo", "bar", sizeof(tmp)); - torture_assert_str_equal(tctx, tmp, "barblabar", "invalid sub"); - return true; -} - -static bool test_string_sub_longer(struct torture_context *tctx) -{ - char tmp[100]; - safe_strcpy(tmp, "foobla", sizeof(tmp)); - string_sub(tmp, "foo", "blie", sizeof(tmp)); - torture_assert_str_equal(tctx, tmp, "bliebla", "invalid sub"); - return true; -} - -static bool test_string_sub_shorter(struct torture_context *tctx) -{ - char tmp[100]; - safe_strcpy(tmp, "foobla", sizeof(tmp)); - string_sub(tmp, "foo", "bl", sizeof(tmp)); - torture_assert_str_equal(tctx, tmp, "blbla", "invalid sub"); - return true; -} - -static bool test_string_sub_special_char(struct torture_context *tctx) -{ - char tmp[100]; - safe_strcpy(tmp, "foobla", sizeof(tmp)); - string_sub(tmp, "foo", "%b;l", sizeof(tmp)); - torture_assert_str_equal(tctx, tmp, "_b_lbla", "invalid sub"); - return true; -} - -static bool test_string_sub_talloc_simple(struct torture_context *tctx) -{ - char *t; - - t = string_sub_talloc(tctx, "foobla", "foo", "bl"); - - torture_assert_str_equal(tctx, t, "blbla", "invalid sub"); - - return true; -} - -static bool test_string_sub_talloc_multiple(struct torture_context *tctx) -{ - char *t; - - t = string_sub_talloc(tctx, "fooblafoo", "foo", "aapnootmies"); - - torture_assert_str_equal(tctx, t, "aapnootmiesblaaapnootmies", - "invalid sub"); - - return true; -} - - - -struct torture_suite *torture_local_util_str(TALLOC_CTX *mem_ctx) -{ - struct torture_suite *suite = torture_suite_create(mem_ctx, "STR"); - - torture_suite_add_simple_test(suite, "string_sub_simple", - test_string_sub_simple); - - torture_suite_add_simple_test(suite, "string_sub_multiple", - test_string_sub_multiple); - - torture_suite_add_simple_test(suite, "string_sub_shorter", - test_string_sub_shorter); - - torture_suite_add_simple_test(suite, "string_sub_longer", - test_string_sub_longer); - - torture_suite_add_simple_test(suite, "string_sub_special_chars", - test_string_sub_special_char); - - torture_suite_add_simple_test(suite, "string_sub_talloc_simple", - test_string_sub_talloc_simple); - - torture_suite_add_simple_test(suite, "string_sub_talloc_multiple", - test_string_sub_talloc_multiple); - - return suite; -} diff --git a/source4/lib/util/tests/strlist.c b/source4/lib/util/tests/strlist.c deleted file mode 100644 index 9af26f9e71..0000000000 --- a/source4/lib/util/tests/strlist.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - util_strlist testing - - Copyright (C) Jelmer Vernooij 2005 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" -#include "torture/torture.h" - -static const char *test_lists_shell_strings[] = { - "", - "foo", - "foo bar", - "foo bar \"bla \"", - "foo \"\" bla", - "bla \"\"\"\" blie", - NULL -}; - -static bool test_lists_shell(struct torture_context *tctx, - const void *test_data) -{ - const char *data = (const char *)test_data; - const char **ret1, **ret2, *tmp; - bool match = true; - TALLOC_CTX *mem_ctx = tctx; - - ret1 = str_list_make_shell(mem_ctx, data, " "); - tmp = str_list_join_shell(mem_ctx, ret1, ' '); - ret2 = str_list_make_shell(mem_ctx, tmp, " "); - - if ((ret1 == NULL || ret2 == NULL) && ret2 != ret1) { - match = false; - } else { - int j; - for (j = 0; ret1[j] && ret2[j]; j++) { - if (strcmp(ret1[j], ret2[j]) != 0) { - match = false; - break; - } - } - - if (ret1[j] || ret2[j]) - match = false; - } - - torture_assert(tctx, match, talloc_asprintf(tctx, - "str_list_{make,join}_shell: Error double parsing, first run:\n%s\nSecond run: \n%s", data, tmp)); - return true; -} - -static bool test_list_copy(struct torture_context *tctx) -{ - const char **result; - const char *list[] = { "foo", "bar", NULL }; - const char *empty_list[] = { NULL }; - const char **null_list = NULL; - - result = str_list_copy(tctx, list); - torture_assert_int_equal(tctx, str_list_length(result), 2, "list length"); - torture_assert_str_equal(tctx, result[0], "foo", "element 0"); - torture_assert_str_equal(tctx, result[1], "bar", "element 1"); - torture_assert_str_equal(tctx, result[2], NULL, "element 2"); - - result = str_list_copy(tctx, empty_list); - torture_assert_int_equal(tctx, str_list_length(result), 0, "list length"); - torture_assert_str_equal(tctx, result[0], NULL, "element 0"); - - result = str_list_copy(tctx, null_list); - torture_assert(tctx, result == NULL, "result NULL"); - - return true; -} - -struct torture_suite *torture_local_util_strlist(TALLOC_CTX *mem_ctx) -{ - struct torture_suite *suite = torture_suite_create(mem_ctx, "STRLIST"); - int i; - - for (i = 0; test_lists_shell_strings[i]; i++) { - torture_suite_add_simple_tcase_const(suite, "lists_shell", - test_lists_shell, &test_lists_shell_strings[i]); - } - - torture_suite_add_simple_test(suite, "list_copy", test_list_copy); - - return suite; -} diff --git a/source4/lib/util/time.c b/source4/lib/util/time.c deleted file mode 100644 index 978d73cc0a..0000000000 --- a/source4/lib/util/time.c +++ /dev/null @@ -1,622 +0,0 @@ -/* - Unix SMB/CIFS implementation. - time handling functions - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" -#include "system/time.h" - -/** - * @file - * @brief time handling functions - */ - -#ifndef TIME_T_MIN -/* we use 0 here, because (time_t)-1 means error */ -#define TIME_T_MIN 0 -#endif - -/* - * we use the INT32_MAX here as on 64 bit systems, - * gmtime() fails with INT64_MAX - */ - -#ifndef TIME_T_MAX -#define TIME_T_MAX MIN(INT32_MAX,_TYPE_MAXIMUM(time_t)) -#endif - -/** - External access to time_t_min and time_t_max. -**/ -_PUBLIC_ time_t get_time_t_max(void) -{ - return TIME_T_MAX; -} - -/** -a gettimeofday wrapper -**/ -_PUBLIC_ void GetTimeOfDay(struct timeval *tval) -{ -#ifdef HAVE_GETTIMEOFDAY_TZ - gettimeofday(tval,NULL); -#else - gettimeofday(tval); -#endif -} - - -#define TIME_FIXUP_CONSTANT 11644473600LL - -/** -interpret an 8 byte "filetime" structure to a time_t -It's originally in "100ns units since jan 1st 1601" -**/ -_PUBLIC_ time_t nt_time_to_unix(NTTIME nt) -{ - if (nt == 0) { - return 0; - } - if (nt == -1LL) { - return (time_t)-1; - } - nt += 1000*1000*10/2; - nt /= 1000*1000*10; - nt -= TIME_FIXUP_CONSTANT; - - if (TIME_T_MIN > nt || nt > TIME_T_MAX) { - return 0; - } - - return (time_t)nt; -} - - -/** -put a 8 byte filetime from a time_t -This takes GMT as input -**/ -_PUBLIC_ void unix_to_nt_time(NTTIME *nt, time_t t) -{ - uint64_t t2; - - if (t == (time_t)-1) { - *nt = (NTTIME)-1LL; - return; - } - if (t == 0) { - *nt = 0; - return; - } - - t2 = t; - t2 += TIME_FIXUP_CONSTANT; - t2 *= 1000*1000*10; - - *nt = t2; -} - - -/** -check if it's a null unix time -**/ -_PUBLIC_ bool null_time(time_t t) -{ - return t == 0 || - t == (time_t)0xFFFFFFFF || - t == (time_t)-1; -} - - -/** -check if it's a null NTTIME -**/ -_PUBLIC_ bool null_nttime(NTTIME t) -{ - return t == 0 || t == (NTTIME)-1; -} - -/******************************************************************* - create a 16 bit dos packed date -********************************************************************/ -static uint16_t make_dos_date1(struct tm *t) -{ - uint16_t ret=0; - ret = (((unsigned int)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1); - ret = ((ret&0xFF)<<8) | (t->tm_mday | (((t->tm_mon+1) & 0x7) << 5)); - return ret; -} - -/******************************************************************* - create a 16 bit dos packed time -********************************************************************/ -static uint16_t make_dos_time1(struct tm *t) -{ - uint16_t ret=0; - ret = ((((unsigned int)t->tm_min >> 3)&0x7) | (((unsigned int)t->tm_hour) << 3)); - ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5)); - return ret; -} - -/******************************************************************* - create a 32 bit dos packed date/time from some parameters - This takes a GMT time and returns a packed localtime structure -********************************************************************/ -static uint32_t make_dos_date(time_t unixdate, int zone_offset) -{ - struct tm *t; - uint32_t ret=0; - - if (unixdate == 0) { - return 0; - } - - unixdate -= zone_offset; - - t = gmtime(&unixdate); - if (!t) { - return 0xFFFFFFFF; - } - - ret = make_dos_date1(t); - ret = ((ret&0xFFFF)<<16) | make_dos_time1(t); - - return ret; -} - -/** -put a dos date into a buffer (time/date format) -This takes GMT time and puts local time in the buffer -**/ -_PUBLIC_ void push_dos_date(uint8_t *buf, int offset, time_t unixdate, int zone_offset) -{ - uint32_t x = make_dos_date(unixdate, zone_offset); - SIVAL(buf,offset,x); -} - -/** -put a dos date into a buffer (date/time format) -This takes GMT time and puts local time in the buffer -**/ -_PUBLIC_ void push_dos_date2(uint8_t *buf,int offset,time_t unixdate, int zone_offset) -{ - uint32_t x; - x = make_dos_date(unixdate, zone_offset); - x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16); - SIVAL(buf,offset,x); -} - -/** -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) -**/ -_PUBLIC_ void push_dos_date3(uint8_t *buf,int offset,time_t unixdate, int zone_offset) -{ - if (!null_time(unixdate)) { - unixdate -= zone_offset; - } - SIVAL(buf,offset,unixdate); -} - -/******************************************************************* - interpret a 32 bit dos packed date/time to some parameters -********************************************************************/ -static void interpret_dos_date(uint32_t date,int *year,int *month,int *day,int *hour,int *minute,int *second) -{ - uint32_t p0,p1,p2,p3; - - 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; -} - -/** - create a unix date (int GMT) from a dos date (which is actually in - localtime) -**/ -_PUBLIC_ time_t pull_dos_date(const uint8_t *date_ptr, int zone_offset) -{ - uint32_t dos_date=0; - struct tm t; - time_t ret; - - dos_date = IVAL(date_ptr,0); - - if (dos_date == 0) return (time_t)0; - - interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon, - &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec); - t.tm_isdst = -1; - - ret = timegm(&t); - - ret += zone_offset; - - return ret; -} - -/** -like make_unix_date() but the words are reversed -**/ -_PUBLIC_ time_t pull_dos_date2(const uint8_t *date_ptr, int zone_offset) -{ - uint32_t x,x2; - - x = IVAL(date_ptr,0); - x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16); - SIVAL(&x,0,x2); - - return pull_dos_date((const uint8_t *)&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 -**/ -_PUBLIC_ time_t pull_dos_date3(const uint8_t *date_ptr, int zone_offset) -{ - time_t t = (time_t)IVAL(date_ptr,0); - if (!null_time(t)) { - t += zone_offset; - } - return t; -} - - -/** -return a HTTP/1.0 time string -**/ -_PUBLIC_ char *http_timestring(TALLOC_CTX *mem_ctx, time_t 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); - } - -#ifndef 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); -#endif /* !HAVE_STRFTIME */ - - return buf; -} - -/** - Return the date and time as a string -**/ -_PUBLIC_ char *timestring(TALLOC_CTX *mem_ctx, time_t t) -{ - char *TimeBuf; - char tempTime[80]; - struct tm *tm; - - tm = localtime(&t); - if (!tm) { - return talloc_asprintf(mem_ctx, - "%ld seconds since the Epoch", - (long)t); - } - -#ifdef HAVE_STRFTIME - /* some versions of gcc complain about using %c. This is a bug - in the gcc warning, not a bug in this code. See a recent - strftime() manual page for details. - */ - strftime(tempTime,sizeof(tempTime)-1,"%c %Z",tm); - TimeBuf = talloc_strdup(mem_ctx, tempTime); -#else - TimeBuf = talloc_strdup(mem_ctx, asctime(tm)); -#endif - - return TimeBuf; -} - -/** - return a talloced string representing a NTTIME for human consumption -*/ -_PUBLIC_ const char *nt_time_string(TALLOC_CTX *mem_ctx, NTTIME nt) -{ - time_t t; - if (nt == 0) { - return "NTTIME(0)"; - } - t = nt_time_to_unix(nt); - return timestring(mem_ctx, t); -} - - -/** - put a NTTIME into a packet -*/ -_PUBLIC_ void push_nttime(uint8_t *base, uint16_t offset, NTTIME t) -{ - SBVAL(base, offset, t); -} - -/** - pull a NTTIME from a packet -*/ -_PUBLIC_ NTTIME pull_nttime(uint8_t *base, uint16_t offset) -{ - NTTIME ret = BVAL(base, offset); - return ret; -} - -/** - return (tv1 - tv2) in microseconds -*/ -_PUBLIC_ int64_t usec_time_diff(const struct timeval *tv1, const struct timeval *tv2) -{ - int64_t sec_diff = tv1->tv_sec - tv2->tv_sec; - return (sec_diff * 1000000) + (int64_t)(tv1->tv_usec - tv2->tv_usec); -} - - -/** - return a zero timeval -*/ -_PUBLIC_ struct timeval timeval_zero(void) -{ - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 0; - return tv; -} - -/** - return true if a timeval is zero -*/ -_PUBLIC_ bool timeval_is_zero(const struct timeval *tv) -{ - return tv->tv_sec == 0 && tv->tv_usec == 0; -} - -/** - return a timeval for the current time -*/ -_PUBLIC_ struct timeval timeval_current(void) -{ - struct timeval tv; - GetTimeOfDay(&tv); - return tv; -} - -/** - return a timeval struct with the given elements -*/ -_PUBLIC_ struct timeval timeval_set(uint32_t secs, uint32_t usecs) -{ - struct timeval tv; - tv.tv_sec = secs; - tv.tv_usec = usecs; - return tv; -} - - -/** - return a timeval ofs microseconds after tv -*/ -_PUBLIC_ struct timeval timeval_add(const struct timeval *tv, - uint32_t secs, uint32_t usecs) -{ - struct timeval tv2 = *tv; - const unsigned int million = 1000000; - tv2.tv_sec += secs; - tv2.tv_usec += usecs; - tv2.tv_sec += tv2.tv_usec / million; - tv2.tv_usec = tv2.tv_usec % million; - return tv2; -} - -/** - return the sum of two timeval structures -*/ -struct timeval timeval_sum(const struct timeval *tv1, - const struct timeval *tv2) -{ - return timeval_add(tv1, tv2->tv_sec, tv2->tv_usec); -} - -/** - return a timeval secs/usecs into the future -*/ -_PUBLIC_ struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs) -{ - struct timeval tv = timeval_current(); - return timeval_add(&tv, secs, usecs); -} - -/** - compare two timeval structures. - Return -1 if tv1 < tv2 - Return 0 if tv1 == tv2 - Return 1 if tv1 > tv2 -*/ -_PUBLIC_ int timeval_compare(const struct timeval *tv1, const struct timeval *tv2) -{ - if (tv1->tv_sec > tv2->tv_sec) return 1; - if (tv1->tv_sec < tv2->tv_sec) return -1; - if (tv1->tv_usec > tv2->tv_usec) return 1; - if (tv1->tv_usec < tv2->tv_usec) return -1; - return 0; -} - -/** - return true if a timer is in the past -*/ -_PUBLIC_ bool timeval_expired(const struct timeval *tv) -{ - struct timeval tv2 = timeval_current(); - if (tv2.tv_sec > tv->tv_sec) return true; - if (tv2.tv_sec < tv->tv_sec) return false; - return (tv2.tv_usec >= tv->tv_usec); -} - -/** - return the number of seconds elapsed between two times -*/ -_PUBLIC_ double timeval_elapsed2(const struct timeval *tv1, const struct timeval *tv2) -{ - return (tv2->tv_sec - tv1->tv_sec) + - (tv2->tv_usec - tv1->tv_usec)*1.0e-6; -} - -/** - return the number of seconds elapsed since a given time -*/ -_PUBLIC_ double timeval_elapsed(const struct timeval *tv) -{ - struct timeval tv2 = timeval_current(); - return timeval_elapsed2(tv, &tv2); -} - -/** - return the lesser of two timevals -*/ -_PUBLIC_ struct timeval timeval_min(const struct timeval *tv1, - const struct timeval *tv2) -{ - if (tv1->tv_sec < tv2->tv_sec) return *tv1; - if (tv1->tv_sec > tv2->tv_sec) return *tv2; - if (tv1->tv_usec < tv2->tv_usec) return *tv1; - return *tv2; -} - -/** - return the greater of two timevals -*/ -_PUBLIC_ struct timeval timeval_max(const struct timeval *tv1, - const struct timeval *tv2) -{ - if (tv1->tv_sec > tv2->tv_sec) return *tv1; - if (tv1->tv_sec < tv2->tv_sec) return *tv2; - if (tv1->tv_usec > tv2->tv_usec) return *tv1; - return *tv2; -} - -/** - return the difference between two timevals as a timeval - if tv1 comes after tv2, then return a zero timeval - (this is *tv2 - *tv1) -*/ -_PUBLIC_ struct timeval timeval_until(const struct timeval *tv1, - const struct timeval *tv2) -{ - struct timeval t; - if (timeval_compare(tv1, tv2) >= 0) { - return timeval_zero(); - } - t.tv_sec = tv2->tv_sec - tv1->tv_sec; - if (tv1->tv_usec > tv2->tv_usec) { - t.tv_sec--; - t.tv_usec = 1000000 - (tv1->tv_usec - tv2->tv_usec); - } else { - t.tv_usec = tv2->tv_usec - tv1->tv_usec; - } - return t; -} - - -/** - convert a timeval to a NTTIME -*/ -_PUBLIC_ NTTIME timeval_to_nttime(const struct timeval *tv) -{ - return 10*(tv->tv_usec + - ((TIME_FIXUP_CONSTANT + (uint64_t)tv->tv_sec) * 1000000)); -} - -/** - convert a NTTIME to a timeval -*/ -_PUBLIC_ void nttime_to_timeval(struct timeval *tv, NTTIME t) -{ - if (tv == NULL) return; - - t += 10/2; - t /= 10; - t -= TIME_FIXUP_CONSTANT*1000*1000; - - tv->tv_sec = t / 1000000; - - if (TIME_T_MIN > tv->tv_sec || tv->tv_sec > TIME_T_MAX) { - tv->tv_sec = 0; - tv->tv_usec = 0; - return; - } - - tv->tv_usec = t - tv->tv_sec*1000000; -} - -/******************************************************************* -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 + (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 - */ -_PUBLIC_ int get_time_zone(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); -} - -/** - check if 2 NTTIMEs are equal. -*/ -bool nt_time_equal(NTTIME *t1, NTTIME *t2) -{ - return *t1 == *t2; -} diff --git a/source4/lib/util/time.h b/source4/lib/util/time.h deleted file mode 100644 index e4008c5782..0000000000 --- a/source4/lib/util/time.h +++ /dev/null @@ -1,232 +0,0 @@ -/* - Unix SMB/CIFS implementation. - time utility functions - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _SAMBA_TIME_H_ -#define _SAMBA_TIME_H_ - -#ifndef _PUBLIC_ -#define _PUBLIC_ -#endif - -/* 64 bit time (100 nanosec) 1601 - cifs6.txt, section 3.5, page 30, 4 byte aligned */ -typedef uint64_t NTTIME; - -/** - External access to time_t_min and time_t_max. -**/ -_PUBLIC_ time_t get_time_t_max(void); - -/** -a gettimeofday wrapper -**/ -_PUBLIC_ void GetTimeOfDay(struct timeval *tval); - -/** -interpret an 8 byte "filetime" structure to a time_t -It's originally in "100ns units since jan 1st 1601" -**/ -_PUBLIC_ time_t nt_time_to_unix(NTTIME nt); - -/** -put a 8 byte filetime from a time_t -This takes GMT as input -**/ -_PUBLIC_ void unix_to_nt_time(NTTIME *nt, time_t t); - -/** -check if it's a null unix time -**/ -_PUBLIC_ bool null_time(time_t t); - -/** -check if it's a null NTTIME -**/ -_PUBLIC_ bool null_nttime(NTTIME t); - -/** -put a dos date into a buffer (time/date format) -This takes GMT time and puts local time in the buffer -**/ -_PUBLIC_ void push_dos_date(uint8_t *buf, int offset, time_t unixdate, int zone_offset); - -/** -put a dos date into a buffer (date/time format) -This takes GMT time and puts local time in the buffer -**/ -_PUBLIC_ void push_dos_date2(uint8_t *buf,int offset,time_t unixdate, int zone_offset); - -/** -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) -**/ -_PUBLIC_ void push_dos_date3(uint8_t *buf,int offset,time_t unixdate, int zone_offset); - -/** - create a unix date (int GMT) from a dos date (which is actually in - localtime) -**/ -_PUBLIC_ time_t pull_dos_date(const uint8_t *date_ptr, int zone_offset); - -/** -like make_unix_date() but the words are reversed -**/ -_PUBLIC_ time_t pull_dos_date2(const uint8_t *date_ptr, int 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 -**/ -_PUBLIC_ time_t pull_dos_date3(const uint8_t *date_ptr, int zone_offset); - -/** -return a HTTP/1.0 time string -**/ -_PUBLIC_ char *http_timestring(TALLOC_CTX *mem_ctx, time_t t); - -/** - Return the date and time as a string -**/ -_PUBLIC_ char *timestring(TALLOC_CTX *mem_ctx, time_t t); - -/** - return a talloced string representing a NTTIME for human consumption -*/ -_PUBLIC_ const char *nt_time_string(TALLOC_CTX *mem_ctx, NTTIME nt); - -/** - put a NTTIME into a packet -*/ -_PUBLIC_ void push_nttime(uint8_t *base, uint16_t offset, NTTIME t); - -/** - pull a NTTIME from a packet -*/ -_PUBLIC_ NTTIME pull_nttime(uint8_t *base, uint16_t offset); - -/** - parse a nttime as a large integer in a string and return a NTTIME -*/ -_PUBLIC_ NTTIME nttime_from_string(const char *s); - -/** - return (tv1 - tv2) in microseconds -*/ -_PUBLIC_ int64_t usec_time_diff(const struct timeval *tv1, const struct timeval *tv2); - -/** - return a zero timeval -*/ -_PUBLIC_ struct timeval timeval_zero(void); - -/** - return true if a timeval is zero -*/ -_PUBLIC_ bool timeval_is_zero(const struct timeval *tv); - -/** - return a timeval for the current time -*/ -_PUBLIC_ struct timeval timeval_current(void); - -/** - return a timeval struct with the given elements -*/ -_PUBLIC_ struct timeval timeval_set(uint32_t secs, uint32_t usecs); - -/** - return a timeval ofs microseconds after tv -*/ -_PUBLIC_ struct timeval timeval_add(const struct timeval *tv, - uint32_t secs, uint32_t usecs); - -/** - return the sum of two timeval structures -*/ -struct timeval timeval_sum(const struct timeval *tv1, - const struct timeval *tv2); - -/** - return a timeval secs/usecs into the future -*/ -_PUBLIC_ struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs); - -/** - compare two timeval structures. - Return -1 if tv1 < tv2 - Return 0 if tv1 == tv2 - Return 1 if tv1 > tv2 -*/ -_PUBLIC_ int timeval_compare(const struct timeval *tv1, const struct timeval *tv2); - -/** - return true if a timer is in the past -*/ -_PUBLIC_ bool timeval_expired(const struct timeval *tv); - -/** - return the number of seconds elapsed between two times -*/ -_PUBLIC_ double timeval_elapsed2(const struct timeval *tv1, const struct timeval *tv2); - -/** - return the number of seconds elapsed since a given time -*/ -_PUBLIC_ double timeval_elapsed(const struct timeval *tv); - -/** - return the lesser of two timevals -*/ -_PUBLIC_ struct timeval timeval_min(const struct timeval *tv1, - const struct timeval *tv2); - -/** - return the greater of two timevals -*/ -_PUBLIC_ struct timeval timeval_max(const struct timeval *tv1, - const struct timeval *tv2); - -/** - return the difference between two timevals as a timeval - if tv1 comes after tv2, then return a zero timeval - (this is *tv2 - *tv1) -*/ -_PUBLIC_ struct timeval timeval_until(const struct timeval *tv1, - const struct timeval *tv2); - -/** - convert a timeval to a NTTIME -*/ -_PUBLIC_ NTTIME timeval_to_nttime(const struct timeval *tv); - -/** - convert a NTTIME to a timeval -*/ -_PUBLIC_ void nttime_to_timeval(struct timeval *tv, NTTIME t); - -/** - return the UTC offset in seconds west of UTC, or 0 if it cannot be determined - */ -_PUBLIC_ int get_time_zone(time_t t); - -/** - check if 2 NTTIMEs are equal. -*/ -bool nt_time_equal(NTTIME *t1, NTTIME *t2); - -#endif /* _SAMBA_TIME_H_ */ diff --git a/source4/lib/util/time.m4 b/source4/lib/util/time.m4 deleted file mode 100644 index f61ae4cd25..0000000000 --- a/source4/lib/util/time.m4 +++ /dev/null @@ -1,9 +0,0 @@ -AC_CACHE_CHECK([if gettimeofday takes tz argument],samba_cv_HAVE_GETTIMEOFDAY_TZ,[ -AC_TRY_RUN([ -#include -#include -main() { struct timeval tv; exit(gettimeofday(&tv, NULL));}], - samba_cv_HAVE_GETTIMEOFDAY_TZ=yes,samba_cv_HAVE_GETTIMEOFDAY_TZ=no,samba_cv_HAVE_GETTIMEOFDAY_TZ=cross)]) -if test x"$samba_cv_HAVE_GETTIMEOFDAY_TZ" = x"yes"; then - AC_DEFINE(HAVE_GETTIMEOFDAY_TZ,1,[Whether gettimeofday() is available]) -fi diff --git a/source4/lib/util/unix_privs.c b/source4/lib/util/unix_privs.c deleted file mode 100644 index 47c172dcfa..0000000000 --- a/source4/lib/util/unix_privs.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - gain/lose root privileges - - Copyright (C) Andrew Tridgell 2004 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" -#include "system/filesys.h" - -/** - * @file - * @brief Gaining/losing root privileges - */ - -/* - there are times when smbd needs to temporarily gain root privileges - to do some operation. To do this you call root_privileges(), which - returns a talloc handle. To restore your previous privileges - talloc_free() this pointer. - - Note that this call is considered successful even if it does not - manage to gain root privileges, but it will call smb_abort() if it - fails to restore the privileges afterwards. The logic is that - failing to gain root access can be caught by whatever operation - needs to be run as root failing, but failing to lose the root - privileges is dangerous. - - This also means that this code is safe to be called from completely - unprivileged processes. -*/ - -struct saved_state { - uid_t uid; -}; - -static int privileges_destructor(struct saved_state *s) -{ - if (geteuid() != s->uid && - seteuid(s->uid) != 0) { - smb_panic("Failed to restore privileges"); - } - return 0; -} - -/** - * Obtain root privileges for the current process. - * - * The privileges can be dropped by talloc_free()-ing the - * token returned by this function - */ -void *root_privileges(void) -{ - struct saved_state *s; - s = talloc(NULL, struct saved_state); - if (!s) return NULL; - s->uid = geteuid(); - if (s->uid != 0) { - seteuid(0); - } - talloc_set_destructor(s, privileges_destructor); - return s; -} diff --git a/source4/lib/util/util.c b/source4/lib/util/util.c deleted file mode 100644 index 5fc785d642..0000000000 --- a/source4/lib/util/util.c +++ /dev/null @@ -1,608 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Samba utility functions - Copyright (C) Andrew Tridgell 1992-1998 - Copyright (C) Jeremy Allison 2001-2002 - Copyright (C) Simo Sorce 2001 - Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003. - Copyright (C) James J Myers 2003 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" -#include "system/network.h" -#include "system/filesys.h" -#include "system/locale.h" - -/** - * @file - * @brief Misc utility functions - */ - -/** - Find a suitable temporary directory. The result should be copied immediately - as it may be overwritten by a subsequent call. -**/ -_PUBLIC_ const char *tmpdir(void) -{ - char *p; - if ((p = getenv("TMPDIR"))) - return p; - return "/tmp"; -} - - -/** - Check if a file exists - call vfs_file_exist for samba files. -**/ -_PUBLIC_ bool file_exist(const char *fname) -{ - struct stat st; - - if (stat(fname, &st) != 0) { - return false; - } - - return ((S_ISREG(st.st_mode)) || (S_ISFIFO(st.st_mode))); -} - -/** - Check a files mod time. -**/ - -_PUBLIC_ time_t file_modtime(const char *fname) -{ - struct stat st; - - if (stat(fname,&st) != 0) - return(0); - - return(st.st_mtime); -} - -/** - Check if a directory exists. -**/ - -_PUBLIC_ bool directory_exist(const char *dname) -{ - struct stat st; - bool ret; - - if (stat(dname,&st) != 0) { - return false; - } - - ret = S_ISDIR(st.st_mode); - if(!ret) - errno = ENOTDIR; - return ret; -} - -/** - * Try to create the specified directory if it didn't exist. - * - * @retval true if the directory already existed and has the right permissions - * or was successfully created. - */ -_PUBLIC_ bool directory_create_or_exist(const char *dname, uid_t uid, - mode_t dir_perms) -{ - mode_t old_umask; - struct stat st; - - old_umask = umask(0); - if (lstat(dname, &st) == -1) { - if (errno == ENOENT) { - /* Create directory */ - if (mkdir(dname, dir_perms) == -1) { - DEBUG(0, ("error creating directory " - "%s: %s\n", dname, - strerror(errno))); - umask(old_umask); - return false; - } - } else { - DEBUG(0, ("lstat failed on directory %s: %s\n", - dname, strerror(errno))); - umask(old_umask); - return false; - } - } else { - /* Check ownership and permission on existing directory */ - if (!S_ISDIR(st.st_mode)) { - DEBUG(0, ("directory %s isn't a directory\n", - dname)); - umask(old_umask); - return false; - } - if ((st.st_uid != uid) || - ((st.st_mode & 0777) != dir_perms)) { - DEBUG(0, ("invalid permissions on directory " - "%s\n", dname)); - umask(old_umask); - return false; - } - } - return true; -} - - -/** - Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available, - else - if SYSV use O_NDELAY - if BSD use FNDELAY -**/ - -_PUBLIC_ int set_blocking(int fd, bool set) -{ - int val; -#ifdef O_NONBLOCK -#define FLAG_TO_SET O_NONBLOCK -#else -#ifdef SYSV -#define FLAG_TO_SET O_NDELAY -#else /* BSD */ -#define FLAG_TO_SET FNDELAY -#endif -#endif - - if((val = fcntl(fd, F_GETFL, 0)) == -1) - return -1; - if(set) /* Turn blocking on - ie. clear nonblock flag */ - val &= ~FLAG_TO_SET; - else - val |= FLAG_TO_SET; - return fcntl( fd, F_SETFL, val); -#undef FLAG_TO_SET -} - - -/** - Sleep for a specified number of milliseconds. -**/ - -_PUBLIC_ void msleep(unsigned int t) -{ - struct timeval tval; - - tval.tv_sec = t/1000; - tval.tv_usec = 1000*(t%1000); - /* this should be the real select - do NOT replace - with sys_select() */ - select(0,NULL,NULL,NULL,&tval); -} - -/** - Get my own name, return in malloc'ed storage. -**/ - -_PUBLIC_ char *get_myname(void) -{ - char *hostname; - char *p; - - hostname = (char *)malloc(MAXHOSTNAMELEN+1); - *hostname = 0; - - /* get my host name */ - if (gethostname(hostname, MAXHOSTNAMELEN+1) == -1) { - DEBUG(0,("gethostname failed\n")); - return NULL; - } - - /* Ensure null termination. */ - hostname[MAXHOSTNAMELEN] = '\0'; - - /* split off any parts after an initial . */ - p = strchr(hostname, '.'); - - if (p != NULL) - *p = 0; - - return hostname; -} - -/** - Return true if a string could be a pure IP address. -**/ - -_PUBLIC_ bool is_ipaddress(const char *str) -{ - bool pure_address = true; - int i; - - if (str == NULL) return false; - - for (i=0; pure_address && str[i]; i++) - if (!(isdigit((int)str[i]) || str[i] == '.')) - pure_address = false; - - /* Check that a pure number is not misinterpreted as an IP */ - pure_address = pure_address && (strchr(str, '.') != NULL); - - return pure_address; -} - -/** - Interpret an internet address or name into an IP address in 4 byte form. -**/ -_PUBLIC_ uint32_t interpret_addr(const char *str) -{ - struct hostent *hp; - uint32_t res; - - if (str == NULL || *str == 0 || - strcmp(str,"0.0.0.0") == 0) { - return 0; - } - if (strcmp(str,"255.255.255.255") == 0) { - return 0xFFFFFFFF; - } - /* recognise 'localhost' as a special name. This fixes problems with - some hosts that don't have localhost in /etc/hosts */ - if (strcasecmp(str,"localhost") == 0) { - str = "127.0.0.1"; - } - - /* if it's in the form of an IP address then get the lib to interpret it */ - if (is_ipaddress(str)) { - res = inet_addr(str); - } else { - /* otherwise assume it's a network name of some sort and use - sys_gethostbyname */ - if ((hp = sys_gethostbyname(str)) == 0) { - DEBUG(3,("sys_gethostbyname: Unknown host. %s\n",str)); - return 0; - } - - if(hp->h_addr == NULL) { - DEBUG(3,("sys_gethostbyname: host address is invalid for host %s\n",str)); - return 0; - } - memcpy((char *)&res,(char *)hp->h_addr, 4); - } - - if (res == (uint32_t)-1) - return(0); - - return(res); -} - -/** - A convenient addition to interpret_addr(). -**/ -_PUBLIC_ struct in_addr interpret_addr2(const char *str) -{ - struct in_addr ret; - uint32_t a = interpret_addr(str); - ret.s_addr = a; - return ret; -} - -/** - Check if an IP is the 0.0.0.0. -**/ - -_PUBLIC_ bool is_zero_ip(struct in_addr ip) -{ - return ip.s_addr == 0; -} - -/** - Are two IPs on the same subnet? -**/ - -_PUBLIC_ bool same_net(struct in_addr ip1, struct in_addr ip2, struct in_addr mask) -{ - uint32_t net1,net2,nmask; - - nmask = ntohl(mask.s_addr); - net1 = ntohl(ip1.s_addr); - net2 = ntohl(ip2.s_addr); - - return((net1 & nmask) == (net2 & nmask)); -} - - -/** - Check if a process exists. Does this work on all unixes? -**/ - -_PUBLIC_ bool process_exists(pid_t pid) -{ - /* Doing kill with a non-positive pid causes messages to be - * sent to places we don't want. */ - SMB_ASSERT(pid > 0); - return(kill(pid,0) == 0 || errno != ESRCH); -} - -/** - Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping - is dealt with in posix.c -**/ - -_PUBLIC_ bool fcntl_lock(int fd, int op, off_t offset, off_t count, int type) -{ - struct flock lock; - int ret; - - DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type)); - - lock.l_type = type; - lock.l_whence = SEEK_SET; - lock.l_start = offset; - lock.l_len = count; - lock.l_pid = 0; - - ret = fcntl(fd,op,&lock); - - if (ret == -1 && errno != 0) - DEBUG(3,("fcntl_lock: fcntl lock gave errno %d (%s)\n",errno,strerror(errno))); - - /* a lock query */ - if (op == F_GETLK) { - if ((ret != -1) && - (lock.l_type != F_UNLCK) && - (lock.l_pid != 0) && - (lock.l_pid != getpid())) { - DEBUG(3,("fcntl_lock: fd %d is locked by pid %d\n",fd,(int)lock.l_pid)); - return true; - } - - /* it must be not locked or locked by me */ - return false; - } - - /* a lock set or unset */ - if (ret == -1) { - DEBUG(3,("fcntl_lock: lock failed at offset %.0f count %.0f op %d type %d (%s)\n", - (double)offset,(double)count,op,type,strerror(errno))); - return false; - } - - /* everything went OK */ - DEBUG(8,("fcntl_lock: Lock call successful\n")); - - return true; -} - - -static void print_asc(int level, const uint8_t *buf,int len) -{ - int i; - for (i=0;i 0) && - (len > i+16) && - (memcmp(&buf[i], &empty, 16) == 0)) - { - i +=16; - continue; - } - - if (i i+16) && - (memcmp(&buf[i], &empty, 16) == 0)) { - if (!skipped) { - DEBUGADD(level,("skipping zero buffer bytes\n")); - skipped = true; - } - } - } - } - - if (i%16) { - int n; - n = 16 - (i%16); - DEBUGADD(level,(" ")); - if (n>8) DEBUGADD(level,(" ")); - while (n--) DEBUGADD(level,(" ")); - n = MIN(8,i%16); - print_asc(level,&buf[i-(i%16)],n); DEBUGADD(level,( " " )); - n = (i%16) - n; - if (n>0) print_asc(level,&buf[i-n],n); - DEBUGADD(level,("\n")); - } - -} - -/** - * Write dump of binary data to the log file. - * - * The data is only written if the log level is at least level. - */ -_PUBLIC_ void dump_data(int level, const uint8_t *buf, int len) -{ - _dump_data(level, buf, len, false); -} - -/** - * Write dump of binary data to the log file. - * - * The data is only written if the log level is at least level. - * 16 zero bytes in a row are ommited - */ -_PUBLIC_ void dump_data_skip_zeros(int level, const uint8_t *buf, int len) -{ - _dump_data(level, buf, len, true); -} - - -/** - malloc that aborts with smb_panic on fail or zero size. -**/ - -_PUBLIC_ void *smb_xmalloc(size_t size) -{ - void *p; - if (size == 0) - smb_panic("smb_xmalloc: called with zero size.\n"); - if ((p = malloc(size)) == NULL) - smb_panic("smb_xmalloc: malloc fail.\n"); - return p; -} - -/** - Memdup with smb_panic on fail. -**/ - -_PUBLIC_ void *smb_xmemdup(const void *p, size_t size) -{ - void *p2; - p2 = smb_xmalloc(size); - memcpy(p2, p, size); - return p2; -} - -/** - strdup that aborts on malloc fail. -**/ - -_PUBLIC_ char *smb_xstrdup(const char *s) -{ - char *s1 = strdup(s); - if (!s1) - smb_panic("smb_xstrdup: malloc fail\n"); - return s1; -} - - -/** - Like strdup but for memory. -**/ - -_PUBLIC_ void *memdup(const void *p, size_t size) -{ - void *p2; - if (size == 0) - return NULL; - p2 = malloc(size); - if (!p2) - return NULL; - memcpy(p2, p, size); - return p2; -} - -/** - * Write a password to the log file. - * - * @note Only actually does something if DEBUG_PASSWORD was defined during - * compile-time. - */ -_PUBLIC_ void dump_data_pw(const char *msg, const uint8_t * data, size_t len) -{ -#ifdef DEBUG_PASSWORD - DEBUG(11, ("%s", msg)); - if (data != NULL && len > 0) - { - dump_data(11, data, len); - } -#endif -} - - -/** - * see if a range of memory is all zero. A NULL pointer is considered - * to be all zero - */ -_PUBLIC_ bool all_zero(const uint8_t *ptr, size_t size) -{ - int i; - if (!ptr) return true; - for (i=0;i= MAX_MALLOC_SIZE/el_size) { - return NULL; - } - if (!ptr) { - return malloc(el_size * count); - } - return realloc(ptr, el_size * count); -} - -/**************************************************************************** - Type-safe malloc. -****************************************************************************/ - -void *malloc_array(size_t el_size, unsigned int count) -{ - return realloc_array(NULL, el_size, count); -} - -_PUBLIC_ void *talloc_check_name_abort(const void *ptr, const char *name) -{ - void *result; - - result = talloc_check_name(ptr, name); - if (result != NULL) - return result; - - DEBUG(0, ("Talloc type mismatch, expected %s, got %s\n", - name, talloc_get_name(ptr))); - smb_panic("talloc type mismatch"); - /* Keep the compiler happy */ - return NULL; -} - diff --git a/source4/lib/util/util.h b/source4/lib/util/util.h deleted file mode 100644 index ffe83c14b2..0000000000 --- a/source4/lib/util/util.h +++ /dev/null @@ -1,813 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Utility functions for Samba - Copyright (C) Andrew Tridgell 1992-1999 - Copyright (C) Jelmer Vernooij 2005 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _SAMBA_UTIL_H_ -#define _SAMBA_UTIL_H_ - -#include "util/attr.h" - -#include "charset/charset.h" - -/* for TALLOC_CTX */ -#include - -/** - * @file - * @brief Helpful macros - */ - -struct smbsrv_tcon; - -extern const char *logfile; -extern const char *panic_action; - -#include "util/time.h" -#include "util/data_blob.h" -#include "util/xfile.h" -#include "util/debug.h" -#include "util/mutex.h" -#include "util/byteorder.h" - -/** - this is a warning hack. The idea is to use this everywhere that we - get the "discarding const" warning from gcc. That doesn't actually - fix the problem of course, but it means that when we do get to - cleaning them up we can do it by searching the code for - discard_const. - - It also means that other error types aren't as swamped by the noise - of hundreds of const warnings, so we are more likely to notice when - we get new errors. - - Please only add more uses of this macro when you find it - _really_ hard to fix const warnings. Our aim is to eventually use - this function in only a very few places. - - Also, please call this via the discard_const_p() macro interface, as that - makes the return type safe. -*/ -#ifndef discard_const -#define discard_const(ptr) ((void *)((uintptr_t)(ptr))) -#endif - -/** Type-safe version of discard_const */ -#ifndef discard_const_p -#define discard_const_p(type, ptr) ((type *)discard_const(ptr)) -#endif - -/** - * assert macros - */ -#define SMB_ASSERT(b) do { if (!(b)) { \ - DEBUG(0,("PANIC: assert failed at %s(%d)\n", __FILE__, __LINE__)); \ - smb_panic("assert failed"); }} while (0) - -#ifndef SAFE_FREE /* Oh no this is also defined in tdb.h */ -/** - * Free memory if the pointer and zero the pointer. - * - * @note You are explicitly allowed to pass NULL pointers -- they will - * always be ignored. - **/ -#define SAFE_FREE(x) do { if ((x) != NULL) {free(discard_const_p(void *, (x))); (x)=NULL;} } while(0) -#endif - -/** - * Type-safe version of malloc. Allocated one copy of the - * specified data type. - */ -#define malloc_p(type) (type *)malloc(sizeof(type)) - -/** - * Allocate an array of elements of one data type. Does type-checking. - */ -#define malloc_array_p(type, count) (type *)realloc_array(NULL, sizeof(type), count) - -/** - * Resize an array of elements of one data type. Does type-checking. - */ -#define realloc_p(p, type, count) (type *)realloc_array(p, sizeof(type), count) - -#if defined(VALGRIND) -#define strlen(x) valgrind_strlen(x) -#endif - -/** - * zero a structure - */ -#ifndef ZERO_STRUCT -#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x)) -#endif - -/** - * zero a structure given a pointer to the structure - */ -#ifndef ZERO_STRUCTP -#define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0) -#endif - -/** - * zero a structure given a pointer to the structure - no zero check - */ -#ifndef ZERO_STRUCTPN -#define ZERO_STRUCTPN(x) memset((char *)(x), 0, sizeof(*(x))) -#endif - -/* zero an array - note that sizeof(array) must work - ie. it must not be a - pointer */ -#ifndef ZERO_ARRAY -#define ZERO_ARRAY(x) memset((char *)(x), 0, sizeof(x)) -#endif - -/** - * work out how many elements there are in a static array - */ -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) -#endif - -/** - * pointer difference macro - */ -#ifndef PTR_DIFF -#define PTR_DIFF(p1,p2) ((ptrdiff_t)(((const char *)(p1)) - (const char *)(p2))) -#endif - -/* The following definitions come from lib/util/fault.c */ - - -/** - * Write backtrace to debug log - */ -_PUBLIC_ void call_backtrace(void); - -/** - Something really nasty happened - panic ! -**/ -_PUBLIC_ _NORETURN_ void smb_panic(const char *why); - -/** -setup our fault handlers -**/ -_PUBLIC_ void fault_setup(const char *pname); - -/** - register a fault handler. - Should only be called once in the execution of smbd. -*/ -_PUBLIC_ bool register_fault_handler(const char *name, void (*fault_handler)(int sig)); - -/* The following definitions come from lib/util/signal.c */ - - -/** - Block sigs. -**/ -void BlockSignals(bool block, int signum); - -/** - Catch a signal. This should implement the following semantics: - - 1) The handler remains installed after being called. - 2) The signal should be blocked during handler execution. -**/ -void (*CatchSignal(int signum,void (*handler)(int )))(int); - -/** - Ignore SIGCLD via whatever means is necessary for this OS. -**/ -void CatchChild(void); - -/** - Catch SIGCLD but leave the child around so it's status can be reaped. -**/ -void CatchChildLeaveStatus(void); - -/* The following definitions come from lib/util/system.c */ - - -struct in_addr; - -/************************************************************************** -A wrapper for gethostbyname() that tries avoids looking up hostnames -in the root domain, which can cause dial-on-demand links to come up for no -apparent reason. -****************************************************************************/ -_PUBLIC_ struct hostent *sys_gethostbyname(const char *name); -_PUBLIC_ struct in_addr sys_inet_makeaddr(int net, int host); - -/* The following definitions come from lib/util/genrand.c */ - -/** - Copy any user given reseed data. -**/ -_PUBLIC_ void set_rand_reseed_callback(void (*fn)(void *, int *), void *); - -/** - * Tell the random number generator it needs to reseed. - */ -_PUBLIC_ void set_need_random_reseed(void); - -/** - Interface to the (hopefully) good crypto random number generator. - Will use our internal PRNG if more than 40 bytes of random generation - has been requested, otherwise tries to read from /dev/random -**/ -_PUBLIC_ void generate_random_buffer(uint8_t *out, int len); - -/** - Interface to the (hopefully) good crypto random number generator. - Will always use /dev/urandom if available. -**/ -_PUBLIC_ void generate_secret_buffer(uint8_t *out, int len); - -/** - generate a single random uint32_t -**/ -_PUBLIC_ uint32_t generate_random(void); - -/** - very basic password quality checker -**/ -_PUBLIC_ bool check_password_quality(const char *s); - -/** - Use the random number generator to generate a random string. -**/ -_PUBLIC_ char *generate_random_str_list(TALLOC_CTX *mem_ctx, size_t len, const char *list); - -/** - * Generate a random text string consisting of the specified length. - * The returned string will be allocated. - * - * Characters used are: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#., - */ -_PUBLIC_ char *generate_random_str(TALLOC_CTX *mem_ctx, size_t len); - -/* The following definitions come from lib/util/dprintf.c */ - -_PUBLIC_ void d_set_iconv(smb_iconv_t); -_PUBLIC_ int d_vfprintf(FILE *f, const char *format, va_list ap) PRINTF_ATTRIBUTE(2,0); -_PUBLIC_ int d_fprintf(FILE *f, const char *format, ...) PRINTF_ATTRIBUTE(2,3); -_PUBLIC_ int d_printf(const char *format, ...) PRINTF_ATTRIBUTE(1,2); -_PUBLIC_ void display_set_stderr(void); - -/* The following definitions come from lib/util/util_str.c */ - - -/** - Trim the specified elements off the front and back of a string. -**/ -_PUBLIC_ bool trim_string(char *s, const char *front, const char *back); - -/** - Find the number of 'c' chars in a string -**/ -_PUBLIC_ _PURE_ size_t count_chars(const char *s, char c); - -/** - Safe string copy into a known length string. maxlength does not - include the terminating zero. -**/ -_PUBLIC_ char *safe_strcpy(char *dest,const char *src, size_t maxlength); - -/** - Safe string cat into a string. maxlength does not - include the terminating zero. -**/ -_PUBLIC_ char *safe_strcat(char *dest, const char *src, size_t maxlength); - -/** - Routine to get hex characters and turn them into a 16 byte array. - the array can be variable length, and any non-hex-numeric - characters are skipped. "0xnn" or "0Xnn" is specially catered - for. - - valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n" - - -**/ -_PUBLIC_ size_t strhex_to_str(char *p, size_t len, const char *strhex); - -/** - * Parse a hex string and return a data blob. - */ -_PUBLIC_ _PURE_ DATA_BLOB strhex_to_data_blob(const char *strhex) ; - -/** - * Routine to print a buffer as HEX digits, into an allocated string. - */ -_PUBLIC_ void hex_encode(const unsigned char *buff_in, size_t len, char **out_hex_buffer); - -/** - * talloc version of hex_encode() - */ -_PUBLIC_ char *hex_encode_talloc(TALLOC_CTX *mem_ctx, const unsigned char *buff_in, size_t len); - -/** - Substitute a string for a pattern in another string. Make sure there is - enough room! - - This routine looks for pattern in s and replaces it with - insert. It may do multiple replacements. - - Any of " ; ' $ or ` in the insert string are replaced with _ - if len==0 then the string cannot be extended. This is different from the old - use of len==0 which was for no length checks to be done. -**/ -_PUBLIC_ void string_sub(char *s,const char *pattern, const char *insert, size_t len); - - -_PUBLIC_ char *string_sub_talloc(TALLOC_CTX *mem_ctx, const char *s, - const char *pattern, const char *insert); - -/** - Similar to string_sub() but allows for any character to be substituted. - Use with caution! - if len==0 then the string cannot be extended. This is different from the old - use of len==0 which was for no length checks to be done. -**/ -_PUBLIC_ void all_string_sub(char *s,const char *pattern,const char *insert, size_t len); - -/** - Unescape a URL encoded string, in place. -**/ -_PUBLIC_ void rfc1738_unescape(char *buf); -size_t valgrind_strlen(const char *s); - -/** - format a string into length-prefixed dotted domain format, as used in NBT - and in some ADS structures -**/ -_PUBLIC_ const char *str_format_nbt_domain(TALLOC_CTX *mem_ctx, const char *s); - -/** - * Add a string to an array of strings. - * - * num should be a pointer to an integer that holds the current - * number of elements in strings. It will be updated by this function. - */ -_PUBLIC_ bool add_string_to_array(TALLOC_CTX *mem_ctx, - const char *str, const char ***strings, int *num); - -/** - varient of strcmp() that handles NULL ptrs -**/ -_PUBLIC_ int strcmp_safe(const char *s1, const char *s2); - -/** -return the number of bytes occupied by a buffer in ASCII format -the result includes the null termination -limited by 'n' bytes -**/ -_PUBLIC_ size_t ascii_len_n(const char *src, size_t n); - -/** - Return a string representing a CIFS attribute for a file. -**/ -_PUBLIC_ char *attrib_string(TALLOC_CTX *mem_ctx, uint32_t attrib); - -/** - Set a boolean variable from the text value stored in the passed string. - Returns true in success, false if the passed string does not correctly - represent a boolean. -**/ -_PUBLIC_ bool set_boolean(const char *boolean_string, bool *boolean); - -/** - * Parse a string containing a boolean value. - * - * val will be set to the read value. - * - * @retval true if a boolean value was parsed, false otherwise. - */ -_PUBLIC_ bool conv_str_bool(const char * str, bool * val); - -/** - * Convert a size specification like 16K into an integral number of bytes. - **/ -_PUBLIC_ bool conv_str_size(const char * str, uint64_t * val); - -/** - * Parse a uint64_t value from a string - * - * val will be set to the value read. - * - * @retval true if parsing was successful, false otherwise - */ -_PUBLIC_ bool conv_str_u64(const char * str, uint64_t * val); - -/** -return the number of bytes occupied by a buffer in CH_UTF16 format -the result includes the null termination -**/ -_PUBLIC_ size_t utf16_len(const void *buf); - -/** -return the number of bytes occupied by a buffer in CH_UTF16 format -the result includes the null termination -limited by 'n' bytes -**/ -_PUBLIC_ size_t utf16_len_n(const void *src, size_t n); -_PUBLIC_ size_t ucs2_align(const void *base_ptr, const void *p, int flags); - -/** -Do a case-insensitive, whitespace-ignoring string compare. -**/ -_PUBLIC_ int strwicmp(const char *psz1, const char *psz2); - -/** - String replace. -**/ -_PUBLIC_ void string_replace(char *s, char oldc, char newc); - -/** - * Compare 2 strings. - * - * @note The comparison is case-insensitive. - **/ -_PUBLIC_ bool strequal(const char *s1, const char *s2); - -/* The following definitions come from lib/util/util_strlist.c */ - - -/** - build a null terminated list of strings from a input string and a - separator list. The separator list must contain characters less than - or equal to 0x2f for this to work correctly on multi-byte strings -*/ -_PUBLIC_ const char **str_list_make(TALLOC_CTX *mem_ctx, const char *string, const char *sep); - -/** - * build a null terminated list of strings from an argv-like input string - * Entries are seperated by spaces and can be enclosed by quotes. - * Does NOT support escaping - */ -_PUBLIC_ const char **str_list_make_shell(TALLOC_CTX *mem_ctx, const char *string, const char *sep); - -/** - * join a list back to one string - */ -_PUBLIC_ char *str_list_join(TALLOC_CTX *mem_ctx, const char **list, char seperator); - -/** join a list back to one (shell-like) string; entries - * seperated by spaces, using quotes where necessary */ -_PUBLIC_ char *str_list_join_shell(TALLOC_CTX *mem_ctx, const char **list, char sep); - -/** - return the number of elements in a string list -*/ -_PUBLIC_ size_t str_list_length(const char **list); - -/** - copy a string list -*/ -_PUBLIC_ const char **str_list_copy(TALLOC_CTX *mem_ctx, const char **list); - -/** - Return true if all the elements of the list match exactly. - */ -_PUBLIC_ bool str_list_equal(const char **list1, const char **list2); - -/** - add an entry to a string list -*/ -_PUBLIC_ const char **str_list_add(const char **list, const char *s); - -/** - remove an entry from a string list -*/ -_PUBLIC_ void str_list_remove(const char **list, const char *s); - -/** - return true if a string is in a list -*/ -_PUBLIC_ bool str_list_check(const char **list, const char *s); - -/** - return true if a string is in a list, case insensitively -*/ -_PUBLIC_ bool str_list_check_ci(const char **list, const char *s); - -/* The following definitions come from lib/util/util_file.c */ - - -/** -read a line from a file with possible \ continuation chars. -Blanks at the start or end of a line are stripped. -The string will be allocated if s2 is NULL -**/ -_PUBLIC_ char *fgets_slash(char *s2,int maxlen,XFILE *f); - -/** - * Read one line (data until next newline or eof) and allocate it - */ -_PUBLIC_ char *afdgets(int fd, TALLOC_CTX *mem_ctx, size_t hint); - -/** -load a file into memory from a fd. -**/ -_PUBLIC_ char *fd_load(int fd, size_t *size, TALLOC_CTX *mem_ctx); - -/** -load a file into memory -**/ -_PUBLIC_ char *file_load(const char *fname, size_t *size, TALLOC_CTX *mem_ctx); - -/** -mmap (if possible) or read a file -**/ -_PUBLIC_ void *map_file(const char *fname, size_t size); - -/** -load a file into memory and return an array of pointers to lines in the file -must be freed with talloc_free(). -**/ -_PUBLIC_ char **file_lines_load(const char *fname, int *numlines, TALLOC_CTX *mem_ctx); - -/** -load a fd into memory and return an array of pointers to lines in the file -must be freed with talloc_free(). If convert is true calls unix_to_dos on -the list. -**/ -_PUBLIC_ char **fd_lines_load(int fd, int *numlines, TALLOC_CTX *mem_ctx); - -/** -take a list of lines and modify them to produce a list where \ continues -a line -**/ -_PUBLIC_ void file_lines_slashcont(char **lines); - -/** - save a lump of data into a file. Mostly used for debugging -*/ -_PUBLIC_ bool file_save(const char *fname, const void *packet, size_t length); -_PUBLIC_ int vfdprintf(int fd, const char *format, va_list ap) PRINTF_ATTRIBUTE(2,0); -_PUBLIC_ int fdprintf(int fd, const char *format, ...) PRINTF_ATTRIBUTE(2,3); -_PUBLIC_ bool large_file_support(const char *path); - -/* The following definitions come from lib/util/util.c */ - - -/** - Find a suitable temporary directory. The result should be copied immediately - as it may be overwritten by a subsequent call. -**/ -_PUBLIC_ const char *tmpdir(void); - -/** - Check if a file exists - call vfs_file_exist for samba files. -**/ -_PUBLIC_ bool file_exist(const char *fname); - -/** - Check a files mod time. -**/ -_PUBLIC_ time_t file_modtime(const char *fname); - -/** - Check if a directory exists. -**/ -_PUBLIC_ bool directory_exist(const char *dname); - -/** - * Try to create the specified directory if it didn't exist. - * - * @retval true if the directory already existed and has the right permissions - * or was successfully created. - */ -_PUBLIC_ bool directory_create_or_exist(const char *dname, uid_t uid, - mode_t dir_perms); - -/** - Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available, - else - if SYSV use O_NDELAY - if BSD use FNDELAY -**/ -_PUBLIC_ int set_blocking(int fd, bool set); - -/** - Sleep for a specified number of milliseconds. -**/ -_PUBLIC_ void msleep(unsigned int t); - -/** - Get my own name, return in malloc'ed storage. -**/ -_PUBLIC_ char* get_myname(void); - -/** - Return true if a string could be a pure IP address. -**/ -_PUBLIC_ bool is_ipaddress(const char *str); - -/** - Interpret an internet address or name into an IP address in 4 byte form. -**/ -_PUBLIC_ uint32_t interpret_addr(const char *str); - -/** - A convenient addition to interpret_addr(). -**/ -_PUBLIC_ struct in_addr interpret_addr2(const char *str); - -/** - Check if an IP is the 0.0.0.0. -**/ -_PUBLIC_ bool is_zero_ip(struct in_addr ip); - -/** - Are two IPs on the same subnet? -**/ -_PUBLIC_ bool same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask); - -/** - Check if a process exists. Does this work on all unixes? -**/ -_PUBLIC_ bool process_exists(pid_t pid); - -/** - Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping - is dealt with in posix.c -**/ -_PUBLIC_ bool fcntl_lock(int fd, int op, off_t offset, off_t count, int type); - -/** - * Write dump of binary data to the log file. - * - * The data is only written if the log level is at least level. - */ -_PUBLIC_ void dump_data(int level, const uint8_t *buf,int len); - -/** - * Write dump of binary data to the log file. - * - * The data is only written if the log level is at least level. - * 16 zero bytes in a row are ommited - */ -_PUBLIC_ void dump_data_skip_zeros(int level, const uint8_t *buf, int len); - -/** - malloc that aborts with smb_panic on fail or zero size. -**/ -_PUBLIC_ void *smb_xmalloc(size_t size); - -/** - Memdup with smb_panic on fail. -**/ -_PUBLIC_ void *smb_xmemdup(const void *p, size_t size); - -/** - strdup that aborts on malloc fail. -**/ -_PUBLIC_ char *smb_xstrdup(const char *s); - -/** - Like strdup but for memory. -**/ -_PUBLIC_ void *memdup(const void *p, size_t size); - -/** - * Write a password to the log file. - * - * @note Only actually does something if DEBUG_PASSWORD was defined during - * compile-time. - */ -_PUBLIC_ void dump_data_pw(const char *msg, const uint8_t * data, size_t len); - -/** - * see if a range of memory is all zero. A NULL pointer is considered - * to be all zero - */ -_PUBLIC_ bool all_zero(const uint8_t *ptr, size_t size); - -/** - realloc an array, checking for integer overflow in the array size -*/ -_PUBLIC_ void *realloc_array(void *ptr, size_t el_size, unsigned count); - -/* The following definitions come from lib/util/fsusage.c */ - - -/** - * Retrieve amount of free disk space. - * this does all of the system specific guff to get the free disk space. - * It is derived from code in the GNU fileutils package, but has been - * considerably mangled for use here - * - * results are returned in *dfree and *dsize, in 512 byte units -*/ -_PUBLIC_ int sys_fsusage(const char *path, uint64_t *dfree, uint64_t *dsize); - -/* The following definitions come from lib/util/ms_fnmatch.c */ - - -/** - * @file - * @brief MS-style Filename matching - */ - -/* protocol types. It assumes that higher protocols include lower protocols - as subsets. FIXME: Move to one of the smb-specific headers */ -enum protocol_types { - PROTOCOL_NONE, - PROTOCOL_CORE, - PROTOCOL_COREPLUS, - PROTOCOL_LANMAN1, - PROTOCOL_LANMAN2, - PROTOCOL_NT1, - PROTOCOL_SMB2 -}; - -int ms_fnmatch(const char *pattern, const char *string, enum protocol_types protocol); - -/** a generic fnmatch function - uses for non-CIFS pattern matching */ -int gen_fnmatch(const char *pattern, const char *string); - -/* The following definitions come from lib/util/mutex.c */ - - -/** - register a set of mutex/rwlock handlers. - Should only be called once in the execution of smbd. -*/ -_PUBLIC_ bool register_mutex_handlers(const char *name, struct mutex_ops *ops); - -/* The following definitions come from lib/util/idtree.c */ - - -/** - initialise a idr tree. The context return value must be passed to - all subsequent idr calls. To destroy the idr tree use talloc_free() - on this context - */ -_PUBLIC_ struct idr_context *idr_init(TALLOC_CTX *mem_ctx); - -/** - allocate the next available id, and assign 'ptr' into its slot. - you can retrieve later this pointer using idr_find() -*/ -_PUBLIC_ int idr_get_new(struct idr_context *idp, void *ptr, int limit); - -/** - allocate a new id, giving the first available value greater than or - equal to the given starting id -*/ -_PUBLIC_ int idr_get_new_above(struct idr_context *idp, void *ptr, int starting_id, int limit); - -/** - allocate a new id randomly in the given range -*/ -_PUBLIC_ int idr_get_new_random(struct idr_context *idp, void *ptr, int limit); - -/** - find a pointer value previously set with idr_get_new given an id -*/ -_PUBLIC_ void *idr_find(struct idr_context *idp, int id); - -/** - remove an id from the idr tree -*/ -_PUBLIC_ int idr_remove(struct idr_context *idp, int id); - -/* The following definitions come from lib/util/become_daemon.c */ - -/** - Become a daemon, discarding the controlling terminal. -**/ -_PUBLIC_ void become_daemon(bool fork); - -/** - * Load a ini-style file. - */ -bool pm_process( const char *fileName, - bool (*sfunc)(const char *, void *), - bool (*pfunc)(const char *, const char *, void *), - void *userdata); - -/** - * Add-on to talloc_get_type - */ -_PUBLIC_ void *talloc_check_name_abort(const void *ptr, const char *name); -#define talloc_get_type_abort(ptr, type) \ - (type *)talloc_check_name_abort(ptr, #type) - -#endif /* _SAMBA_UTIL_H_ */ diff --git a/source4/lib/util/util.m4 b/source4/lib/util/util.m4 deleted file mode 100644 index 9e362954cd..0000000000 --- a/source4/lib/util/util.m4 +++ /dev/null @@ -1 +0,0 @@ -AC_CHECK_FUNCS(setsid) diff --git a/source4/lib/util/util_file.c b/source4/lib/util/util_file.c deleted file mode 100644 index c3e22196c0..0000000000 --- a/source4/lib/util/util_file.c +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * SMB parameters and setup - * Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995. - * - * Added afdgets() Jelmer Vernooij 2005 - * - * 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 3 of the License, or (at your option) - * any later version. - * - * This program 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 General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, see . - */ - -#include "includes.h" -#include "system/shmem.h" -#include "system/filesys.h" - -/** - * @file - * @brief File-related utility functions - */ - -/** -read a line from a file with possible \ continuation chars. -Blanks at the start or end of a line are stripped. -The string will be allocated if s2 is NULL -**/ -_PUBLIC_ char *fgets_slash(char *s2,int maxlen,XFILE *f) -{ - char *s=s2; - int len = 0; - int c; - bool start_of_line = true; - - if (x_feof(f)) - return(NULL); - - if (maxlen <2) return(NULL); - - if (!s2) - { - maxlen = MIN(maxlen,8); - s = (char *)malloc(maxlen); - } - - if (!s) return(NULL); - - *s = 0; - - while (len < maxlen-1) - { - c = x_getc(f); - switch (c) - { - case '\r': - break; - case '\n': - while (len > 0 && s[len-1] == ' ') - { - s[--len] = 0; - } - if (len > 0 && s[len-1] == '\\') - { - s[--len] = 0; - start_of_line = true; - break; - } - return(s); - case EOF: - if (len <= 0 && !s2) - SAFE_FREE(s); - return(len>0?s:NULL); - case ' ': - if (start_of_line) - break; - /* fall through */ - default: - start_of_line = false; - s[len++] = c; - s[len] = 0; - } - if (!s2 && len > maxlen-3) - { - char *t; - - maxlen *= 2; - t = realloc_p(s, char, maxlen); - if (!t) { - DEBUG(0,("fgets_slash: failed to expand buffer!\n")); - SAFE_FREE(s); - return(NULL); - } else s = t; - } - } - return(s); -} - -/** - * Read one line (data until next newline or eof) and allocate it - */ -_PUBLIC_ char *afdgets(int fd, TALLOC_CTX *mem_ctx, size_t hint) -{ - char *data = NULL; - ssize_t alloc_size = 0, offset = 0, ret; - int p; - - if (hint <= 0) hint = 0x100; - - do { - alloc_size += hint; - - data = talloc_realloc(mem_ctx, data, char, alloc_size); - - if (!data) - return NULL; - - ret = read(fd, data + offset, hint); - - if (ret == 0) { - return NULL; - } - - if (ret == -1) { - talloc_free(data); - return NULL; - } - - /* Find newline */ - for (p = 0; p < ret; p++) { - if (data[offset + p] == '\n') - break; - } - - if (p < ret) { - data[offset + p] = '\0'; - - /* Go back to position of newline */ - lseek(fd, p - ret + 1, SEEK_CUR); - return data; - } - - offset += ret; - - } while (ret == hint); - - data[offset] = '\0'; - - return data; -} - - -/** -load a file into memory from a fd. -**/ -_PUBLIC_ char *fd_load(int fd, size_t *size, TALLOC_CTX *mem_ctx) -{ - struct stat sbuf; - char *p; - - if (fstat(fd, &sbuf) != 0) return NULL; - - p = (char *)talloc_size(mem_ctx, sbuf.st_size+1); - if (!p) return NULL; - - if (read(fd, p, sbuf.st_size) != sbuf.st_size) { - talloc_free(p); - return NULL; - } - p[sbuf.st_size] = 0; - - if (size) *size = sbuf.st_size; - - return p; -} - -/** -load a file into memory -**/ -_PUBLIC_ char *file_load(const char *fname, size_t *size, TALLOC_CTX *mem_ctx) -{ - int fd; - char *p; - - if (!fname || !*fname) return NULL; - - fd = open(fname,O_RDONLY); - if (fd == -1) return NULL; - - p = fd_load(fd, size, mem_ctx); - - close(fd); - - return p; -} - - -/** -mmap (if possible) or read a file -**/ -_PUBLIC_ void *map_file(const char *fname, size_t size) -{ - size_t s2 = 0; - void *p = NULL; -#ifdef HAVE_MMAP - int fd; - fd = open(fname, O_RDONLY, 0); - if (fd == -1) { - DEBUG(2,("Failed to load %s - %s\n", fname, strerror(errno))); - return NULL; - } - p = mmap(NULL, size, PROT_READ, MAP_SHARED|MAP_FILE, fd, 0); - close(fd); - if (p == MAP_FAILED) { - DEBUG(1,("Failed to mmap %s - %s\n", fname, strerror(errno))); - return NULL; - } -#endif - if (!p) { - p = file_load(fname, &s2, talloc_autofree_context()); - if (!p) return NULL; - if (s2 != size) { - DEBUG(1,("incorrect size for %s - got %d expected %d\n", - fname, (int)s2, (int)size)); - talloc_free(p); - return NULL; - } - } - - return p; -} - - -/** -parse a buffer into lines -'p' will be freed on error, and otherwise will be made a child of the returned array -**/ -static char **file_lines_parse(char *p, size_t size, int *numlines, TALLOC_CTX *mem_ctx) -{ - int i; - char *s, **ret; - - if (!p) return NULL; - - for (s = p, i=0; s < p+size; s++) { - if (s[0] == '\n') i++; - } - - ret = talloc_array(mem_ctx, char *, i+2); - if (!ret) { - talloc_free(p); - return NULL; - } - - talloc_steal(ret, p); - - memset(ret, 0, sizeof(ret[0])*(i+2)); - - ret[0] = p; - for (s = p, i=0; s < p+size; s++) { - if (s[0] == '\n') { - s[0] = 0; - i++; - ret[i] = s+1; - } - if (s[0] == '\r') s[0] = 0; - } - - /* remove any blank lines at the end */ - while (i > 0 && ret[i-1][0] == 0) { - i--; - } - - if (numlines) *numlines = i; - - return ret; -} - - -/** -load a file into memory and return an array of pointers to lines in the file -must be freed with talloc_free(). -**/ -_PUBLIC_ char **file_lines_load(const char *fname, int *numlines, TALLOC_CTX *mem_ctx) -{ - char *p; - size_t size; - - p = file_load(fname, &size, mem_ctx); - if (!p) return NULL; - - return file_lines_parse(p, size, numlines, mem_ctx); -} - -/** -load a fd into memory and return an array of pointers to lines in the file -must be freed with talloc_free(). If convert is true calls unix_to_dos on -the list. -**/ -_PUBLIC_ char **fd_lines_load(int fd, int *numlines, TALLOC_CTX *mem_ctx) -{ - char *p; - size_t size; - - p = fd_load(fd, &size, mem_ctx); - if (!p) return NULL; - - return file_lines_parse(p, size, numlines, mem_ctx); -} - - -/** -take a list of lines and modify them to produce a list where \ continues -a line -**/ -_PUBLIC_ void file_lines_slashcont(char **lines) -{ - int i, j; - - for (i=0; lines[i];) { - int len = strlen(lines[i]); - if (lines[i][len-1] == '\\') { - lines[i][len-1] = ' '; - if (lines[i+1]) { - char *p = &lines[i][len]; - while (p < lines[i+1]) *p++ = ' '; - for (j = i+1; lines[j]; j++) lines[j] = lines[j+1]; - } - } else { - i++; - } - } -} - -/** - save a lump of data into a file. Mostly used for debugging -*/ -_PUBLIC_ bool file_save(const char *fname, const void *packet, size_t length) -{ - int fd; - fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0644); - if (fd == -1) { - return false; - } - if (write(fd, packet, length) != (size_t)length) { - return false; - } - close(fd); - return true; -} - -_PUBLIC_ int vfdprintf(int fd, const char *format, va_list ap) -{ - char *p; - int len, ret; - va_list ap2; - - va_copy(ap2, ap); - len = vasprintf(&p, format, ap2); - va_end(ap2); - if (len <= 0) return len; - ret = write(fd, p, len); - SAFE_FREE(p); - return ret; -} - -_PUBLIC_ int fdprintf(int fd, const char *format, ...) -{ - va_list ap; - int ret; - - va_start(ap, format); - ret = vfdprintf(fd, format, ap); - va_end(ap); - return ret; -} - - -/* - try to determine if the filesystem supports large files -*/ -_PUBLIC_ bool large_file_support(const char *path) -{ - int fd; - ssize_t ret; - char c; - - fd = open(path, O_RDWR|O_CREAT, 0600); - unlink(path); - if (fd == -1) { - /* have to assume large files are OK */ - return true; - } - ret = pread(fd, &c, 1, ((uint64_t)1)<<32); - close(fd); - return ret == 0; -} diff --git a/source4/lib/util/util_getent.c b/source4/lib/util/util_getent.c deleted file mode 100644 index b9b2658f59..0000000000 --- a/source4/lib/util/util_getent.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Samba utility functions - Copyright (C) Simo Sorce 2001 - Copyright (C) Jeremy Allison 2001 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" - - -/**************************************************************** - Returns a single linked list of group entries. - Use grent_free() to free it after use. -****************************************************************/ - -struct sys_grent * getgrent_list(void) -{ - struct sys_grent *glist; - struct sys_grent *gent; - struct group *grp; - - gent = malloc_p(struct sys_grent); - if (gent == NULL) { - DEBUG (0, ("Out of memory in getgrent_list!\n")); - return NULL; - } - memset(gent, '\0', sizeof(struct sys_grent)); - glist = gent; - - setgrent(); - grp = getgrent(); - if (grp == NULL) { - endgrent(); - SAFE_FREE(glist); - return NULL; - } - - while (grp != NULL) { - int i,num; - - if (grp->gr_name) { - if ((gent->gr_name = strdup(grp->gr_name)) == NULL) - goto err; - } - if (grp->gr_passwd) { - if ((gent->gr_passwd = strdup(grp->gr_passwd)) == NULL) - goto err; - } - gent->gr_gid = grp->gr_gid; - - /* number of strings in gr_mem */ - for (num = 0; grp->gr_mem[num]; num++) - ; - - /* alloc space for gr_mem string pointers */ - if ((gent->gr_mem = malloc_array_p(char *, num+1)) == NULL) - goto err; - - memset(gent->gr_mem, '\0', (num+1) * sizeof(char *)); - - for (i=0; i < num; i++) { - if ((gent->gr_mem[i] = strdup(grp->gr_mem[i])) == NULL) - goto err; - } - gent->gr_mem[num] = NULL; - - grp = getgrent(); - if (grp) { - gent->next = malloc_p(struct sys_grent); - if (gent->next == NULL) - goto err; - gent = gent->next; - memset(gent, '\0', sizeof(struct sys_grent)); - } - } - - endgrent(); - return glist; - - err: - - endgrent(); - DEBUG(0, ("Out of memory in getgrent_list!\n")); - grent_free(glist); - return NULL; -} - -/**************************************************************** - Free the single linked list of group entries made by - getgrent_list() -****************************************************************/ - -void grent_free (struct sys_grent *glist) -{ - while (glist) { - struct sys_grent *prev; - - SAFE_FREE(glist->gr_name); - SAFE_FREE(glist->gr_passwd); - if (glist->gr_mem) { - int i; - for (i = 0; glist->gr_mem[i]; i++) - SAFE_FREE(glist->gr_mem[i]); - SAFE_FREE(glist->gr_mem); - } - prev = glist; - glist = glist->next; - SAFE_FREE(prev); - } -} - -/**************************************************************** - Returns a single linked list of passwd entries. - Use pwent_free() to free it after use. -****************************************************************/ - -struct sys_pwent * getpwent_list(void) -{ - struct sys_pwent *plist; - struct sys_pwent *pent; - struct passwd *pwd; - - pent = malloc_p(struct sys_pwent); - if (pent == NULL) { - DEBUG (0, ("Out of memory in getpwent_list!\n")); - return NULL; - } - plist = pent; - - setpwent(); - pwd = getpwent(); - while (pwd != NULL) { - memset(pent, '\0', sizeof(struct sys_pwent)); - if (pwd->pw_name) { - if ((pent->pw_name = strdup(pwd->pw_name)) == NULL) - goto err; - } - if (pwd->pw_passwd) { - if ((pent->pw_passwd = strdup(pwd->pw_passwd)) == NULL) - goto err; - } - pent->pw_uid = pwd->pw_uid; - pent->pw_gid = pwd->pw_gid; - if (pwd->pw_gecos) { - if ((pent->pw_name = strdup(pwd->pw_gecos)) == NULL) - goto err; - } - if (pwd->pw_dir) { - if ((pent->pw_name = strdup(pwd->pw_dir)) == NULL) - goto err; - } - if (pwd->pw_shell) { - if ((pent->pw_name = strdup(pwd->pw_shell)) == NULL) - goto err; - } - - pwd = getpwent(); - if (pwd) { - pent->next = malloc_p(struct sys_pwent); - if (pent->next == NULL) - goto err; - pent = pent->next; - } - } - - endpwent(); - return plist; - - err: - - endpwent(); - DEBUG(0, ("Out of memory in getpwent_list!\n")); - pwent_free(plist); - return NULL; -} - -/**************************************************************** - Free the single linked list of passwd entries made by - getpwent_list() -****************************************************************/ - -void pwent_free (struct sys_pwent *plist) -{ - while (plist) { - struct sys_pwent *prev; - - SAFE_FREE(plist->pw_name); - SAFE_FREE(plist->pw_passwd); - SAFE_FREE(plist->pw_gecos); - SAFE_FREE(plist->pw_dir); - SAFE_FREE(plist->pw_shell); - - prev = plist; - plist = plist->next; - SAFE_FREE(prev); - } -} - -/**************************************************************** - Add the individual group users onto the list. -****************************************************************/ - -static struct sys_userlist *add_members_to_userlist(struct sys_userlist *list_head, const struct group *grp) -{ - size_t num_users, i; - - /* Count the number of users. */ - for (num_users = 0; grp->gr_mem[num_users]; num_users++) - ; - - for (i = 0; i < num_users; i++) { - struct sys_userlist *entry = malloc_p(struct sys_userlist); - if (entry == NULL) { - free_userlist(list_head); - return NULL; - } - entry->unix_name = (char *)strdup(grp->gr_mem[i]); - if (entry->unix_name == NULL) { - SAFE_FREE(entry); - free_userlist(list_head); - return NULL; - } - DLIST_ADD(list_head, entry); - } - return list_head; -} - -/**************************************************************** - Get the list of UNIX users in a group. - We have to enumerate the /etc/group file as some UNIX getgrnam() - calls won't do that for us (notably Tru64 UNIX). -****************************************************************/ - -struct sys_userlist *get_users_in_group(const char *gname) -{ - struct sys_userlist *list_head = NULL; - struct group *gptr; - -#if !defined(BROKEN_GETGRNAM) - if ((gptr = (struct group *)getgrnam(gname)) == NULL) - return NULL; - return add_members_to_userlist(list_head, gptr); -#else - /* BROKEN_GETGRNAM - True64 */ - setgrent(); - while((gptr = getgrent()) != NULL) { - if (strequal(gname, gptr->gr_name)) { - list_head = add_members_to_userlist(list_head, gptr); - if (list_head == NULL) - return NULL; - } - } - endgrent(); - return list_head; -#endif -} - -/**************************************************************** - Free list allocated above. -****************************************************************/ - -void free_userlist(struct sys_userlist *list_head) -{ - while (list_head) { - struct sys_userlist *old_head = list_head; - DLIST_REMOVE(list_head, list_head); - SAFE_FREE(old_head->unix_name); - SAFE_FREE(old_head); - } -} diff --git a/source4/lib/util/util_ldb.c b/source4/lib/util/util_ldb.c deleted file mode 100644 index 0465022edd..0000000000 --- a/source4/lib/util/util_ldb.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - common share info functions - - Copyright (C) Andrew Tridgell 2004 - Copyright (C) Tim Potter 2004 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" -#include "lib/events/events.h" -#include "lib/ldb/include/ldb.h" -#include "lib/ldb/include/ldb_errors.h" -#include "lib/util/util_ldb.h" -/* - search the sam for the specified attributes - va_list variant -*/ -int gendb_search_v(struct ldb_context *ldb, - TALLOC_CTX *mem_ctx, - struct ldb_dn *basedn, - struct ldb_message ***msgs, - const char * const *attrs, - const char *format, - va_list ap) -{ - enum ldb_scope scope = LDB_SCOPE_SUBTREE; - struct ldb_result *res; - char *expr = NULL; - int ret; - - if (format) { - expr = talloc_vasprintf(mem_ctx, format, ap); - if (expr == NULL) { - return -1; - } - } else { - scope = LDB_SCOPE_BASE; - } - - res = NULL; - - ret = ldb_search(ldb, mem_ctx, &res, basedn, scope, attrs, - expr?"%s":NULL, expr); - - if (ret == LDB_SUCCESS) { - talloc_steal(mem_ctx, res->msgs); - - DEBUG(6,("gendb_search_v: %s %s -> %d\n", - basedn?ldb_dn_get_linearized(basedn):"NULL", - expr?expr:"NULL", res->count)); - - ret = res->count; - *msgs = res->msgs; - talloc_free(res); - } else if (scope == LDB_SCOPE_BASE && ret == LDB_ERR_NO_SUCH_OBJECT) { - ret = 0; - *msgs = NULL; - } else { - DEBUG(4,("gendb_search_v: search failed: %s\n", - ldb_errstring(ldb))); - ret = -1; - } - - talloc_free(expr); - - return ret; -} - -/* - search the LDB for the specified attributes - varargs variant -*/ -int gendb_search(struct ldb_context *ldb, - TALLOC_CTX *mem_ctx, - struct ldb_dn *basedn, - struct ldb_message ***res, - const char * const *attrs, - const char *format, ...) -{ - va_list ap; - int count; - - va_start(ap, format); - count = gendb_search_v(ldb, mem_ctx, basedn, res, attrs, format, ap); - va_end(ap); - - return count; -} - -/* - search the LDB for a specified record (by DN) -*/ - -int gendb_search_dn(struct ldb_context *ldb, - TALLOC_CTX *mem_ctx, - struct ldb_dn *dn, - struct ldb_message ***res, - const char * const *attrs) -{ - return gendb_search(ldb, mem_ctx, dn, res, attrs, NULL); -} - -/* - setup some initial ldif in a ldb -*/ -int gendb_add_ldif(struct ldb_context *ldb, const char *ldif_string) -{ - struct ldb_ldif *ldif; - int ret; - ldif = ldb_ldif_read_string(ldb, &ldif_string); - if (ldif == NULL) return -1; - ret = ldb_add(ldb, ldif->msg); - talloc_free(ldif); - return ret; -} - -char *wrap_casefold(void *context, void *mem_ctx, const char *s, size_t n) -{ - return strupper_talloc_n(mem_ctx, s, n); -} - - diff --git a/source4/lib/util/util_ldb.h b/source4/lib/util/util_ldb.h deleted file mode 100644 index 43f98ae1a9..0000000000 --- a/source4/lib/util/util_ldb.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef __LIB_UTIL_UTIL_LDB_H__ -#define __LIB_UTIL_UTIL_LDB_H__ - -/* The following definitions come from lib/util/util_ldb.c */ - -int gendb_search_v(struct ldb_context *ldb, - TALLOC_CTX *mem_ctx, - struct ldb_dn *basedn, - struct ldb_message ***msgs, - const char * const *attrs, - const char *format, - va_list ap) PRINTF_ATTRIBUTE(6,0); -int gendb_search(struct ldb_context *ldb, - TALLOC_CTX *mem_ctx, - struct ldb_dn *basedn, - struct ldb_message ***res, - const char * const *attrs, - const char *format, ...) PRINTF_ATTRIBUTE(6,7); -int gendb_search_dn(struct ldb_context *ldb, - TALLOC_CTX *mem_ctx, - struct ldb_dn *dn, - struct ldb_message ***res, - const char * const *attrs); -int gendb_add_ldif(struct ldb_context *ldb, const char *ldif_string); -char *wrap_casefold(void *context, void *mem_ctx, const char *s, size_t n); - -#endif /* __LIB_UTIL_UTIL_LDB_H__ */ diff --git a/source4/lib/util/util_pw.c b/source4/lib/util/util_pw.c deleted file mode 100644 index 11e46ec4e3..0000000000 --- a/source4/lib/util/util_pw.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Safe versions of getpw* calls - - Copyright (C) Andrew Bartlett 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" - -static struct passwd *alloc_copy_passwd(TALLOC_CTX *mem_ctx, - const struct passwd *from) -{ - struct passwd *ret = talloc_zero(mem_ctx, struct passwd); - - if (ret == NULL) - return NULL; - - ret->pw_name = talloc_strdup(ret, from->pw_name); - ret->pw_passwd = talloc_strdup(ret, from->pw_passwd); - ret->pw_uid = from->pw_uid; - ret->pw_gid = from->pw_gid; - ret->pw_gecos = talloc_strdup(ret, from->pw_gecos); - ret->pw_dir = talloc_strdup(ret, from->pw_dir); - ret->pw_shell = talloc_strdup(ret, from->pw_shell); - - return ret; -} - -struct passwd *getpwnam_alloc(TALLOC_CTX *mem_ctx, const char *name) -{ - struct passwd *temp; - - temp = sys_getpwnam(name); - - if (!temp) { -#if 0 - if (errno == ENOMEM) { - /* what now? */ - } -#endif - return NULL; - } - - return alloc_copy_passwd(mem_ctx, temp); -} - -struct passwd *getpwuid_alloc(TALLOC_CTX *mem_ctx, uid_t uid) -{ - struct passwd *temp; - - temp = sys_getpwuid(uid); - - if (!temp) { -#if 0 - if (errno == ENOMEM) { - /* what now? */ - } -#endif - return NULL; - } - - return alloc_copy_passwd(mem_ctx, temp); -} diff --git a/source4/lib/util/util_str.c b/source4/lib/util/util_str.c deleted file mode 100644 index 9ea6403c52..0000000000 --- a/source4/lib/util/util_str.c +++ /dev/null @@ -1,790 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Samba utility functions - - Copyright (C) Andrew Tridgell 1992-2001 - Copyright (C) Simo Sorce 2001-2002 - Copyright (C) Martin Pool 2003 - Copyright (C) James Peach 2005 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" -#include "libcli/raw/smb.h" -#include "system/locale.h" - -/** - * @file - * @brief String utilities. - **/ - - -/** - Trim the specified elements off the front and back of a string. -**/ -_PUBLIC_ bool trim_string(char *s, const char *front, const char *back) -{ - bool ret = false; - size_t front_len; - size_t back_len; - size_t len; - - /* Ignore null or empty strings. */ - if (!s || (s[0] == '\0')) - return false; - - front_len = front? strlen(front) : 0; - back_len = back? strlen(back) : 0; - - len = strlen(s); - - if (front_len) { - while (len && strncmp(s, front, front_len)==0) { - /* Must use memmove here as src & dest can - * easily overlap. Found by valgrind. JRA. */ - memmove(s, s+front_len, (len-front_len)+1); - len -= front_len; - ret=true; - } - } - - if (back_len) { - while ((len >= back_len) && strncmp(s+len-back_len,back,back_len)==0) { - s[len-back_len]='\0'; - len -= back_len; - ret=true; - } - } - return ret; -} - -/** - Find the number of 'c' chars in a string -**/ -_PUBLIC_ _PURE_ size_t count_chars(const char *s, char c) -{ - size_t count = 0; - - while (*s) { - if (*s == c) count++; - s ++; - } - - return count; -} - - - -/** - Safe string copy into a known length string. maxlength does not - include the terminating zero. -**/ -_PUBLIC_ char *safe_strcpy(char *dest,const char *src, size_t maxlength) -{ - size_t len; - - if (!dest) { - DEBUG(0,("ERROR: NULL dest in safe_strcpy\n")); - return NULL; - } - -#ifdef DEVELOPER - /* We intentionally write out at the extremity of the destination - * string. If the destination is too short (e.g. pstrcpy into mallocd - * or fstring) then this should cause an error under a memory - * checker. */ - dest[maxlength] = '\0'; - if (PTR_DIFF(&len, dest) > 0) { /* check if destination is on the stack, ok if so */ - log_suspicious_usage("safe_strcpy", src); - } -#endif - - if (!src) { - *dest = 0; - return dest; - } - - len = strlen(src); - - if (len > maxlength) { - DEBUG(0,("ERROR: string overflow by %u (%u - %u) in safe_strcpy [%.50s]\n", - (uint_t)(len-maxlength), (unsigned)len, (unsigned)maxlength, src)); - len = maxlength; - } - - memmove(dest, src, len); - dest[len] = 0; - return dest; -} - -/** - Safe string cat into a string. maxlength does not - include the terminating zero. -**/ -_PUBLIC_ char *safe_strcat(char *dest, const char *src, size_t maxlength) -{ - size_t src_len, dest_len; - - if (!dest) { - DEBUG(0,("ERROR: NULL dest in safe_strcat\n")); - return NULL; - } - - if (!src) - return dest; - -#ifdef DEVELOPER - if (PTR_DIFF(&src_len, dest) > 0) { /* check if destination is on the stack, ok if so */ - log_suspicious_usage("safe_strcat", src); - } -#endif - src_len = strlen(src); - dest_len = strlen(dest); - - if (src_len + dest_len > maxlength) { - DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n", - (int)(src_len + dest_len - maxlength), src)); - if (maxlength > dest_len) { - memcpy(&dest[dest_len], src, maxlength - dest_len); - } - dest[maxlength] = 0; - return NULL; - } - - memcpy(&dest[dest_len], src, src_len); - dest[dest_len + src_len] = 0; - return dest; -} - -/** - Routine to get hex characters and turn them into a 16 byte array. - the array can be variable length, and any non-hex-numeric - characters are skipped. "0xnn" or "0Xnn" is specially catered - for. - - valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n" - - -**/ -_PUBLIC_ size_t strhex_to_str(char *p, size_t len, const char *strhex) -{ - size_t i; - size_t num_chars = 0; - uint8_t lonybble, hinybble; - const char *hexchars = "0123456789ABCDEF"; - char *p1 = NULL, *p2 = NULL; - - for (i = 0; i < len && strhex[i] != 0; i++) { - if (strncasecmp(hexchars, "0x", 2) == 0) { - i++; /* skip two chars */ - continue; - } - - if (!(p1 = strchr(hexchars, toupper((unsigned char)strhex[i])))) - break; - - i++; /* next hex digit */ - - if (!(p2 = strchr(hexchars, toupper((unsigned char)strhex[i])))) - break; - - /* get the two nybbles */ - hinybble = PTR_DIFF(p1, hexchars); - lonybble = PTR_DIFF(p2, hexchars); - - p[num_chars] = (hinybble << 4) | lonybble; - num_chars++; - - p1 = NULL; - p2 = NULL; - } - return num_chars; -} - -/** - * Parse a hex string and return a data blob. - */ -_PUBLIC_ _PURE_ DATA_BLOB strhex_to_data_blob(const char *strhex) -{ - DATA_BLOB ret_blob = data_blob(NULL, strlen(strhex)/2+1); - - ret_blob.length = strhex_to_str((char *)ret_blob.data, - strlen(strhex), - strhex); - - return ret_blob; -} - - -/** - * Routine to print a buffer as HEX digits, into an allocated string. - */ -_PUBLIC_ void hex_encode(const unsigned char *buff_in, size_t len, char **out_hex_buffer) -{ - int i; - char *hex_buffer; - - *out_hex_buffer = malloc_array_p(char, (len*2)+1); - hex_buffer = *out_hex_buffer; - - for (i = 0; i < len; i++) - slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]); -} - -/** - * talloc version of hex_encode() - */ -_PUBLIC_ char *hex_encode_talloc(TALLOC_CTX *mem_ctx, const unsigned char *buff_in, size_t len) -{ - int i; - char *hex_buffer; - - hex_buffer = talloc_array(mem_ctx, char, (len*2)+1); - - for (i = 0; i < len; i++) - slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]); - - return hex_buffer; -} - -/** - Substitute a string for a pattern in another string. Make sure there is - enough room! - - This routine looks for pattern in s and replaces it with - insert. It may do multiple replacements. - - Any of " ; ' $ or ` in the insert string are replaced with _ - if len==0 then the string cannot be extended. This is different from the old - use of len==0 which was for no length checks to be done. -**/ - -_PUBLIC_ void string_sub(char *s, const char *pattern, const char *insert, size_t len) -{ - char *p; - ssize_t ls, lp, li, i; - - if (!insert || !pattern || !*pattern || !s) - return; - - ls = (ssize_t)strlen(s); - lp = (ssize_t)strlen(pattern); - li = (ssize_t)strlen(insert); - - if (len == 0) - len = ls + 1; /* len is number of *bytes* */ - - while (lp <= ls && (p = strstr(s, pattern))) { - if (ls + (li-lp) >= len) { - DEBUG(0,("ERROR: string overflow by %d in string_sub(%.50s, %d)\n", - (int)(ls + (li-lp) - len), - pattern, (int)len)); - break; - } - if (li != lp) { - memmove(p+li,p+lp,strlen(p+lp)+1); - } - for (i=0;i= len) { - DEBUG(0,("ERROR: string overflow by %d in all_string_sub(%.50s, %d)\n", - (int)(ls + (li-lp) - len), - pattern, (int)len)); - break; - } - if (li != lp) { - memmove(p+li,p+lp,strlen(p+lp)+1); - } - memcpy(p, insert, li); - s = p + li; - ls += (li-lp); - } -} - - - -/** - Unescape a URL encoded string, in place. -**/ - -_PUBLIC_ void rfc1738_unescape(char *buf) -{ - char *p=buf; - - while ((p=strchr(p,'+'))) - *p = ' '; - - p = buf; - - while (p && *p && (p=strchr(p,'%'))) { - int c1 = p[1]; - int c2 = p[2]; - - if (c1 >= '0' && c1 <= '9') - c1 = c1 - '0'; - else if (c1 >= 'A' && c1 <= 'F') - c1 = 10 + c1 - 'A'; - else if (c1 >= 'a' && c1 <= 'f') - c1 = 10 + c1 - 'a'; - else {p++; continue;} - - if (c2 >= '0' && c2 <= '9') - c2 = c2 - '0'; - else if (c2 >= 'A' && c2 <= 'F') - c2 = 10 + c2 - 'A'; - else if (c2 >= 'a' && c2 <= 'f') - c2 = 10 + c2 - 'a'; - else {p++; continue;} - - *p = (c1<<4) | c2; - - memmove(p+1, p+3, strlen(p+3)+1); - p++; - } -} - -#ifdef VALGRIND -size_t valgrind_strlen(const char *s) -{ - size_t count; - for(count = 0; *s++; count++) - ; - return count; -} -#endif - - -/** - format a string into length-prefixed dotted domain format, as used in NBT - and in some ADS structures -**/ -_PUBLIC_ const char *str_format_nbt_domain(TALLOC_CTX *mem_ctx, const char *s) -{ - char *ret; - int i; - if (!s || !*s) { - return talloc_strdup(mem_ctx, ""); - } - ret = talloc_array(mem_ctx, char, strlen(s)+2); - if (!ret) { - return ret; - } - - memcpy(ret+1, s, strlen(s)+1); - ret[0] = '.'; - - for (i=0;ret[i];i++) { - if (ret[i] == '.') { - char *p = strchr(ret+i+1, '.'); - if (p) { - ret[i] = p-(ret+i+1); - } else { - ret[i] = strlen(ret+i+1); - } - } - } - - return ret; -} - -/** - * Add a string to an array of strings. - * - * num should be a pointer to an integer that holds the current - * number of elements in strings. It will be updated by this function. - */ -_PUBLIC_ bool add_string_to_array(TALLOC_CTX *mem_ctx, - const char *str, const char ***strings, int *num) -{ - char *dup_str = talloc_strdup(mem_ctx, str); - - *strings = talloc_realloc(mem_ctx, - *strings, - const char *, ((*num)+1)); - - if ((*strings == NULL) || (dup_str == NULL)) - return false; - - (*strings)[*num] = dup_str; - *num += 1; - - return true; -} - - - -/** - varient of strcmp() that handles NULL ptrs -**/ -_PUBLIC_ int strcmp_safe(const char *s1, const char *s2) -{ - if (s1 == s2) { - return 0; - } - if (s1 == NULL || s2 == NULL) { - return s1?-1:1; - } - return strcmp(s1, s2); -} - - -/** -return the number of bytes occupied by a buffer in ASCII format -the result includes the null termination -limited by 'n' bytes -**/ -_PUBLIC_ size_t ascii_len_n(const char *src, size_t n) -{ - size_t len; - - len = strnlen(src, n); - if (len+1 <= n) { - len += 1; - } - - return len; -} - - -/** - Return a string representing a CIFS attribute for a file. -**/ -_PUBLIC_ char *attrib_string(TALLOC_CTX *mem_ctx, uint32_t attrib) -{ - int i, len; - const struct { - char c; - uint16_t attr; - } attr_strs[] = { - {'V', FILE_ATTRIBUTE_VOLUME}, - {'D', FILE_ATTRIBUTE_DIRECTORY}, - {'A', FILE_ATTRIBUTE_ARCHIVE}, - {'H', FILE_ATTRIBUTE_HIDDEN}, - {'S', FILE_ATTRIBUTE_SYSTEM}, - {'N', FILE_ATTRIBUTE_NORMAL}, - {'R', FILE_ATTRIBUTE_READONLY}, - {'d', FILE_ATTRIBUTE_DEVICE}, - {'t', FILE_ATTRIBUTE_TEMPORARY}, - {'s', FILE_ATTRIBUTE_SPARSE}, - {'r', FILE_ATTRIBUTE_REPARSE_POINT}, - {'c', FILE_ATTRIBUTE_COMPRESSED}, - {'o', FILE_ATTRIBUTE_OFFLINE}, - {'n', FILE_ATTRIBUTE_NONINDEXED}, - {'e', FILE_ATTRIBUTE_ENCRYPTED} - }; - char *ret; - - ret = talloc_array(mem_ctx, char, ARRAY_SIZE(attr_strs)+1); - if (!ret) { - return NULL; - } - - for (len=i=0; i. -*/ - -#include "includes.h" -#include "system/locale.h" - -/** - * @file - * @brief String list manipulation - */ - -/** - build a null terminated list of strings from a input string and a - separator list. The separator list must contain characters less than - or equal to 0x2f for this to work correctly on multi-byte strings -*/ -_PUBLIC_ const char **str_list_make(TALLOC_CTX *mem_ctx, const char *string, const char *sep) -{ - int num_elements = 0; - const char **ret = NULL; - - if (sep == NULL) { - sep = LIST_SEP; - } - - ret = talloc_array(mem_ctx, const char *, 1); - if (ret == NULL) { - return NULL; - } - - while (string && *string) { - size_t len = strcspn(string, sep); - const char **ret2; - - if (len == 0) { - string += strspn(string, sep); - continue; - } - - ret2 = talloc_realloc(mem_ctx, ret, const char *, num_elements+2); - if (ret2 == NULL) { - talloc_free(ret); - return NULL; - } - ret = ret2; - - ret[num_elements] = talloc_strndup(ret, string, len); - if (ret[num_elements] == NULL) { - talloc_free(ret); - return NULL; - } - - num_elements++; - string += len; - } - - ret[num_elements] = NULL; - - return ret; -} - -/** - * build a null terminated list of strings from an argv-like input string - * Entries are seperated by spaces and can be enclosed by quotes. - * Does NOT support escaping - */ -_PUBLIC_ const char **str_list_make_shell(TALLOC_CTX *mem_ctx, const char *string, const char *sep) -{ - int num_elements = 0; - const char **ret = NULL; - - ret = talloc_array(mem_ctx, const char *, 1); - if (ret == NULL) { - return NULL; - } - - if (sep == NULL) - sep = " \t\n\r"; - - while (string && *string) { - size_t len = strcspn(string, sep); - char *element; - const char **ret2; - - if (len == 0) { - string += strspn(string, sep); - continue; - } - - if (*string == '\"') { - string++; - len = strcspn(string, "\""); - element = talloc_strndup(ret, string, len); - string += len + 1; - } else { - element = talloc_strndup(ret, string, len); - string += len; - } - - if (element == NULL) { - talloc_free(ret); - return NULL; - } - - ret2 = talloc_realloc(mem_ctx, ret, const char *, num_elements+2); - if (ret2 == NULL) { - talloc_free(ret); - return NULL; - } - ret = ret2; - - ret[num_elements] = element; - - num_elements++; - } - - ret[num_elements] = NULL; - - return ret; - -} - -/** - * join a list back to one string - */ -_PUBLIC_ char *str_list_join(TALLOC_CTX *mem_ctx, const char **list, char seperator) -{ - char *ret = NULL; - int i; - - if (list[0] == NULL) - return talloc_strdup(mem_ctx, ""); - - ret = talloc_strdup(mem_ctx, list[0]); - - for (i = 1; list[i]; i++) { - ret = talloc_asprintf_append_buffer(ret, "%c%s", seperator, list[i]); - } - - return ret; -} - -/** join a list back to one (shell-like) string; entries - * seperated by spaces, using quotes where necessary */ -_PUBLIC_ char *str_list_join_shell(TALLOC_CTX *mem_ctx, const char **list, char sep) -{ - char *ret = NULL; - int i; - - if (list[0] == NULL) - return talloc_strdup(mem_ctx, ""); - - if (strchr(list[0], ' ') || strlen(list[0]) == 0) - ret = talloc_asprintf(mem_ctx, "\"%s\"", list[0]); - else - ret = talloc_strdup(mem_ctx, list[0]); - - for (i = 1; list[i]; i++) { - if (strchr(list[i], ' ') || strlen(list[i]) == 0) - ret = talloc_asprintf_append_buffer(ret, "%c\"%s\"", sep, list[i]); - else - ret = talloc_asprintf_append_buffer(ret, "%c%s", sep, list[i]); - } - - return ret; -} - -/** - return the number of elements in a string list -*/ -_PUBLIC_ size_t str_list_length(const char **list) -{ - size_t ret; - for (ret=0;list && list[ret];ret++) /* noop */ ; - return ret; -} - - -/** - copy a string list -*/ -_PUBLIC_ const char **str_list_copy(TALLOC_CTX *mem_ctx, const char **list) -{ - int i; - const char **ret; - - if (list == NULL) - return NULL; - - ret = talloc_array(mem_ctx, const char *, str_list_length(list)+1); - if (ret == NULL) - return NULL; - - for (i=0;list && list[i];i++) { - ret[i] = talloc_strdup(ret, list[i]); - if (ret[i] == NULL) { - talloc_free(ret); - return NULL; - } - } - ret[i] = NULL; - return ret; -} - -/** - Return true if all the elements of the list match exactly. - */ -_PUBLIC_ bool str_list_equal(const char **list1, const char **list2) -{ - int i; - - if (list1 == NULL || list2 == NULL) { - return (list1 == list2); - } - - for (i=0;list1[i] && list2[i];i++) { - if (strcmp(list1[i], list2[i]) != 0) { - return false; - } - } - if (list1[i] || list2[i]) { - return false; - } - return true; -} - - -/** - add an entry to a string list -*/ -_PUBLIC_ const char **str_list_add(const char **list, const char *s) -{ - size_t len = str_list_length(list); - const char **ret; - - ret = talloc_realloc(NULL, list, const char *, len+2); - if (ret == NULL) return NULL; - - ret[len] = talloc_strdup(ret, s); - if (ret[len] == NULL) return NULL; - - ret[len+1] = NULL; - - return ret; -} - -/** - remove an entry from a string list -*/ -_PUBLIC_ void str_list_remove(const char **list, const char *s) -{ - int i; - - for (i=0;list[i];i++) { - if (strcmp(list[i], s) == 0) break; - } - if (!list[i]) return; - - for (;list[i];i++) { - list[i] = list[i+1]; - } -} - - -/** - return true if a string is in a list -*/ -_PUBLIC_ bool str_list_check(const char **list, const char *s) -{ - int i; - - for (i=0;list[i];i++) { - if (strcmp(list[i], s) == 0) return true; - } - return false; -} - -/** - return true if a string is in a list, case insensitively -*/ -_PUBLIC_ bool str_list_check_ci(const char **list, const char *s) -{ - int i; - - for (i=0;list[i];i++) { - if (strcasecmp(list[i], s) == 0) return true; - } - return false; -} - - diff --git a/source4/lib/util/util_tdb.c b/source4/lib/util/util_tdb.c deleted file mode 100644 index e89085a31b..0000000000 --- a/source4/lib/util/util_tdb.c +++ /dev/null @@ -1,546 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - tdb utility functions - - Copyright (C) Andrew Tridgell 1992-2006 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" -#include "../tdb/include/tdb.h" -#include "pstring.h" -#include "lib/util/util_tdb.h" - -/* these are little tdb utility functions that are meant to make - dealing with a tdb database a little less cumbersome in Samba */ - -/*************************************************************** - Make a TDB_DATA and keep the const warning in one place -****************************************************************/ - -static TDB_DATA make_tdb_data(const char *dptr, size_t dsize) -{ - TDB_DATA ret; - ret.dptr = discard_const_p(unsigned char, dptr); - ret.dsize = dsize; - return ret; -} - -/**************************************************************************** - Lock a chain by string. Return -1 if lock failed. -****************************************************************************/ - -int tdb_lock_bystring(struct tdb_context *tdb, const char *keyval) -{ - TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); - - return tdb_chainlock(tdb, key); -} - -/**************************************************************************** - Unlock a chain by string. -****************************************************************************/ - -void tdb_unlock_bystring(struct tdb_context *tdb, const char *keyval) -{ - TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); - - tdb_chainunlock(tdb, key); -} - -/**************************************************************************** - Read lock a chain by string. Return -1 if lock failed. -****************************************************************************/ - -int tdb_read_lock_bystring(struct tdb_context *tdb, const char *keyval) -{ - TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); - - return tdb_chainlock_read(tdb, key); -} - -/**************************************************************************** - Read unlock a chain by string. -****************************************************************************/ - -void tdb_read_unlock_bystring(struct tdb_context *tdb, const char *keyval) -{ - TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1); - - tdb_chainunlock_read(tdb, key); -} - - -/**************************************************************************** - Fetch a int32_t value by a arbitrary blob key, return -1 if not found. - Output is int32_t in native byte order. -****************************************************************************/ - -int32_t tdb_fetch_int32_byblob(struct tdb_context *tdb, const char *keyval, size_t len) -{ - TDB_DATA key = make_tdb_data(keyval, len); - TDB_DATA data; - int32_t ret; - - data = tdb_fetch(tdb, key); - if (!data.dptr || data.dsize != sizeof(int32_t)) { - SAFE_FREE(data.dptr); - return -1; - } - - ret = IVAL(data.dptr,0); - SAFE_FREE(data.dptr); - return ret; -} - -/**************************************************************************** - Fetch a int32_t value by string key, return -1 if not found. - Output is int32_t in native byte order. -****************************************************************************/ - -int32_t tdb_fetch_int32(struct tdb_context *tdb, const char *keystr) -{ - return tdb_fetch_int32_byblob(tdb, keystr, strlen(keystr) + 1); -} - -/**************************************************************************** - Store a int32_t value by an arbitary blob key, return 0 on success, -1 on failure. - Input is int32_t in native byte order. Output in tdb is in little-endian. -****************************************************************************/ - -int tdb_store_int32_byblob(struct tdb_context *tdb, const char *keystr, size_t len, int32_t v) -{ - TDB_DATA key = make_tdb_data(keystr, len); - TDB_DATA data; - int32_t v_store; - - SIVAL(&v_store,0,v); - data.dptr = (unsigned char *)&v_store; - data.dsize = sizeof(int32_t); - - return tdb_store(tdb, key, data, TDB_REPLACE); -} - -/**************************************************************************** - Store a int32_t value by string key, return 0 on success, -1 on failure. - Input is int32_t in native byte order. Output in tdb is in little-endian. -****************************************************************************/ - -int tdb_store_int32(struct tdb_context *tdb, const char *keystr, int32_t v) -{ - return tdb_store_int32_byblob(tdb, keystr, strlen(keystr) + 1, v); -} - -/**************************************************************************** - Fetch a uint32_t value by a arbitrary blob key, return -1 if not found. - Output is uint32_t in native byte order. -****************************************************************************/ - -bool tdb_fetch_uint32_byblob(struct tdb_context *tdb, const char *keyval, size_t len, uint32_t *value) -{ - TDB_DATA key = make_tdb_data(keyval, len); - TDB_DATA data; - - data = tdb_fetch(tdb, key); - if (!data.dptr || data.dsize != sizeof(uint32_t)) { - SAFE_FREE(data.dptr); - return false; - } - - *value = IVAL(data.dptr,0); - SAFE_FREE(data.dptr); - return true; -} - -/**************************************************************************** - Fetch a uint32_t value by string key, return -1 if not found. - Output is uint32_t in native byte order. -****************************************************************************/ - -bool tdb_fetch_uint32(struct tdb_context *tdb, const char *keystr, uint32_t *value) -{ - return tdb_fetch_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value); -} - -/**************************************************************************** - Store a uint32_t value by an arbitary blob key, return 0 on success, -1 on failure. - Input is uint32_t in native byte order. Output in tdb is in little-endian. -****************************************************************************/ - -bool tdb_store_uint32_byblob(struct tdb_context *tdb, const char *keystr, size_t len, uint32_t value) -{ - TDB_DATA key = make_tdb_data(keystr, len); - TDB_DATA data; - uint32_t v_store; - bool ret = true; - - SIVAL(&v_store, 0, value); - data.dptr = (unsigned char *)&v_store; - data.dsize = sizeof(uint32_t); - - if (tdb_store(tdb, key, data, TDB_REPLACE) == -1) - ret = false; - - return ret; -} - -/**************************************************************************** - Store a uint32_t value by string key, return 0 on success, -1 on failure. - Input is uint32_t in native byte order. Output in tdb is in little-endian. -****************************************************************************/ - -bool tdb_store_uint32(struct tdb_context *tdb, const char *keystr, uint32_t value) -{ - return tdb_store_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value); -} -/**************************************************************************** - Store a buffer by a null terminated string key. Return 0 on success, -1 - on failure. -****************************************************************************/ - -int tdb_store_bystring(struct tdb_context *tdb, const char *keystr, TDB_DATA data, int flags) -{ - TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); - - return tdb_store(tdb, key, data, flags); -} - -/**************************************************************************** - Fetch a buffer using a null terminated string key. Don't forget to call - free() on the result dptr. -****************************************************************************/ - -TDB_DATA tdb_fetch_bystring(struct tdb_context *tdb, const char *keystr) -{ - TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); - - return tdb_fetch(tdb, key); -} - -/**************************************************************************** - Delete an entry using a null terminated string key. -****************************************************************************/ - -int tdb_delete_bystring(struct tdb_context *tdb, const char *keystr) -{ - TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); - - return tdb_delete(tdb, key); -} - -/**************************************************************************** - Atomic integer change. Returns old value. To create, set initial value in *oldval. -****************************************************************************/ - -int32_t tdb_change_int32_atomic(struct tdb_context *tdb, const char *keystr, int32_t *oldval, int32_t change_val) -{ - int32_t val; - int32_t ret = -1; - - if (tdb_lock_bystring(tdb, keystr) == -1) - return -1; - - if ((val = tdb_fetch_int32(tdb, keystr)) == -1) { - /* The lookup failed */ - if (tdb_error(tdb) != TDB_ERR_NOEXIST) { - /* but not because it didn't exist */ - goto err_out; - } - - /* Start with 'old' value */ - val = *oldval; - - } else { - /* It worked, set return value (oldval) to tdb data */ - *oldval = val; - } - - /* Increment value for storage and return next time */ - val += change_val; - - if (tdb_store_int32(tdb, keystr, val) == -1) - goto err_out; - - ret = 0; - - err_out: - - tdb_unlock_bystring(tdb, keystr); - return ret; -} - -/**************************************************************************** - Atomic unsigned integer change. Returns old value. To create, set initial value in *oldval. -****************************************************************************/ - -bool tdb_change_uint32_atomic(struct tdb_context *tdb, const char *keystr, uint32_t *oldval, uint32_t change_val) -{ - uint32_t val; - bool ret = false; - - if (tdb_lock_bystring(tdb, keystr) == -1) - return false; - - if (!tdb_fetch_uint32(tdb, keystr, &val)) { - /* It failed */ - if (tdb_error(tdb) != TDB_ERR_NOEXIST) { - /* and not because it didn't exist */ - goto err_out; - } - - /* Start with 'old' value */ - val = *oldval; - - } else { - /* it worked, set return value (oldval) to tdb data */ - *oldval = val; - - } - - /* get a new value to store */ - val += change_val; - - if (!tdb_store_uint32(tdb, keystr, val)) - goto err_out; - - ret = true; - - err_out: - - tdb_unlock_bystring(tdb, keystr); - return ret; -} - -/**************************************************************************** - Allow tdb_delete to be used as a tdb_traversal_fn. -****************************************************************************/ - -int tdb_traverse_delete_fn(struct tdb_context *the_tdb, TDB_DATA key, TDB_DATA dbuf, - void *state) -{ - return tdb_delete(the_tdb, key); -} - - - -/**************************************************************************** - Useful pair of routines for packing/unpacking data consisting of - integers and strings. -****************************************************************************/ - -size_t tdb_pack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) -{ - va_list ap; - uint8_t bt; - uint16_t w; - uint32_t d; - int i; - void *p; - int len; - char *s; - char c; - char *buf0 = buf; - const char *fmt0 = fmt; - int bufsize0 = bufsize; - tdb_log_func log_fn = tdb_log_fn(tdb); - - va_start(ap, fmt); - - while (*fmt) { - switch ((c = *fmt++)) { - case 'b': /* unsigned 8-bit integer */ - len = 1; - bt = (uint8_t)va_arg(ap, int); - if (bufsize && bufsize >= len) - SSVAL(buf, 0, bt); - break; - case 'w': /* unsigned 16-bit integer */ - len = 2; - w = (uint16_t)va_arg(ap, int); - if (bufsize && bufsize >= len) - SSVAL(buf, 0, w); - break; - case 'd': /* signed 32-bit integer (standard int in most systems) */ - len = 4; - d = va_arg(ap, uint32_t); - if (bufsize && bufsize >= len) - SIVAL(buf, 0, d); - break; - case 'p': /* pointer */ - len = 4; - p = va_arg(ap, void *); - d = p?1:0; - if (bufsize && bufsize >= len) - SIVAL(buf, 0, d); - break; - case 'P': /* null-terminated string */ - s = va_arg(ap,char *); - w = strlen(s); - len = w + 1; - if (bufsize && bufsize >= len) - memcpy(buf, s, len); - break; - case 'f': /* null-terminated string */ - s = va_arg(ap,char *); - w = strlen(s); - len = w + 1; - if (bufsize && bufsize >= len) - memcpy(buf, s, len); - break; - case 'B': /* fixed-length string */ - i = va_arg(ap, int); - s = va_arg(ap, char *); - len = 4+i; - if (bufsize && bufsize >= len) { - SIVAL(buf, 0, i); - memcpy(buf+4, s, i); - } - break; - default: - log_fn(tdb, 0,"Unknown tdb_pack format %c in %s\n", - c, fmt); - len = 0; - break; - } - - buf += len; - if (bufsize) - bufsize -= len; - if (bufsize < 0) - bufsize = 0; - } - - va_end(ap); - - log_fn(tdb, 18,"tdb_pack(%s, %d) -> %d\n", - fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)); - - return PTR_DIFF(buf, buf0); -} - -/**************************************************************************** - Useful pair of routines for packing/unpacking data consisting of - integers and strings. -****************************************************************************/ - -int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...) -{ - va_list ap; - uint8_t *bt; - uint16_t *w; - uint32_t *d; - int len; - int *i; - void **p; - char *s, **b, **ps; - char c; - char *buf0 = buf; - const char *fmt0 = fmt; - int bufsize0 = bufsize; - tdb_log_func log_fn = tdb_log_fn(tdb); - - va_start(ap, fmt); - - while (*fmt) { - switch ((c=*fmt++)) { - case 'b': - len = 1; - bt = va_arg(ap, uint8_t *); - if (bufsize < len) - goto no_space; - *bt = SVAL(buf, 0); - break; - case 'w': - len = 2; - w = va_arg(ap, uint16_t *); - if (bufsize < len) - goto no_space; - *w = SVAL(buf, 0); - break; - case 'd': - len = 4; - d = va_arg(ap, uint32_t *); - if (bufsize < len) - goto no_space; - *d = IVAL(buf, 0); - break; - case 'p': - len = 4; - p = va_arg(ap, void **); - if (bufsize < len) - goto no_space; - - /* - * This isn't a real pointer - only a token (1 or 0) - * to mark the fact a pointer is present. - */ - - *p = (void *)(IVAL(buf, 0) ? (void *)1 : NULL); - break; - case 'P': - /* Return a malloc'ed string. */ - ps = va_arg(ap,char ** ); - len = strlen((const char *)buf) + 1; - *ps = strdup((const char *)buf); - break; - case 'f': - s = va_arg(ap,char *); - len = strlen(buf) + 1; - if (bufsize < len || len > sizeof(fstring)) - goto no_space; - memcpy(s, buf, len); - break; - case 'B': - i = va_arg(ap, int *); - b = va_arg(ap, char **); - len = 4; - if (bufsize < len) - goto no_space; - *i = IVAL(buf, 0); - if (! *i) { - *b = NULL; - break; - } - len += *i; - if (bufsize < len) - goto no_space; - *b = (char *)malloc(*i); - if (! *b) - goto no_space; - memcpy(*b, buf+4, *i); - break; - default: - log_fn(tdb, 0, "Unknown tdb_unpack format %c in %s\n", - c, fmt); - - len = 0; - break; - } - - buf += len; - bufsize -= len; - } - - va_end(ap); - - log_fn(tdb, 18, "tdb_unpack(%s, %d) -> %d\n", - fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)); - - return PTR_DIFF(buf, buf0); - - no_space: - return -1; -} diff --git a/source4/lib/util/wrap_xattr.c b/source4/lib/util/wrap_xattr.c deleted file mode 100644 index 955f39a7eb..0000000000 --- a/source4/lib/util/wrap_xattr.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - POSIX NTVFS backend - xattr support using filesystem xattrs - - Copyright (C) Andrew Tridgell 2004 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" -#include "system/filesys.h" -#include "lib/util/wrap_xattr.h" - -#if defined(HAVE_XATTR_SUPPORT) && defined(XATTR_ADDITIONAL_OPTIONS) -static ssize_t _wrap_darwin_fgetxattr(int fd, const char *name, void *value, size_t size) -{ - return fgetxattr(fd, name, value, size, 0, 0); -} -static ssize_t _wrap_darwin_getxattr(const char *path, const char *name, void *value, size_t size) -{ - return getxattr(path, name, value, size, 0, 0); -} -static int _wrap_darwin_fsetxattr(int fd, const char *name, void *value, size_t size, int flags) -{ - return fsetxattr(fd, name, value, size, 0, flags); -} -static int _wrap_darwin_setxattr(const char *path, const char *name, void *value, size_t size, int flags) -{ - return setxattr(path, name, value, size, 0, flags); -} -static int _wrap_darwin_fremovexattr(int fd, const char *name) -{ - return fremovexattr(fd, name, 0); -} -static int _wrap_darwin_removexattr(const char *path, const char *name) -{ - return removexattr(path, name, 0); -} -#define fgetxattr _wrap_darwin_fgetxattr -#define getxattr _wrap_darwin_getxattr -#define fsetxattr _wrap_darwin_fsetxattr -#define setxattr _wrap_darwin_setxattr -#define fremovexattr _wrap_darwin_fremovexattr -#define removexattr _wrap_darwin_removexattr -#elif !defined(HAVE_XATTR_SUPPORT) -static ssize_t _none_fgetxattr(int fd, const char *name, void *value, size_t size) -{ - errno = ENOSYS; - return -1; -} -static ssize_t _none_getxattr(const char *path, const char *name, void *value, size_t size) -{ - errno = ENOSYS; - return -1; -} -static int _none_fsetxattr(int fd, const char *name, void *value, size_t size, int flags) -{ - errno = ENOSYS; - return -1; -} -static int _none_setxattr(const char *path, const char *name, void *value, size_t size, int flags) -{ - errno = ENOSYS; - return -1; -} -static int _none_fremovexattr(int fd, const char *name) -{ - errno = ENOSYS; - return -1; -} -static int _none_removexattr(const char *path, const char *name) -{ - errno = ENOSYS; - return -1; -} -#define fgetxattr _none_fgetxattr -#define getxattr _none_getxattr -#define fsetxattr _none_fsetxattr -#define setxattr _none_setxattr -#define fremovexattr _none_fremovexattr -#define removexattr _none_removexattr -#endif - -_PUBLIC_ ssize_t wrap_fgetxattr(int fd, const char *name, void *value, size_t size) -{ - return fgetxattr(fd, name, value, size); -} -_PUBLIC_ ssize_t wrap_getxattr(const char *path, const char *name, void *value, size_t size) -{ - return getxattr(path, name, value, size); -} -_PUBLIC_ int wrap_fsetxattr(int fd, const char *name, void *value, size_t size, int flags) -{ - return fsetxattr(fd, name, value, size, flags); -} -_PUBLIC_ int wrap_setxattr(const char *path, const char *name, void *value, size_t size, int flags) -{ - return setxattr(path, name, value, size, flags); -} -_PUBLIC_ int wrap_fremovexattr(int fd, const char *name) -{ - return fremovexattr(fd, name); -} -_PUBLIC_ int wrap_removexattr(const char *path, const char *name) -{ - return removexattr(path, name); -} - diff --git a/source4/lib/util/wrap_xattr.h b/source4/lib/util/wrap_xattr.h deleted file mode 100644 index 64b28d250c..0000000000 --- a/source4/lib/util/wrap_xattr.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __LIB_UTIL_WRAP_XATTR_H__ -#define __LIB_UTIL_WRAP_XATTR_H__ - -ssize_t wrap_fgetxattr(int fd, const char *name, void *value, size_t size); -ssize_t wrap_getxattr(const char *path, const char *name, void *value, size_t size); -int wrap_fsetxattr(int fd, const char *name, void *value, size_t size, int flags); -int wrap_setxattr(const char *path, const char *name, void *value, size_t size, int flags); -int wrap_fremovexattr(int fd, const char *name); -int wrap_removexattr(const char *path, const char *name); - -#endif /* __LIB_UTIL_WRAP_XATTR_H__ */ - diff --git a/source4/lib/util/xattr.m4 b/source4/lib/util/xattr.m4 deleted file mode 100644 index 497809a47a..0000000000 --- a/source4/lib/util/xattr.m4 +++ /dev/null @@ -1,32 +0,0 @@ -dnl ############################################ -dnl use flistxattr as the key function for having -dnl sufficient xattr support for posix xattr backend -AC_CHECK_HEADERS(sys/attributes.h attr/xattr.h sys/xattr.h) -AC_SEARCH_LIBS_EXT(flistxattr, [attr], XATTR_LIBS) -AC_CHECK_FUNC_EXT(flistxattr, $XATTR_LIBS) -SMB_EXT_LIB(XATTR,[${XATTR_LIBS}],[${XATTR_CFLAGS}],[${XATTR_CPPFLAGS}],[${XATTR_LDFLAGS}]) -if test x"$ac_cv_func_ext_flistxattr" = x"yes"; then - AC_CACHE_CHECK([whether xattr interface takes additional options], smb_attr_cv_xattr_add_opt, - [old_LIBS=$LIBS - LIBS="$LIBS $XATTRLIBS" - AC_TRY_COMPILE([ - #include - #if HAVE_ATTR_XATTR_H - #include - #elif HAVE_SYS_XATTR_H - #include - #endif - #ifndef NULL - #define NULL ((void *)0) - #endif - ],[ - getxattr(NULL, NULL, NULL, 0, 0, 0); - ],smb_attr_cv_xattr_add_opt=yes,smb_attr_cv_xattr_add_opt=no) - LIBS=$old_LIBS]) - if test x"$smb_attr_cv_xattr_add_opt" = x"yes"; then - AC_DEFINE(XATTR_ADDITIONAL_OPTIONS, 1, [xattr functions have additional options]) - fi - AC_DEFINE(HAVE_XATTR_SUPPORT,1,[Whether we have xattr support]) - SMB_ENABLE(XATTR,YES) -fi - diff --git a/source4/lib/util/xfile.c b/source4/lib/util/xfile.c deleted file mode 100644 index a016031a77..0000000000 --- a/source4/lib/util/xfile.c +++ /dev/null @@ -1,389 +0,0 @@ -/* - Unix SMB/CIFS implementation. - stdio replacement - Copyright (C) Andrew Tridgell 2001 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file - * @brief scalable FILE replacement - */ - -/* - stdio is very convenient, but on some systems the file descriptor - in FILE* is 8 bits, so it fails when more than 255 files are open. - - XFILE replaces stdio. It is less efficient, but at least it works - when you have lots of files open - - The main restriction on XFILE is that it doesn't support seeking, - and doesn't support O_RDWR. That keeps the code simple. -*/ - -#include "includes.h" -#include "system/filesys.h" - -#define XBUFSIZE BUFSIZ - -static XFILE _x_stdin = { 0, NULL, NULL, XBUFSIZE, 0, O_RDONLY, X_IOFBF, 0 }; -static XFILE _x_stdout = { 1, NULL, NULL, XBUFSIZE, 0, O_WRONLY, X_IOLBF, 0 }; -static XFILE _x_stderr = { 2, NULL, NULL, 0, 0, O_WRONLY, X_IONBF, 0 }; - -XFILE *x_stdin = &_x_stdin; -XFILE *x_stdout = &_x_stdout; -XFILE *x_stderr = &_x_stderr; - -#define X_FLAG_EOF 1 -#define X_FLAG_ERROR 2 -#define X_FLAG_EINVAL 3 - -/** simulate setvbuf() */ -int x_setvbuf(XFILE *f, char *buf, int mode, size_t size) -{ - x_fflush(f); - if (f->bufused) return -1; - - /* on files being read full buffering is the only option */ - if ((f->open_flags & O_ACCMODE) == O_RDONLY) { - mode = X_IOFBF; - } - - /* destroy any earlier buffer */ - SAFE_FREE(f->buf); - f->buf = 0; - f->bufsize = 0; - f->next = NULL; - f->bufused = 0; - f->buftype = mode; - - if (f->buftype == X_IONBF) return 0; - - /* if buffering then we need some size */ - if (size == 0) size = XBUFSIZE; - - f->bufsize = size; - f->bufused = 0; - - return 0; -} - -/* allocate the buffer */ -static int x_allocate_buffer(XFILE *f) -{ - if (f->buf) return 1; - if (f->bufsize == 0) return 0; - f->buf = (char *)malloc(f->bufsize); - if (!f->buf) return 0; - f->next = f->buf; - return 1; -} - - -/** this looks more like open() than fopen(), but that is quite deliberate. - I want programmers to *think* about O_EXCL, O_CREAT etc not just - get them magically added -*/ -XFILE *x_fopen(const char *fname, int flags, mode_t mode) -{ - XFILE *ret; - - ret = malloc_p(XFILE); - if (!ret) return NULL; - - memset(ret, 0, sizeof(XFILE)); - - if ((flags & O_ACCMODE) == O_RDWR) { - /* we don't support RDWR in XFILE - use file - descriptors instead */ - errno = EINVAL; - return NULL; - } - - ret->open_flags = flags; - - ret->fd = open(fname, flags, mode); - if (ret->fd == -1) { - SAFE_FREE(ret); - return NULL; - } - - x_setvbuf(ret, NULL, X_IOFBF, XBUFSIZE); - - return ret; -} - -/** simulate fclose() */ -int x_fclose(XFILE *f) -{ - int ret; - - /* make sure we flush any buffered data */ - x_fflush(f); - - ret = close(f->fd); - f->fd = -1; - if (f->buf) { - /* make sure data can't leak into a later malloc */ - memset(f->buf, 0, f->bufsize); - SAFE_FREE(f->buf); - } - /* check the file descriptor given to the function is NOT one of the static - * descriptor of this libreary or we will free unallocated memory - * --sss */ - if (f != x_stdin && f != x_stdout && f != x_stderr) { - SAFE_FREE(f); - } - return ret; -} - -/** simulate fwrite() */ -size_t x_fwrite(const void *p, size_t size, size_t nmemb, XFILE *f) -{ - ssize_t ret; - size_t total=0; - - /* we might be writing unbuffered */ - if (f->buftype == X_IONBF || - (!f->buf && !x_allocate_buffer(f))) { - ret = write(f->fd, p, size*nmemb); - if (ret == -1) return -1; - return ret/size; - } - - - while (total < size*nmemb) { - size_t n = f->bufsize - f->bufused; - n = MIN(n, (size*nmemb)-total); - - if (n == 0) { - /* it's full, flush it */ - x_fflush(f); - continue; - } - - memcpy(f->buf + f->bufused, total+(const char *)p, n); - f->bufused += n; - total += n; - } - - /* when line buffered we need to flush at the last linefeed. This can - flush a bit more than necessary, but that is harmless */ - if (f->buftype == X_IOLBF && f->bufused) { - int i; - for (i=(size*nmemb)-1; i>=0; i--) { - if (*(i+(const char *)p) == '\n') { - x_fflush(f); - break; - } - } - } - - return total/size; -} - -/** thank goodness for asprintf() */ - int x_vfprintf(XFILE *f, const char *format, va_list ap) -{ - char *p; - int len, ret; - va_list ap2; - - va_copy(ap2, ap); - len = vasprintf(&p, format, ap2); - va_end(ap2); - if (len <= 0) return len; - ret = x_fwrite(p, 1, len, f); - SAFE_FREE(p); - return ret; -} - - int x_fprintf(XFILE *f, const char *format, ...) -{ - va_list ap; - int ret; - - va_start(ap, format); - ret = x_vfprintf(f, format, ap); - va_end(ap); - return ret; -} - -/* at least fileno() is simple! */ -int x_fileno(XFILE *f) -{ - return f->fd; -} - -/** simulate fflush() */ -int x_fflush(XFILE *f) -{ - int ret; - - if (f->flags & X_FLAG_ERROR) return -1; - - if ((f->open_flags & O_ACCMODE) != O_WRONLY) { - errno = EINVAL; - return -1; - } - - if (f->bufused == 0) return 0; - - ret = write(f->fd, f->buf, f->bufused); - if (ret == -1) return -1; - - f->bufused -= ret; - if (f->bufused > 0) { - f->flags |= X_FLAG_ERROR; - memmove(f->buf, ret + (char *)f->buf, f->bufused); - return -1; - } - - return 0; -} - -/** simulate setbuffer() */ -void x_setbuffer(XFILE *f, char *buf, size_t size) -{ - x_setvbuf(f, buf, buf?X_IOFBF:X_IONBF, size); -} - -/** simulate setbuf() */ -void x_setbuf(XFILE *f, char *buf) -{ - x_setvbuf(f, buf, buf?X_IOFBF:X_IONBF, XBUFSIZE); -} - -/** simulate setlinebuf() */ -void x_setlinebuf(XFILE *f) -{ - x_setvbuf(f, NULL, X_IOLBF, 0); -} - - -/** simulate feof() */ -int x_feof(XFILE *f) -{ - if (f->flags & X_FLAG_EOF) return 1; - return 0; -} - -/** simulate ferror() */ -int x_ferror(XFILE *f) -{ - if (f->flags & X_FLAG_ERROR) return 1; - return 0; -} - -/* fill the read buffer */ -static void x_fillbuf(XFILE *f) -{ - int n; - - if (f->bufused) return; - - if (!f->buf && !x_allocate_buffer(f)) return; - - n = read(f->fd, f->buf, f->bufsize); - if (n <= 0) return; - f->bufused = n; - f->next = f->buf; -} - -/** simulate fgetc() */ -int x_fgetc(XFILE *f) -{ - int ret; - - if (f->flags & (X_FLAG_EOF | X_FLAG_ERROR)) return EOF; - - if (f->bufused == 0) x_fillbuf(f); - - if (f->bufused == 0) { - f->flags |= X_FLAG_EOF; - return EOF; - } - - ret = *(uint8_t *)(f->next); - f->next++; - f->bufused--; - return ret; -} - -/** simulate fread */ -size_t x_fread(void *p, size_t size, size_t nmemb, XFILE *f) -{ - size_t total = 0; - while (total < size*nmemb) { - int c = x_fgetc(f); - if (c == EOF) break; - (total+(char *)p)[0] = (char)c; - total++; - } - return total/size; -} - -/** simulate fgets() */ -char *x_fgets(char *s, int size, XFILE *stream) -{ - char *s0 = s; - int l = size; - while (l>1) { - int c = x_fgetc(stream); - if (c == EOF) break; - *s++ = (char)c; - l--; - if (c == '\n') break; - } - if (l==size || x_ferror(stream)) { - return 0; - } - *s = 0; - return s0; -} - -/** - * trivial seek, works only for SEEK_SET and SEEK_END if SEEK_CUR is - * set then an error is returned */ -off_t x_tseek(XFILE *f, off_t offset, int whence) -{ - if (f->flags & X_FLAG_ERROR) - return -1; - - /* only SEEK_SET and SEEK_END are supported */ - /* SEEK_CUR needs internal offset counter */ - if (whence != SEEK_SET && whence != SEEK_END) { - f->flags |= X_FLAG_EINVAL; - errno = EINVAL; - return -1; - } - - /* empty the buffer */ - switch (f->open_flags & O_ACCMODE) { - case O_RDONLY: - f->bufused = 0; - break; - case O_WRONLY: - if (x_fflush(f) != 0) - return -1; - break; - default: - errno = EINVAL; - return -1; - } - - f->flags &= ~X_FLAG_EOF; - return lseek(f->fd, offset, whence); -} diff --git a/source4/lib/util/xfile.h b/source4/lib/util/xfile.h deleted file mode 100644 index 2cc369d8d8..0000000000 --- a/source4/lib/util/xfile.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - Unix SMB/CIFS implementation. - stdio replacement - Copyright (C) Andrew Tridgell 2001 - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _XFILE_H_ -#define _XFILE_H_ -/* - see xfile.c for explanations -*/ - -typedef struct { - int fd; - char *buf; - char *next; - int bufsize; - int bufused; - int open_flags; - int buftype; - int flags; -} XFILE; - -extern XFILE *x_stdin, *x_stdout, *x_stderr; - -/* buffering type */ -#define X_IOFBF 0 -#define X_IOLBF 1 -#define X_IONBF 2 - -#define x_getc(f) x_fgetc(f) - -int x_vfprintf(XFILE *f, const char *format, va_list ap) PRINTF_ATTRIBUTE(2, 0); -int x_fprintf(XFILE *f, const char *format, ...) PRINTF_ATTRIBUTE(2, 3); - -/** simulate setvbuf() */ -int x_setvbuf(XFILE *f, char *buf, int mode, size_t size); - -/** this looks more like open() than fopen(), but that is quite deliberate. - I want programmers to *think* about O_EXCL, O_CREAT etc not just - get them magically added -*/ -XFILE *x_fopen(const char *fname, int flags, mode_t mode); - -/** simulate fclose() */ -int x_fclose(XFILE *f); - -/** simulate fwrite() */ -size_t x_fwrite(const void *p, size_t size, size_t nmemb, XFILE *f); - -/** thank goodness for asprintf() */ -int x_fileno(XFILE *f); - -/** simulate fflush() */ -int x_fflush(XFILE *f); - -/** simulate setbuffer() */ -void x_setbuffer(XFILE *f, char *buf, size_t size); - -/** simulate setbuf() */ -void x_setbuf(XFILE *f, char *buf); - -/** simulate setlinebuf() */ -void x_setlinebuf(XFILE *f); - -/** simulate feof() */ -int x_feof(XFILE *f); - -/** simulate ferror() */ -int x_ferror(XFILE *f); - -/** simulate fgetc() */ -int x_fgetc(XFILE *f); - -/** simulate fread */ -size_t x_fread(void *p, size_t size, size_t nmemb, XFILE *f); - -/** simulate fgets() */ -char *x_fgets(char *s, int size, XFILE *stream) ; - -/** - * trivial seek, works only for SEEK_SET and SEEK_END if SEEK_CUR is - * set then an error is returned */ -off_t x_tseek(XFILE *f, off_t offset, int whence); - -#endif /* _XFILE_H_ */ diff --git a/source4/librpc/ndr/libndr.h b/source4/librpc/ndr/libndr.h index 3f4de7801a..1be1a54045 100644 --- a/source4/librpc/ndr/libndr.h +++ b/source4/librpc/ndr/libndr.h @@ -26,7 +26,7 @@ #define __LIBNDR_H__ #include -#include "lib/util/util.h" /* for discard_const */ +#include "../lib/util/util.h" /* for discard_const */ #include #include "lib/charset/charset.h" diff --git a/source4/librpc/rpc/dcerpc.h b/source4/librpc/rpc/dcerpc.h index 2b38c65669..482e803a35 100644 --- a/source4/librpc/rpc/dcerpc.h +++ b/source4/librpc/rpc/dcerpc.h @@ -27,7 +27,7 @@ #ifndef __DCERPC_H__ #define __DCERPC_H__ -#include "lib/util/data_blob.h" +#include "../lib/util/data_blob.h" #include "librpc/gen_ndr/dcerpc.h" #include "librpc/ndr/libndr.h" diff --git a/source4/main.mk b/source4/main.mk index 368dce9f59..8ce86b91ca 100644 --- a/source4/main.mk +++ b/source4/main.mk @@ -19,7 +19,7 @@ mkinclude lib/cmdline/config.mk mkinclude ../lib/socket_wrapper/config.mk mkinclude ../lib/nss_wrapper/config.mk mkinclude lib/stream/config.mk -mkinclude lib/util/config.mk +mkinclude ../lib/util/config.mk mkinclude lib/tdr/config.mk mkinclude lib/dbwrap/config.mk mkinclude ../lib/crypto/config.mk diff --git a/source4/torture/local/config.mk b/source4/torture/local/config.mk index 4cd9f6c865..1f87912e8b 100644 --- a/source4/torture/local/config.mk +++ b/source4/torture/local/config.mk @@ -28,14 +28,14 @@ TORTURE_LOCAL_OBJ_FILES = \ $(torturesrcdir)/../lib/messaging/tests/messaging.o \ $(torturesrcdir)/../lib/messaging/tests/irpc.o \ $(torturesrcdir)/../librpc/tests/binding_string.o \ - $(torturesrcdir)/../lib/util/tests/idtree.o \ + $(torturesrcdir)/../../lib/util/tests/idtree.o \ $(torturesrcdir)/../lib/socket/testsuite.o \ $(torturesrcdir)/../../lib/socket_wrapper/testsuite.o \ $(torturesrcdir)/../libcli/resolve/testsuite.o \ - $(torturesrcdir)/../lib/util/tests/strlist.o \ - $(torturesrcdir)/../lib/util/tests/str.o \ - $(torturesrcdir)/../lib/util/tests/file.o \ - $(torturesrcdir)/../lib/util/tests/genrand.o \ + $(torturesrcdir)/../../lib/util/tests/strlist.o \ + $(torturesrcdir)/../../lib/util/tests/str.o \ + $(torturesrcdir)/../../lib/util/tests/file.o \ + $(torturesrcdir)/../../lib/util/tests/genrand.o \ $(torturesrcdir)/../../lib/compression/testsuite.o \ $(torturesrcdir)/../lib/charset/tests/charset.o \ $(torturesrcdir)/../libcli/security/tests/sddl.o \ diff --git a/source4/utils/getntacl.c b/source4/utils/getntacl.c index 132d689dcb..f26c87bd85 100644 --- a/source4/utils/getntacl.c +++ b/source4/utils/getntacl.c @@ -22,7 +22,7 @@ #include "includes.h" #include "system/filesys.h" #include "librpc/gen_ndr/ndr_xattr.h" -#include "lib/util/wrap_xattr.h" +#include "../lib/util/wrap_xattr.h" #include "param/param.h" static void ntacl_print_debug_helper(struct ndr_print *ndr, const char *format, ...) PRINTF_ATTRIBUTE(2,3); -- cgit