/* * Copyright © 2009 CNRS * Copyright © 2009-2014 Inria. All rights reserved. * Copyright © 2009-2010 Université Bordeaux * Copyright © 2009-2018 Cisco Systems, Inc. All rights reserved. * See COPYING in top-level directory. */ #include #include #include #include #ifdef HAVE_SYS_UTSNAME_H #include #endif #include #include #include #include #include #ifdef HAVE_PROGRAM_INVOCATION_NAME #include extern char *program_invocation_name; #endif #ifdef HAVE___PROGNAME extern char *__progname; #endif int hwloc_snprintf(char *str, size_t size, const char *format, ...) { int ret; va_list ap; static char bin; size_t fakesize; char *fakestr; /* Some systems crash on str == NULL */ if (!size) { str = &bin; size = 1; } va_start(ap, format); ret = vsnprintf(str, size, format, ap); va_end(ap); if (ret >= 0 && (size_t) ret != size-1) return ret; /* vsnprintf returned size-1 or -1. That could be a system which reports the * written data and not the actually required room. Try increasing buffer * size to get the latter. */ fakesize = size; fakestr = NULL; do { fakesize *= 2; free(fakestr); fakestr = malloc(fakesize); if (NULL == fakestr) return -1; va_start(ap, format); errno = 0; ret = vsnprintf(fakestr, fakesize, format, ap); va_end(ap); } while ((size_t) ret == fakesize-1 || (ret < 0 && (!errno || errno == ERANGE))); if (ret >= 0 && size) { if (size > (size_t) ret+1) size = ret+1; memcpy(str, fakestr, size-1); str[size-1] = 0; } free(fakestr); return ret; } int hwloc_namecoloncmp(const char *haystack, const char *needle, size_t n) { size_t i = 0; while (*haystack && *haystack != ':') { int ha = *haystack++; int low_h = tolower(ha); int ne = *needle++; int low_n = tolower(ne); if (low_h != low_n) return 1; i++; } return i < n; } void hwloc_add_uname_info(struct hwloc_topology *topology __hwloc_attribute_unused, void *cached_uname __hwloc_attribute_unused) { #ifdef HAVE_UNAME struct utsname _utsname, *utsname; if (hwloc_obj_get_info_by_name(topology->levels[0][0], "OSName")) /* don't annotate twice */ return; if (cached_uname) utsname = (struct utsname *) cached_uname; else { utsname = &_utsname; if (uname(utsname) < 0) return; } if (*utsname->sysname) hwloc_obj_add_info(topology->levels[0][0], "OSName", utsname->sysname); if (*utsname->release) hwloc_obj_add_info(topology->levels[0][0], "OSRelease", utsname->release); if (*utsname->version) hwloc_obj_add_info(topology->levels[0][0], "OSVersion", utsname->version); if (*utsname->nodename) hwloc_obj_add_info(topology->levels[0][0], "HostName", utsname->nodename); if (*utsname->machine) hwloc_obj_add_info(topology->levels[0][0], "Architecture", utsname->machine); #endif /* HAVE_UNAME */ } char * hwloc_progname(struct hwloc_topology *topology __hwloc_attribute_unused) { #if HAVE_DECL_GETMODULEFILENAME char name[256], *local_basename; unsigned res = GetModuleFileName(NULL, name, sizeof(name)); if (res == sizeof(name) || !res) return NULL; local_basename = strrchr(name, '\\'); if (!local_basename) local_basename = name; else local_basename++; return strdup(local_basename); #else /* !HAVE_GETMODULEFILENAME */ const char *name, *local_basename; #if HAVE_DECL_GETPROGNAME name = getprogname(); /* FreeBSD, NetBSD, some Solaris */ #elif HAVE_DECL_GETEXECNAME name = getexecname(); /* Solaris */ #elif defined HAVE_PROGRAM_INVOCATION_NAME name = program_invocation_name; /* Glibc. BGQ CNK. */ /* could use program_invocation_short_name directly, but we have the code to remove the path below anyway */ #elif defined HAVE___PROGNAME name = __progname; /* fallback for most unix, used for OpenBSD */ #else /* TODO: _NSGetExecutablePath(path, &size) on Darwin */ /* TODO: AIX, HPUX, OSF */ name = NULL; #endif if (!name) return NULL; local_basename = strrchr(name, '/'); if (!local_basename) local_basename = name; else local_basename++; return strdup(local_basename); #endif /* !HAVE_GETMODULEFILENAME */ }