From: Lennart Poettering Date: Mon, 3 Oct 2005 20:46:05 +0000 (+0000) Subject: * Use a recursive mutex for locking DNSServiceRef X-Git-Url: https://git.meshlink.io/?a=commitdiff_plain;h=f7ece52f5ba3633abf2515dcbc467ad6b80a447b;p=catta * Use a recursive mutex for locking DNSServiceRef * Implement TXT* function * Implement txt-test.c * Print a warning to STDERR once when the compat layer is used * Print a warning to STDERR when a non-implemented function is called * Add Makefile support to compile Apple's dns-sd.c with our compat library (but don't include that file ) git-svn-id: file:///home/lennart/svn/public/avahi/trunk@680 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe --- diff --git a/compat-bonjour/Makefile.am b/compat-bonjour/Makefile.am index 78decb7..37eb1df 100644 --- a/compat-bonjour/Makefile.am +++ b/compat-bonjour/Makefile.am @@ -24,17 +24,36 @@ AM_CFLAGS+='-DDEBUG_TRAP=__asm__("int $$3")' avahi_compat_bonjourdir=$(includedir)/avahi-compat-bonjour -avahi_compat_bonjour_HEADERS = \ - dns_sd.h +avahi_compat_bonjour_HEADERS = dns_sd.h +lib_LTLIBRARIES = libavahi-compat-bonjour.la -lib_LTLIBRARIES = \ - libavahi-compat-bonjour.la +noinst_PROGRAMS = txt-test libavahi_compat_bonjour_la_SOURCES = \ - unsupported.c \ + dns_sd.h \ compat.c \ - dns_sd.h - + txt.c \ + unsupported.c \ + warn.c warn.h libavahi_compat_bonjour_la_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) -libavahi_compat_bonjour_la_LDFLAGS = $(AM_LDFLAGS) -export-dynamic -version-info $(LIBAVAHI_COMPAT_BONJOUR_VERSION_INFO) $(PTHREAD_LIBS) +libavahi_compat_bonjour_la_LDFLAGS = $(AM_LDFLAGS) -export-dynamic -version-info $(LIBAVAHI_COMPAT_BONJOUR_VERSION_INFO) $(PTHREAD_LIBS) ../avahi-common/libavahi-common.la ../avahi-client/libavahi-client.la + +txt_test_SOURCES = \ + dns_sd.h \ + txt.c \ + txt-test.c \ + warn.c warn.h +txt_test_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) +txt_test_LDADD = $(AM_LDADD) ../avahi-common/libavahi-common.la + +# You can test the compatibility layer by sticking in mDNSResponder's +# dns-sd.c source here, naming it "bonjour-test.c" and running "make +# bonjour-test" manually. We do not distribute that file due to +# licensing restrictions. + +bonjour-test: bonjour-test.c libavahi-compat-bonjour.la + $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) $(PTHREAD_CFLAGS) -o bonjour-test.o -c bonjour-test.c + $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(PTHREAD_CFLAGS) -o bonjour-test bonjour-test.o $(PTHREAD_LIBS) ../avahi-common/libavahi-common.la libavahi-compat-bonjour.la + +CLEANFILES = bonjour-test.o bonjour-test diff --git a/compat-bonjour/compat.c b/compat-bonjour/compat.c index 6651845..6f129d0 100644 --- a/compat-bonjour/compat.c +++ b/compat-bonjour/compat.c @@ -37,7 +37,7 @@ #include #include - +#include "warn.h" #include "dns_sd.h" enum { @@ -161,6 +161,7 @@ static void * thread_func(void *data) { static DNSServiceRef sdref_new(void) { int fd[2] = { -1, -1 }; DNSServiceRef sdref = NULL; + pthread_mutexattr_t mutex_attr; if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0) goto fail; @@ -175,7 +176,9 @@ static DNSServiceRef sdref_new(void) { sdref->service_browser = NULL; sdref->service_resolver = NULL; - pthread_mutex_init(&sdref->mutex, NULL); + ASSERT_SUCCESS(pthread_mutexattr_init(&mutex_attr)); + pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE); + ASSERT_SUCCESS(pthread_mutex_init(&sdref->mutex, NULL)); sdref->thread_running = 0; @@ -210,14 +213,17 @@ fail: int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef) { assert(sdRef); + AVAHI_WARN_LINKAGE; + return sdRef->main_fd; } DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdref) { DNSServiceErrorType ret = kDNSServiceErr_Unknown; - if (pthread_mutex_lock(&sdref->mutex) != 0) - return kDNSServiceErr_Unknown; + AVAHI_WARN_LINKAGE; + + ASSERT_SUCCESS(pthread_mutex_lock(&sdref->mutex)); /* Cleanup notification socket */ if (read_command(sdref->main_fd) != COMMAND_POLLED) @@ -237,7 +243,7 @@ DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdref) { finish: - pthread_mutex_unlock(&sdref->mutex); + ASSERT_SUCCESS(pthread_mutex_unlock(&sdref->mutex)); return ret; } @@ -245,8 +251,8 @@ finish: void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdref) { assert(sdref); - fprintf(stderr, "deallocating()\n"); - + AVAHI_WARN_LINKAGE; + if (sdref->thread_running) { write_command(sdref->main_fd, COMMAND_QUIT); avahi_simple_poll_wakeup(sdref->simple_poll); @@ -387,6 +393,8 @@ DNSServiceErrorType DNSSD_API DNSServiceBrowse( DNSServiceRef sdref = NULL; AvahiIfIndex ifindex; + AVAHI_WARN_LINKAGE; + assert(ret_sdref); assert(regtype); assert(domain); @@ -475,7 +483,6 @@ static void service_resolver_callback( } } - DNSServiceErrorType DNSSD_API DNSServiceResolve( DNSServiceRef *ret_sdref, DNSServiceFlags flags, @@ -491,6 +498,8 @@ DNSServiceErrorType DNSSD_API DNSServiceResolve( DNSServiceRef sdref = NULL; AvahiIfIndex ifindex; + AVAHI_WARN_LINKAGE; + assert(ret_sdref); assert(name); assert(regtype); diff --git a/compat-bonjour/txt-test.c b/compat-bonjour/txt-test.c new file mode 100644 index 0000000..61f1292 --- /dev/null +++ b/compat-bonjour/txt-test.c @@ -0,0 +1,129 @@ +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + avahi is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General + Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "dns_sd.h" + +static void hexdump(const void* p, size_t size) { + const uint8_t *c = p; + assert(p); + + printf("Dumping %u bytes from %p:\n", size, p); + + while (size > 0) { + unsigned i; + + for (i = 0; i < 16; i++) { + if (i < size) + printf("%02x ", c[i]); + else + printf(" "); + } + + for (i = 0; i < 16; i++) { + if (i < size) + printf("%c", c[i] >= 32 && c[i] < 127 ? c[i] : '.'); + else + printf(" "); + } + + printf("\n"); + + c += 16; + + if (size <= 16) + break; + + size -= 16; + } +} + + +int main(int argc, char *argv[]) { + const char *r; + TXTRecordRef ref; + uint8_t l; + const void *p; + char k[256]; + + TXTRecordCreate(&ref, 0, NULL); + + hexdump(TXTRecordGetBytesPtr(&ref), TXTRecordGetLength(&ref)); + + TXTRecordSetValue(&ref, "foo", 7, "lennart"); + hexdump(TXTRecordGetBytesPtr(&ref), TXTRecordGetLength(&ref)); + + TXTRecordSetValue(&ref, "waldo", 5, "rocks"); + hexdump(TXTRecordGetBytesPtr(&ref), TXTRecordGetLength(&ref)); + + TXTRecordSetValue(&ref, "quux", 9, "the_house"); + hexdump(TXTRecordGetBytesPtr(&ref), TXTRecordGetLength(&ref)); + + TXTRecordSetValue(&ref, "yeah", 0, NULL); + hexdump(TXTRecordGetBytesPtr(&ref), TXTRecordGetLength(&ref)); + + TXTRecordSetValue(&ref, "waldo", 6, "rocked"); + hexdump(TXTRecordGetBytesPtr(&ref), TXTRecordGetLength(&ref)); + + TXTRecordRemoveValue(&ref, "foo"); + hexdump(TXTRecordGetBytesPtr(&ref), TXTRecordGetLength(&ref)); + + TXTRecordRemoveValue(&ref, "waldo"); + hexdump(TXTRecordGetBytesPtr(&ref), TXTRecordGetLength(&ref)); + + TXTRecordSetValue(&ref, "kawumm", 6, "bloerb"); + hexdump(TXTRecordGetBytesPtr(&ref), TXTRecordGetLength(&ref)); + + TXTRecordSetValue(&ref, "one", 1, "1"); + hexdump(TXTRecordGetBytesPtr(&ref), TXTRecordGetLength(&ref)); + + TXTRecordSetValue(&ref, "two", 1, "2"); + hexdump(TXTRecordGetBytesPtr(&ref), TXTRecordGetLength(&ref)); + + TXTRecordSetValue(&ref, "three", 1, "3"); + hexdump(TXTRecordGetBytesPtr(&ref), TXTRecordGetLength(&ref)); + + assert(TXTRecordContainsKey(TXTRecordGetLength(&ref), TXTRecordGetBytesPtr(&ref), "two")); + assert(!TXTRecordContainsKey(TXTRecordGetLength(&ref), TXTRecordGetBytesPtr(&ref), "four")); + + r = TXTRecordGetValuePtr(TXTRecordGetLength(&ref), TXTRecordGetBytesPtr(&ref), "kawumm", &l); + + hexdump(r, l); + + assert(TXTRecordGetCount(TXTRecordGetLength(&ref), TXTRecordGetBytesPtr(&ref)) == 6); + + TXTRecordGetItemAtIndex(TXTRecordGetLength(&ref), TXTRecordGetBytesPtr(&ref), 2, sizeof(k), k, &l, &p); + + fprintf(stderr, "key=<%s>\n", k); + + hexdump(p, l); + + assert(TXTRecordGetItemAtIndex(TXTRecordGetLength(&ref), TXTRecordGetBytesPtr(&ref), 20, sizeof(k), k, &l, &p) == kDNSServiceErr_Invalid); + + TXTRecordDeallocate(&ref); +} diff --git a/compat-bonjour/txt.c b/compat-bonjour/txt.c new file mode 100644 index 0000000..c85837a --- /dev/null +++ b/compat-bonjour/txt.c @@ -0,0 +1,491 @@ +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + avahi is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General + Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include + +#include "dns_sd.h" +#include "warn.h" + +typedef struct TXTRecordInternal { + uint8_t *buffer, *malloc_buffer; + size_t size, max_size; +} TXTRecordInternal; + +#define INTERNAL_PTR(txtref) (* (TXTRecordInternal**) (txtref)) +#define INTERNAL_PTR_CONST(txtref) (* (const TXTRecordInternal* const *) (txtref)) + +void DNSSD_API TXTRecordCreate( + TXTRecordRef *txtref, + uint16_t length, + void *buffer) { + + TXTRecordInternal *t; + + AVAHI_WARN_LINKAGE; + + assert(txtref); + + /* Apple's API design is flawed in so many ways, including the + * fact that it isn't compatible with 64 bit processors. To work + * around this we need some magic here which involves allocating + * our own memory. Please, Apple, do your homework next time + * before designing an API! */ + + if ((t = avahi_new(TXTRecordInternal, 1))) { + t->buffer = buffer; + t->max_size = length; + t->size = 0; + t->malloc_buffer = NULL; + } + + /* If we were unable to allocate memory, we store a NULL pointer + * and return a NoMemory error later, is somewhat unclean, but + * should work. */ + INTERNAL_PTR(txtref) = t; +} + +void DNSSD_API TXTRecordDeallocate(TXTRecordRef *txtref) { + TXTRecordInternal *t; + + AVAHI_WARN_LINKAGE; + + assert(txtref); + t = INTERNAL_PTR(txtref); + if (!t) + return; + + avahi_free(t->malloc_buffer); + avahi_free(t); + + /* Just in case ... */ + INTERNAL_PTR(txtref) = NULL; +} + +static int make_sure_fits_in(TXTRecordInternal *t, size_t size) { + uint8_t *n; + size_t nsize; + + assert(t); + + if (t->size + size <= t->max_size) + return 0; + + nsize = t->size + size + 100; + + if (nsize > 0xFFFF) + return -1; + + if (!(n = avahi_realloc(t->malloc_buffer, nsize))) + return -1; + + if (!t->malloc_buffer && t->size) + memcpy(n, t->buffer, t->size); + + t->buffer = t->malloc_buffer = n; + t->max_size = nsize; + + return 0; +} + +static int remove_key(TXTRecordInternal *t, const char *key) { + size_t i; + uint8_t *p; + size_t key_len; + int found = 0; + + key_len = strlen(key); + assert(key_len <= 0xFF); + + p = t->buffer; + i = 0; + + while (i < t->size) { + + /* Does the item fit in? */ + assert(*p <= t->size - i - 1); + + /* Key longer than buffer */ + if (key_len > t->size - i - 1) + break; + + if (key_len <= *p && + strncmp(key, (char*) p+1, key_len) == 0 && + (key_len == *p || p[1+key_len] == '=')) { + + uint8_t s; + + /* Key matches, so let's remove it */ + + s = *p; + memmove(p, p + 1 + *p, t->size - i - *p -1); + t->size -= s + 1; + + found = 1; + } else { + /* Skip to next */ + + i += *p +1; + p += *p +1; + } + } + + return found; +} + +DNSServiceErrorType DNSSD_API TXTRecordSetValue( + TXTRecordRef *txtref, + const char *key, + uint8_t length, + const void *value) { + + TXTRecordInternal *t; + uint8_t *p; + size_t l, n; + + AVAHI_WARN_LINKAGE; + + assert(key); + assert(txtref); + + l = strlen(key); + + if (*key == 0 || strchr(key, '=') || l > 0xFF) /* Empty or invalid key */ + return kDNSServiceErr_Invalid; + + if (!(t = INTERNAL_PTR(txtref))) + return kDNSServiceErr_NoMemory; + + n = l + (value ? length + 1 : 0); + + if (n > 0xFF) + return kDNSServiceErr_Invalid; + + if (make_sure_fits_in(t, 1 + n) < 0) + return kDNSServiceErr_NoMemory; + + remove_key(t, key); + + p = t->buffer + t->size; + + *(p++) = (uint8_t) n; + t->size ++; + + memcpy(p, key, l); + p += l; + t->size += l; + + if (value) { + *(p++) = '='; + memcpy(p, value, length); + t->size += length + 1; + } + + assert(t->size <= t->max_size); + + return kDNSServiceErr_NoError; +} + +DNSServiceErrorType DNSSD_API TXTRecordRemoveValue(TXTRecordRef *txtref, const char *key) { + TXTRecordInternal *t; + int found; + + AVAHI_WARN_LINKAGE; + + assert(key); + assert(txtref); + + if (*key == 0 || strchr(key, '=') || strlen(key) > 0xFF) /* Empty or invalid key */ + return kDNSServiceErr_Invalid; + + if (!(t = INTERNAL_PTR(txtref))) + return kDNSServiceErr_NoError; + + found = remove_key(t, key); + + return found ? kDNSServiceErr_NoError : kDNSServiceErr_NoSuchKey; +} + +uint16_t DNSSD_API TXTRecordGetLength(const TXTRecordRef *txtref) { + const TXTRecordInternal *t; + + AVAHI_WARN_LINKAGE; + + assert(txtref); + + if (!(t = INTERNAL_PTR_CONST(txtref))) + return 0; + + assert(t->size <= 0xFFFF); + return (uint16_t) t->size; +} + +const void * DNSSD_API TXTRecordGetBytesPtr(const TXTRecordRef *txtref) { + const TXTRecordInternal *t; + + AVAHI_WARN_LINKAGE; + + assert(txtref); + + if (!(t = INTERNAL_PTR_CONST(txtref)) || !t->buffer) + return ""; + + return t->buffer; +} + +static const uint8_t *find_key(const uint8_t *buffer, size_t size, const char *key) { + size_t i; + const uint8_t *p; + size_t key_len; + + key_len = strlen(key); + + assert(key_len <= 0xFF); + + p = buffer; + i = 0; + + while (i < size) { + + /* Does the item fit in? */ + if (*p > size - i - 1) + return NULL; + + /* Key longer than buffer */ + if (key_len > size - i - 1) + return NULL; + + if (key_len <= *p && + strncmp(key, (const char*) p+1, key_len) == 0 && + (key_len == *p || p[1+key_len] == '=')) { + + /* Key matches, so let's return it */ + + return p; + } + + /* Skip to next */ + i += *p +1; + p += *p +1; + } + + return NULL; +} + +int DNSSD_API TXTRecordContainsKey ( + uint16_t size, + const void *buffer, + const char *key) { + + AVAHI_WARN_LINKAGE; + + assert(key); + + if (!size) + return 0; + + assert(buffer); + + if (!(find_key(buffer, size, key))) + return 0; + + return 1; +} + +const void * DNSSD_API TXTRecordGetValuePtr( + uint16_t size, + const void *buffer, + const char *key, + uint8_t *value_len) { + + const uint8_t *p; + size_t n, l; + + AVAHI_WARN_LINKAGE; + + assert(key); + + if (!size) + goto fail; + + if (*key == 0 || strchr(key, '=') || strlen(key) > 0xFF) /* Empty or invalid key */ + return NULL; + + assert(buffer); + + if (!(p = find_key(buffer, size, key))) + goto fail; + + n = *p; + l = strlen(key); + + assert(n >= l); + p += 1 + l; + n -= l; + + if (n <= 0) + goto fail; + + assert(*p == '='); + p++; + n--; + + if (value_len) + *value_len = n; + + return p; + +fail: + if (value_len) + *value_len = 0; + + return NULL; +} + + +uint16_t DNSSD_API TXTRecordGetCount( + uint16_t size, + const void *buffer) { + + const uint8_t *p; + unsigned n = 0; + size_t i; + + AVAHI_WARN_LINKAGE; + + if (!size) + return 0; + + assert(buffer); + + p = buffer; + i = 0; + + while (i < size) { + + /* Does the item fit in? */ + if (*p > size - i - 1) + break; + + n++; + + /* Skip to next */ + i += *p +1; + p += *p +1; + } + + assert(n <= 0xFFFF); + + return (uint16_t) n; +} + +DNSServiceErrorType DNSSD_API TXTRecordGetItemAtIndex( + uint16_t size, + const void *buffer, + uint16_t idx, + uint16_t key_len, + char *key, + uint8_t *value_len, + const void **value) { + + const uint8_t *p; + size_t i; + unsigned n = 0; + DNSServiceErrorType ret = kDNSServiceErr_Invalid; + + AVAHI_WARN_LINKAGE; + + if (!size) + goto fail; + + assert(buffer); + + p = buffer; + i = 0; + + while (i < size) { + + /* Does the item fit in? */ + if (*p > size - i - 1) + goto fail; + + if (n >= idx) { + size_t l; + const uint8_t *d; + + d = memchr(p+1, '=', *p); + + /* Length of key */ + l = d ? d - p - 1 : *p; + + if (key_len < l+1) { + ret = kDNSServiceErr_NoMemory; + goto fail; + } + + strncpy(key, (const char*) p + 1, l); + key[l] = 0; + + if (d) { + if (value_len) + *value_len = *p - l - 1; + + if (value) + *value = d + 1; + } else { + + if (value_len) + *value_len = 0; + + if (value) + *value = NULL; + } + + return kDNSServiceErr_NoError; + } + + n++; + + /* Skip to next */ + i += *p +1; + p += *p +1; + } + + +fail: + + if (value) + *value = NULL; + + if (value_len) + *value_len = 0; + + return ret; + +} diff --git a/compat-bonjour/unsupported.c b/compat-bonjour/unsupported.c index d57d028..972f3e5 100644 --- a/compat-bonjour/unsupported.c +++ b/compat-bonjour/unsupported.c @@ -24,6 +24,7 @@ #endif #include "dns_sd.h" +#include "warn.h" DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains( DNSServiceRef *sdRef, @@ -32,6 +33,8 @@ DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains( DNSServiceDomainEnumReply callBack, void *context) { + AVAHI_WARN_UNSUPPORTED; + return kDNSServiceErr_Unsupported; } @@ -49,6 +52,8 @@ DNSServiceErrorType DNSSD_API DNSServiceRegister ( DNSServiceRegisterReply callBack, void *context) { + AVAHI_WARN_UNSUPPORTED; + return kDNSServiceErr_Unsupported; } @@ -58,6 +63,8 @@ int DNSSD_API DNSServiceConstructFullName ( const char *regtype, const char *domain) { + AVAHI_WARN_UNSUPPORTED; + return kDNSServiceErr_Unsupported; } @@ -75,6 +82,8 @@ DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord ( DNSServiceRegisterRecordReply callBack, void *context) { + AVAHI_WARN_UNSUPPORTED; + return kDNSServiceErr_Unsupported; } @@ -88,6 +97,8 @@ DNSServiceErrorType DNSSD_API DNSServiceQueryRecord ( DNSServiceQueryRecordReply callBack, void *context) { + AVAHI_WARN_UNSUPPORTED; + return kDNSServiceErr_Unsupported; } @@ -100,10 +111,14 @@ void DNSSD_API DNSServiceReconfirmRecord ( uint16_t rdlen, const void *rdata) { + AVAHI_WARN_UNSUPPORTED; + return; } DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef) { + AVAHI_WARN_UNSUPPORTED; + return kDNSServiceErr_Unsupported; } @@ -116,6 +131,8 @@ DNSServiceErrorType DNSSD_API DNSServiceAddRecord( const void *rdata, uint32_t ttl) { + AVAHI_WARN_UNSUPPORTED; + return kDNSServiceErr_Unsupported; } @@ -127,6 +144,8 @@ DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord( const void *rdata, uint32_t ttl) { + AVAHI_WARN_UNSUPPORTED; + return kDNSServiceErr_Unsupported; } @@ -135,6 +154,8 @@ DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord( DNSRecordRef RecordRef, DNSServiceFlags flags) { + AVAHI_WARN_UNSUPPORTED; + return kDNSServiceErr_Unsupported; } diff --git a/compat-bonjour/warn.c b/compat-bonjour/warn.c new file mode 100644 index 0000000..859cfb0 --- /dev/null +++ b/compat-bonjour/warn.c @@ -0,0 +1,85 @@ +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + avahi is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General + Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "warn.h" + +static pthread_mutex_t linkage_mutex = PTHREAD_MUTEX_INITIALIZER; +static int linkage_warning = 0; + +static void get_exe_name(char *t, size_t l) { + int k; + char fn[1024]; + + /* Yes, I know, this is not portable. But who cares? It's + * for cosmetics only, anyway. */ + + snprintf(fn, sizeof(fn), "/proc/%lu/exe", (unsigned long) getpid()); + + if ((k = readlink(fn, t, l-1)) < 0) + snprintf(t, l, "(unknown)"); + else { + char *slash; + + assert((size_t) k <= l-1); + t[k] = 0; + + if ((slash = strrchr(t, '/'))) + memmove(t, slash+1, strlen(slash)+1); + } +} + +void avahi_warn_linkage(void) { + int w; + + pthread_mutex_lock(&linkage_mutex); + w = linkage_warning; + linkage_warning = 1; + pthread_mutex_unlock(&linkage_mutex); + + if (!w && !getenv("AVAHI_BONJOUR_NOWARN")) { + char exename[256]; + get_exe_name(exename, sizeof(exename)); + + fprintf(stderr, "*** WARNING: The application '%s' uses the Bonjour compatiblity layer of Avahi. Please fix it to use the native API! ***\n", exename); + } +} + +void avahi_warn_unsupported(const char *function) { + char exename[256]; + get_exe_name(exename, sizeof(exename)); + + fprintf(stderr, "*** WARNING: The application '%s' called '%s()' which is not supported in the Bonjour compatiblity layer of Avahi. Please fix it to use the native API! ***\n", exename, function); +} + + + diff --git a/compat-bonjour/warn.h b/compat-bonjour/warn.h new file mode 100644 index 0000000..b419cd8 --- /dev/null +++ b/compat-bonjour/warn.h @@ -0,0 +1,32 @@ +#ifndef foowarnhfoo +#define foowarnhfoo + +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + avahi is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General + Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +void avahi_warn_unsupported(const char *function); + +void avahi_warn_linkage(void); + +#define AVAHI_WARN_LINKAGE { avahi_warn_linkage(); } +#define AVAHI_WARN_UNSUPPORTED { avahi_warn_linkage(); avahi_warn_unsupported(__FUNCTION__); } + +#endif