Files
hdf5/src/H5system.c
Binh-Minh Ribler e57234b027 Fixed HDFFV-10404
Description:
    Applied the typo fixes from user's report.
    The previous pull request couldn't be merged because it was too old,
    and it was too complicated for me to resolve conflicts.
Platform tested:
    Linux/64 (jelly) - very minor
2018-07-26 17:19:03 -05:00

1286 lines
41 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* Copyright by the Board of Trustees of the University of Illinois. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the COPYING file, which can be found at the root of the source code *
* distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*-------------------------------------------------------------------------
*
* Created: H5system.c
* Aug 21 2006
* Quincey Koziol <koziol@hdfgroup.org>
*
* Purpose: System call wrapper implementations.
*
*-------------------------------------------------------------------------
*/
/****************/
/* Module Setup */
/****************/
/***********/
/* Headers */
/***********/
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5Fprivate.h" /* File access */
#include "H5MMprivate.h" /* Memory management */
/****************/
/* Local Macros */
/****************/
/******************/
/* Local Typedefs */
/******************/
/********************/
/* Package Typedefs */
/********************/
/********************/
/* Local Prototypes */
/********************/
/*********************/
/* Package Variables */
/*********************/
/*****************************/
/* Library Private Variables */
/*****************************/
/*******************/
/* Local Variables */
/*******************/
/* Track whether tzset routine was called */
static hbool_t H5_ntzset = FALSE;
/*-------------------------------------------------------------------------
* Function: HDfprintf
*
* Purpose: Prints the optional arguments under the control of the format
* string FMT to the stream STREAM. This function takes the
* same format as fprintf(3c) with a few added features:
*
* The conversion modifier `H' refers to the size of an
* `hsize_t' or `hssize_t' type. For instance, "0x%018Hx"
* prints an `hsize_t' value as a hex number right justified and
* zero filled in an 18-character field.
*
* The conversion `a' refers to an `haddr_t' type.
*
* Return: Success: Number of characters printed
*
* Failure: -1
*
* Programmer: Robb Matzke
* Thursday, April 9, 1998
*
* Modifications:
* Robb Matzke, 1999-07-27
* The `%a' format refers to an argument of `haddr_t' type
* instead of `haddr_t*' and the return value is correct.
*-------------------------------------------------------------------------
*/
int
HDfprintf(FILE *stream, const char *fmt, ...)
{
int n=0, nout = 0;
int fwidth, prec;
int zerofill;
int leftjust;
int plussign;
int ldspace;
int prefix;
char modifier[8];
int conv;
char *rest, format_templ[128];
int len;
const char *s;
va_list ap;
HDassert(stream);
HDassert(fmt);
va_start (ap, fmt);
while (*fmt) {
fwidth = prec = 0;
zerofill = 0;
leftjust = 0;
plussign = 0;
prefix = 0;
ldspace = 0;
modifier[0] = '\0';
if ('%'==fmt[0] && '%'==fmt[1]) {
HDputc ('%', stream);
fmt += 2;
nout++;
} else if ('%'==fmt[0]) {
s = fmt + 1;
/* Flags */
while(HDstrchr("-+ #", *s)) {
switch(*s) {
case '-':
leftjust = 1;
break;
case '+':
plussign = 1;
break;
case ' ':
ldspace = 1;
break;
case '#':
prefix = 1;
break;
default:
HDassert(0 && "Unknown format flag");
} /* end switch */ /*lint !e744 Switch statement doesn't _need_ default */
s++;
} /* end while */
/* Field width */
if(HDisdigit(*s)) {
zerofill = ('0' == *s);
fwidth = (int)HDstrtol (s, &rest, 10);
s = rest;
} /* end if */
else if ('*'==*s) {
fwidth = va_arg(ap, int);
if(fwidth < 0) {
leftjust = 1;
fwidth = -fwidth;
}
s++;
}
/* Precision */
if('.'==*s) {
s++;
if(HDisdigit(*s)) {
prec = (int)HDstrtol(s, &rest, 10);
s = rest;
} else if('*'==*s) {
prec = va_arg(ap, int);
s++;
}
if(prec < 1)
prec = 1;
}
/* Extra type modifiers */
if(HDstrchr("zZHhlqLI", *s)) {
switch(*s) {
/*lint --e{506} Don't issue warnings about constant value booleans */
/*lint --e{774} Don't issue warnings boolean within 'if' always evaluates false/true */
case 'H':
if(sizeof(hsize_t) < sizeof(long))
modifier[0] = '\0';
else if(sizeof(hsize_t) == sizeof(long)) {
HDstrncpy(modifier, "l", sizeof(modifier));
modifier[sizeof(modifier) - 1] = '\0';
} /* end if */
else {
HDstrncpy(modifier, H5_PRINTF_LL_WIDTH, sizeof(modifier));
modifier[sizeof(modifier) - 1] = '\0';
} /* end else */
break;
case 'Z':
case 'z':
if(sizeof(size_t) < sizeof(long))
modifier[0] = '\0';
else if(sizeof(size_t) == sizeof(long)) {
HDstrncpy(modifier, "l", sizeof(modifier));
modifier[sizeof(modifier) - 1] = '\0';
} /* end if */
else {
HDstrncpy(modifier, H5_PRINTF_LL_WIDTH, sizeof(modifier));
modifier[sizeof(modifier) - 1] = '\0';
} /* end else */
break;
default:
/* Handle 'I64' modifier for Microsoft's "__int64" type */
if(*s=='I' && *(s+1)=='6' && *(s+2)=='4') {
modifier[0] = *s;
modifier[1] = *(s+1);
modifier[2] = *(s+2);
modifier[3] = '\0';
s += 2; /* Increment over 'I6', the '4' is taken care of below */
} /* end if */
else {
/* Handle 'll' for long long types */
if(*s=='l' && *(s+1)=='l') {
modifier[0] = *s;
modifier[1] = *s;
modifier[2] = '\0';
s++; /* Increment over first 'l', second is taken care of below */
} /* end if */
else {
modifier[0] = *s;
modifier[1] = '\0';
} /* end else */
} /* end else */
break;
}
s++;
}
/* Conversion */
conv = *s++;
/* Create the format template */
len = 0;
len += HDsnprintf(format_templ, (sizeof(format_templ) - (size_t)(len + 1)), "%%%s%s%s%s%s", (leftjust ? "-" : ""),
(plussign ? "+" : ""), (ldspace ? " " : ""),
(prefix ? "#" : ""), (zerofill ? "0" : ""));
if(fwidth > 0)
len += HDsnprintf(format_templ + len, (sizeof(format_templ) - (size_t)(len + 1)), "%d", fwidth);
if(prec > 0)
len += HDsnprintf(format_templ + len, (sizeof(format_templ) - (size_t)(len + 1)), ".%d", prec);
if(*modifier)
len += HDsnprintf(format_templ + len, (sizeof(format_templ) - (size_t)(len + 1)), "%s", modifier);
HDsnprintf(format_templ + len, (sizeof(format_templ) - (size_t)(len + 1)), "%c", conv);
/* Conversion */
switch (conv) {
case 'd':
case 'i':
if(!HDstrcmp(modifier, "h")) {
short x = (short)va_arg(ap, int);
n = fprintf(stream, format_templ, x);
} else if(!*modifier) {
int x = va_arg(ap, int);
n = fprintf(stream, format_templ, x);
} else if(!HDstrcmp(modifier, "l")) {
long x = va_arg(ap, long);
n = fprintf(stream, format_templ, x);
} else {
int64_t x = va_arg(ap, int64_t);
n = fprintf(stream, format_templ, x);
}
break;
case 'o':
case 'u':
case 'x':
case 'X':
if(!HDstrcmp(modifier, "h")) {
unsigned short x = (unsigned short)va_arg(ap, unsigned int);
n = fprintf(stream, format_templ, x);
} else if(!*modifier) {
unsigned int x = va_arg(ap, unsigned int); /*lint !e732 Loss of sign not really occurring */
n = fprintf(stream, format_templ, x);
} else if(!HDstrcmp(modifier, "l")) {
unsigned long x = va_arg(ap, unsigned long); /*lint !e732 Loss of sign not really occurring */
n = fprintf(stream, format_templ, x);
} else {
uint64_t x = va_arg(ap, uint64_t); /*lint !e732 Loss of sign not really occurring */
n = fprintf(stream, format_templ, x);
}
break;
case 'f':
case 'e':
case 'E':
case 'g':
case 'G':
if(!HDstrcmp(modifier, "h")) {
float x = (float)va_arg(ap, double);
n = fprintf(stream, format_templ, (double)x);
} else if(!*modifier || !HDstrcmp(modifier, "l")) {
double x = va_arg(ap, double);
n = fprintf(stream, format_templ, x);
} else {
/*
* Some compilers complain when `long double' and
* `double' are the same thing.
*/
#if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE
long double x = va_arg(ap, long double);
n = fprintf(stream, format_templ, x);
#else
double x = va_arg(ap, double);
n = fprintf(stream, format_templ, x);
#endif
}
break;
case 'a':
{
haddr_t x = va_arg(ap, haddr_t); /*lint !e732 Loss of sign not really occurring */
if(H5F_addr_defined(x)) {
len = 0;
len += HDsnprintf(format_templ, (sizeof(format_templ) - (size_t)(len + 1)), "%%%s%s%s%s%s",
(leftjust ? "-" : ""), (plussign ? "+" : ""),
(ldspace ? " " : ""), (prefix ? "#" : ""),
(zerofill ? "0" : ""));
if(fwidth > 0)
len += HDsnprintf(format_templ + len, (sizeof(format_templ) - (size_t)(len + 1)), "%d", fwidth);
/*lint --e{506} Don't issue warnings about constant value booleans */
/*lint --e{774} Don't issue warnings boolean within 'if' always evaluates false/true */
if(sizeof(x) == H5_SIZEOF_INT) {
HDstrncat(format_templ, "u", (sizeof(format_templ) - (size_t)(len + 1)));
len++;
} /* end if */
else if(sizeof(x) == H5_SIZEOF_LONG) {
HDstrncat(format_templ, "lu", (sizeof(format_templ) - (size_t)(len + 1)));
len++;
} /* end if */
else if(sizeof(x) == H5_SIZEOF_LONG_LONG) {
HDstrncat(format_templ, H5_PRINTF_LL_WIDTH, (sizeof(format_templ) - (size_t)(len + 1)));
len += (int)sizeof(H5_PRINTF_LL_WIDTH);
HDstrncat(format_templ, "u", (sizeof(format_templ) - (size_t)(len + 1)));
len++;
}
n = fprintf(stream, format_templ, x);
} else {
len = 0;
HDstrncpy(format_templ, "%", (sizeof(format_templ) - (size_t)(len + 1)));
len++;
if(leftjust) {
HDstrncat(format_templ, "-", (sizeof(format_templ) - (size_t)(len + 1)));
len++;
} /* end if */
if(fwidth)
len += HDsnprintf(format_templ + len, (sizeof(format_templ) - (size_t)(len + 1)), "%d", fwidth);
HDstrncat(format_templ, "s", (sizeof(format_templ) - (size_t)(len + 1)));
fprintf(stream, format_templ, "UNDEF");
}
}
break;
case 'c':
{
char x = (char)va_arg(ap, int);
n = fprintf(stream, format_templ, x);
}
break;
case 's':
case 'p':
{
char *x = va_arg(ap, char*); /*lint !e64 Type mismatch not really occurring */
n = fprintf(stream, format_templ, x);
}
break;
case 'n':
format_templ[HDstrlen(format_templ) - 1] = 'u';
n = fprintf(stream, format_templ, nout);
break;
case 't':
{
htri_t tri_var = va_arg(ap, htri_t);
if(tri_var > 0)
fprintf(stream, "TRUE");
else if(!tri_var)
fprintf(stream, "FALSE");
else
fprintf(stream, "FAIL(%d)", (int)tri_var);
}
break;
default:
HDfputs(format_templ, stream);
n = (int)HDstrlen(format_templ);
break;
}
nout += n;
fmt = s;
} else {
HDputc(*fmt, stream);
fmt++;
nout++;
}
}
va_end(ap);
return nout;
} /* end HDfprintf() */
/*-------------------------------------------------------------------------
* Function: HDstrtoll
*
* Purpose: Converts the string S to an int64_t value according to the
* given BASE, which must be between 2 and 36 inclusive, or be
* the special value zero.
*
* The string must begin with an arbitrary amount of white space
* (as determined by isspace(3c)) followed by a single optional
* `+' or `-' sign. If BASE is zero or 16 the string may then
* include a `0x' or `0X' prefix, and the number will be read in
* base 16; otherwise a zero BASE is taken as 10 (decimal)
* unless the next character is a `0', in which case it is taken
* as 8 (octal).
*
* The remainder of the string is converted to an int64_t in the
* obvious manner, stopping at the first character which is not
* a valid digit in the given base. (In bases above 10, the
* letter `A' in either upper or lower case represetns 10, `B'
* represents 11, and so forth, with `Z' representing 35.)
*
* If REST is not null, the address of the first invalid
* character in S is stored in *REST. If there were no digits
* at all, the original value of S is stored in *REST. Thus, if
* *S is not `\0' but **REST is `\0' on return the entire string
* was valid.
*
* Return: Success: The result.
*
* Failure: If the input string does not contain any
* digits then zero is returned and REST points
* to the original value of S. If an overflow
* or underflow occurs then the maximum or
* minimum possible value is returned and the
* global `errno' is set to ERANGE. If BASE is
* incorrect then zero is returned.
*
* Programmer: Robb Matzke
* Thursday, April 9, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
#ifndef HDstrtoll
int64_t
HDstrtoll(const char *s, const char **rest, int base)
{
int64_t sign=1, acc=0;
hbool_t overflow = FALSE;
errno = 0;
if (!s || (base && (base<2 || base>36))) {
if (rest)
*rest = s;
return 0;
}
/* Skip white space */
while (HDisspace (*s)) s++;
/* Optional minus or plus sign */
if ('+'==*s) {
s++;
} else if ('-'==*s) {
sign = -1;
s++;
}
/* Zero base prefix */
if (0==base && '0'==*s && ('x'==s[1] || 'X'==s[1])) {
base = 16;
s += 2;
} else if (0==base && '0'==*s) {
base = 8;
s++;
} else if (0==base) {
base = 10;
}
/* Digits */
while ((base<=10 && *s>='0' && *s<'0'+base) ||
(base>10 && ((*s>='0' && *s<='9') ||
(*s>='a' && *s<'a'+base-10) ||
(*s>='A' && *s<'A'+base-10)))) {
if (!overflow) {
int64_t digit = 0;
if (*s>='0' && *s<='9')
digit = *s - '0';
else if (*s>='a' && *s<='z')
digit = (*s-'a')+10;
else
digit = (*s-'A')+10;
if (acc*base+digit < acc) {
overflow = TRUE;
} else {
acc = acc*base + digit;
}
}
s++;
}
/* Overflow */
if (overflow) {
if (sign>0) {
acc = ((uint64_t)1<<(8*sizeof(int64_t)-1))-1;
} else {
acc = (int64_t)((uint64_t)1<<(8*sizeof(int64_t)-1));
}
errno = ERANGE;
}
/* Return values */
acc *= sign;
if (rest)
*rest = s;
return acc;
} /* end HDstrtoll() */
#endif
/*-------------------------------------------------------------------------
* Function: HDrand/HDsrand
*
* Purpose: Wrapper function for rand. If rand_r exists on this system,
* use it.
*
* Wrapper function for srand. If rand_r is available, it will keep
* track of the seed locally instead of using srand() which modifies
* global state and can break other programs.
*
* Return: Success: Random number from 0 to RAND_MAX
*
* Failure: Cannot fail.
*
* Programmer: Leon Arber
* March 6, 2006.
*
*-------------------------------------------------------------------------
*/
#ifdef H5_HAVE_RAND_R
static unsigned int g_seed = 42;
int HDrand(void)
{
return rand_r(&g_seed);
}
void HDsrand(unsigned int seed)
{
g_seed = seed;
}
#endif /* H5_HAVE_RAND_R */
/*-------------------------------------------------------------------------
* Function: Pflock
*
* Purpose: Wrapper function for POSIX systems where flock(2) is not
* available.
*
* Return: Success: 0
* Failure: -1
*
*-------------------------------------------------------------------------
*/
/* NOTE: Compile this all the time on POSIX systems, even when flock(2) is
* present so that it's less likely to become dead code.
*/
#ifdef H5_HAVE_FCNTL
int
Pflock(int fd, int operation) {
struct flock flk;
/* Set the lock type */
if(operation & LOCK_UN)
flk.l_type = F_UNLCK;
else if(operation & LOCK_SH)
flk.l_type = F_RDLCK;
else
flk.l_type = F_WRLCK;
/* Set the other flock struct values */
flk.l_whence = SEEK_SET;
flk.l_start = 0;
flk.l_len = 0; /* to EOF */
flk.l_pid = 0; /* not used with set */
/* Lock or unlock */
if(HDfcntl(fd, F_SETLK, flk) < 0)
return -1;
return 0;
} /* end Pflock() */
#endif /* H5_HAVE_FCNTL */
/*-------------------------------------------------------------------------
* Function: Nflock
*
* Purpose: Wrapper function for systems where no file locking is
* available.
*
* Return: Failure: -1 (always fails)
*
*-------------------------------------------------------------------------
*/
int H5_ATTR_CONST
Nflock(int H5_ATTR_UNUSED fd, int H5_ATTR_UNUSED operation) {
/* just fail */
return -1;
} /* end Nflock() */
/*-------------------------------------------------------------------------
* Function: H5_make_time
*
* Purpose: Portability routine to abstract converting a 'tm' struct into
* a time_t value.
*
* Note: This is a little problematic because mktime() operates on
* local times. We convert to local time and then figure out the
* adjustment based on the local time zone and daylight savings
* setting.
*
* Return: Success: The value of timezone
* Failure: -1
*
* Programmer: Quincey Koziol
* November 18, 2015
*
*-------------------------------------------------------------------------
*/
time_t
H5_make_time(struct tm *tm)
{
time_t the_time; /* The converted time */
#if defined(H5_HAVE_VISUAL_STUDIO) && (_MSC_VER >= 1900) /* VS 2015 */
/* In gcc and in Visual Studio prior to VS 2015 'timezone' is a global
* variable declared in time.h. That variable was deprecated and in
* VS 2015 is removed, with _get_timezone replacing it.
*/
long timezone = 0;
#endif /* defined(H5_HAVE_VISUAL_STUDIO) && (_MSC_VER >= 1900) */
time_t ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
/* Sanity check */
HDassert(tm);
/* Initialize timezone information */
if(!H5_ntzset) {
HDtzset();
H5_ntzset = TRUE;
} /* end if */
/* Perform base conversion */
if((time_t)-1 == (the_time = HDmktime(tm)))
HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCONVERT, FAIL, "badly formatted modification time message")
/* Adjust for timezones */
#if defined(H5_HAVE_TM_GMTOFF)
/* BSD-like systems */
the_time += tm->tm_gmtoff;
#elif defined(H5_HAVE_TIMEZONE)
#if defined(H5_HAVE_VISUAL_STUDIO) && (_MSC_VER >= 1900) /* VS 2015 */
/* In gcc and in Visual Studio prior to VS 2015 'timezone' is a global
* variable declared in time.h. That variable was deprecated and in
* VS 2015 is removed, with _get_timezone replacing it.
*/
_get_timezone(&timezone);
#endif /* defined(H5_HAVE_VISUAL_STUDIO) && (_MSC_VER >= 1900) */
the_time -= timezone - (tm->tm_isdst ? 3600 : 0);
#else
/*
* The catch-all. If we can't convert a character string universal
* coordinated time to a time_t value reliably then we can't decode the
* modification time message. This really isn't as bad as it sounds -- the
* only way a user can get the modification time is from our internal
* query routines, which can gracefully recover.
*/
HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "unable to obtain local timezone information")
#endif
/* Set return value */
ret_value = the_time;
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5_make_time() */
#ifdef H5_HAVE_WIN32_API
/* Offset between 1/1/1601 and 1/1/1970 in 100 nanosecond units */
#define _W32_FT_OFFSET (116444736000000000ULL)
/*-------------------------------------------------------------------------
* Function: Wgettimeofday
*
* Purpose: Wrapper function for gettimeofday on Windows systems
*
* This function can get the time as well as a timezone
*
* Return: 0
*
* This implementation is taken from the Cygwin source distribution at
* src/winsup/mingw/mingwex/gettimeofday.c
*
* The original source code was contributed by
* Danny Smith <dannysmith@users.sourceforge.net>
* and released in the public domain.
*
* Programmer: Scott Wegner
* May 19, 2009
*
*-------------------------------------------------------------------------
*/
int
Wgettimeofday(struct timeval *tv, struct timezone *tz)
{
union {
unsigned long long ns100; /*time since 1 Jan 1601 in 100ns units */
FILETIME ft;
} _now;
static int tzsetflag;
if(tv) {
GetSystemTimeAsFileTime (&_now.ft);
tv->tv_usec=(long)((_now.ns100 / 10ULL) % 1000000ULL );
tv->tv_sec= (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000ULL);
}
if(tz) {
if(!tzsetflag) {
_tzset();
tzsetflag = 1;
}
tz->tz_minuteswest = _timezone / 60;
tz->tz_dsttime = _daylight;
}
/* Always return 0 as per Open Group Base Specifications Issue 6.
Do not set errno on error. */
return 0;
} /* end Wgettimeofday() */
/*-------------------------------------------------------------------------
* Function: Wsetenv
*
* Purpose: Wrapper function for setenv on Windows systems.
* Interestingly, getenv *is* available in the Windows
* POSIX layer, just not setenv.
*
* Return: Success: 0
* Failure: non-zero error code
*
* Programmer: Dana Robinson
* February 2016
*
*-------------------------------------------------------------------------
*/
int
Wsetenv(const char *name, const char *value, int overwrite)
{
size_t bufsize;
errno_t err;
/* If we're not overwriting, check if the environment variable exists.
* If it does (i.e.: the required buffer size to store the variable's
* value is non-zero), then return an error code.
*/
if(!overwrite) {
err = getenv_s(&bufsize, NULL, 0, name);
if (err || bufsize)
return (int)err;
} /* end if */
return (int)_putenv_s(name, value);
} /* end Wsetenv() */
#ifdef H5_HAVE_WINSOCK2_H
#pragma comment(lib, "advapi32.lib")
#endif
#define WloginBuffer_count 256
static char Wlogin_buffer[WloginBuffer_count];
char*
Wgetlogin()
{
#ifdef H5_HAVE_WINSOCK2_H
long bufferCount = WloginBuffer_count;
if (GetUserName(Wlogin_buffer, &bufferCount) == 0)
return (Wlogin_buffer);
else
#endif /* H5_HAVE_WINSOCK2_H */
return NULL;
}
int c99_snprintf(char* str, size_t size, const char* format, ...)
{
int count;
va_list ap;
va_start(ap, format);
count = c99_vsnprintf(str, size, format, ap);
va_end(ap);
return count;
}
int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap)
{
int count = -1;
if (size != 0)
count = _vsnprintf_s(str, size, _TRUNCATE, format, ap);
if (count == -1)
count = _vscprintf(format, ap);
return count;
}
/*-------------------------------------------------------------------------
* Function: Wflock
*
* Purpose: Wrapper function for flock on Windows systems
*
* Return: Success: 0
* Failure: -1
*
*-------------------------------------------------------------------------
*/
int
Wflock(int H5_ATTR_UNUSED fd, int H5_ATTR_UNUSED operation) {
/* This is a no-op while we implement a Win32 VFD */
#if 0
int
Wflock(int fd, int operation) {
HANDLE hFile;
DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
DWORD dwReserved = 0;
/* MAXDWORD for entire file */
DWORD nNumberOfBytesToLockLow = MAXDWORD;
DWORD nNumberOfBytesToLockHigh = MAXDWORD;
/* Must initialize OVERLAPPED struct */
OVERLAPPED overlapped = {0};
/* Get Windows HANDLE */
hFile = _get_osfhandle(fd);
/* Convert to Windows flags */
if(operation & LOCK_EX)
dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
/* Lock or unlock */
if(operation & LOCK_UN)
if(0 == UnlockFileEx(hFile, dwReserved, nNumberOfBytesToLockLow,
nNumberOfBytesToLockHigh, &overlapped))
return -1;
else
if(0 == LockFileEx(hFile, dwFlags, dwReserved, nNumberOfBytesToLockLow,
nNumberOfBytesToLockHigh, &overlapped))
return -1;
#endif /* 0 */
return 0;
} /* end Wflock() */
/*--------------------------------------------------------------------------
* Function: Wnanosleep
*
* Purpose: Sleep for a given # of nanoseconds (Windows version)
*
* Return: SUCCEED/FAIL
*
* Programmer: Dana Robinson
* Fall 2016
*--------------------------------------------------------------------------
*/
int
Wnanosleep(const struct timespec *req, struct timespec *rem)
{
/* XXX: Currently just a placeholder */
return 0;
} /* end Wnanosleep() */
/*-------------------------------------------------------------------------
* Function: Wllround, Wllroundf, Wlround, Wlroundf, Wround, Wroundf
*
* Purpose: Wrapper function for round functions for use with VS2012
* and earlier.
*
* Return: The rounded value that was passed in.
*
* Programmer: Dana Robinson
* December 2016
*
*-------------------------------------------------------------------------
*/
long long
Wllround(double arg)
{
return (long long)(arg < 0.0 ? HDceil(arg - 0.5) : HDfloor(arg + 0.5));
}
long long
Wllroundf(float arg)
{
return (long long)(arg < 0.0F ? HDceil(arg - 0.5F) : HDfloor(arg + 0.5F));
}
long
Wlround(double arg)
{
return (long)(arg < 0.0 ? HDceil(arg - 0.5) : HDfloor(arg + 0.5));
}
long
Wlroundf(float arg)
{
return (long)(arg < 0.0F ? HDceil(arg - 0.5F) : HDfloor(arg + 0.5F));
}
double
Wround(double arg)
{
return arg < 0.0 ? HDceil(arg - 0.5) : HDfloor(arg + 0.5);
}
float
Wroundf(float arg)
{
return (float)(arg < 0.0F ? HDceil(arg - 0.5F) : HDfloor(arg + 0.5F));
}
#endif /* H5_HAVE_WIN32_API */
/*-------------------------------------------------------------------------
* Function: H5_build_extpath
*
* Purpose: To build the path for later searching of target file for external
* links and external files. This path can be either:
* 1. The absolute path of NAME
* or
* 2. The current working directory + relative path of NAME
*
* Return: SUCCEED/FAIL
*
* Programmer: Vailin Choi
* April 2, 2008
*
*-------------------------------------------------------------------------
*/
#define MAX_PATH_LEN 1024
herr_t
H5_build_extpath(const char *name, char **extpath /*out*/)
{
char *full_path = NULL; /* Pointer to the full path, as built or passed in */
char *cwdpath = NULL; /* Pointer to the current working directory path */
char *new_name = NULL; /* Pointer to the name of the file */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
/* Sanity check */
HDassert(name);
HDassert(extpath);
/* Clear external path pointer to begin with */
*extpath = NULL;
/*
* Unix: name[0] is a "/"
* Windows: name[0-2] is "<drive letter>:\" or "<drive-letter>:/"
*/
if(H5_CHECK_ABSOLUTE(name)) {
if(NULL == (full_path = (char *)H5MM_strdup(name)))
HGOTO_ERROR(H5E_INTERNAL, H5E_NOSPACE, FAIL, "memory allocation failed")
} /* end if */
else { /* relative pathname */
char *retcwd;
size_t name_len;
int drive;
if(NULL == (cwdpath = (char *)H5MM_malloc(MAX_PATH_LEN)))
HGOTO_ERROR(H5E_INTERNAL, H5E_NOSPACE, FAIL, "memory allocation failed")
name_len = HDstrlen(name) + 1;
if(NULL == (new_name = (char *)H5MM_malloc(name_len)))
HGOTO_ERROR(H5E_INTERNAL, H5E_NOSPACE, FAIL, "memory allocation failed")
/*
* Windows: name[0-1] is "<drive-letter>:"
* Get current working directory on the drive specified in NAME
* Unix: does not apply
*/
if(H5_CHECK_ABS_DRIVE(name)) {
drive = HDtoupper(name[0]) - 'A' + 1;
retcwd = HDgetdcwd(drive, cwdpath, MAX_PATH_LEN);
HDstrncpy(new_name, &name[2], name_len);
} /* end if */
/*
* Windows: name[0] is a '/' or '\'
* Get current drive
* Unix: does not apply
*/
else if(H5_CHECK_ABS_PATH(name) && (0 != (drive = HDgetdrive()))) {
HDsnprintf(cwdpath, MAX_PATH_LEN, "%c:%c", (drive + 'A' - 1), name[0]);
retcwd = cwdpath;
HDstrncpy(new_name, &name[1], name_len);
}
/* totally relative for Unix and Windows: get current working directory */
else {
retcwd = HDgetcwd(cwdpath, MAX_PATH_LEN);
HDstrncpy(new_name, name, name_len);
} /* end if */
if(retcwd != NULL) {
size_t cwdlen;
size_t path_len;
HDassert(cwdpath);
cwdlen = HDstrlen(cwdpath);
HDassert(cwdlen);
HDassert(new_name);
path_len = cwdlen + HDstrlen(new_name) + 2;
if(NULL == (full_path = (char *)H5MM_malloc(path_len)))
HGOTO_ERROR(H5E_INTERNAL, H5E_NOSPACE, FAIL, "memory allocation failed")
HDstrncpy(full_path, cwdpath, cwdlen + 1);
if(!H5_CHECK_DELIMITER(cwdpath[cwdlen - 1]))
HDstrncat(full_path, H5_DIR_SEPS, HDstrlen(H5_DIR_SEPS));
HDstrncat(full_path, new_name, HDstrlen(new_name));
} /* end if */
} /* end else */
/* strip out the last component (the file name itself) from the path */
if(full_path) {
char *ptr = NULL;
H5_GET_LAST_DELIMITER(full_path, ptr)
HDassert(ptr);
*++ptr = '\0';
*extpath = full_path;
} /* end if */
done:
/* Release resources */
if(cwdpath)
H5MM_xfree(cwdpath);
if(new_name)
H5MM_xfree(new_name);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5_build_extpath() */
/*--------------------------------------------------------------------------
* Function: H5_combine_path
*
* Purpose: If path2 is relative, interpret path2 as relative to path1
* and store the result in full_name. Otherwise store path2
* in full_name.
*
* Return: SUCCEED/FAIL
*
* Programmer: Steffen Kiess
* June 22, 2015
*--------------------------------------------------------------------------
*/
herr_t
H5_combine_path(const char* path1, const char* path2, char **full_name /*out*/)
{
size_t path1_len; /* length of path1 */
size_t path2_len; /* length of path2 */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
HDassert(path1);
HDassert(path2);
path1_len = HDstrlen(path1);
path2_len = HDstrlen(path2);
if(*path1 == '\0' || H5_CHECK_ABSOLUTE(path2)) {
/* If path1 is empty or path2 is absolute, simply use path2 */
if(NULL == (*full_name = (char *)H5MM_strdup(path2)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
} /* end if */
else if(H5_CHECK_ABS_PATH(path2)) {
/* On windows path2 is a path absolute name */
if (H5_CHECK_ABSOLUTE(path1) || H5_CHECK_ABS_DRIVE(path1)) {
/* path1 is absolute or drive absolute and path2 is path absolute.
* Use the drive letter of path1 + path2
*/
if(NULL == (*full_name = (char *)H5MM_malloc(path2_len + 3)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate path2 buffer")
HDsnprintf(*full_name, (path2_len + 3), "%c:%s", path1[0], path2);
} /* end if */
else {
/* On windows path2 is path absolute name ("\foo\bar"),
* path1 does not have a drive letter (i.e. is "a\b" or "\a\b").
* Use path2.
*/
if(NULL == (*full_name = (char *)H5MM_strdup(path2)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
} /* end else */
} /* end else if */
else {
/* Relative path2:
* Allocate a buffer to hold path1 + path2 + possibly the delimiter
* + terminating null byte
*/
if(NULL == (*full_name = (char *)H5MM_malloc(path1_len + path2_len + 2)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate filename buffer")
/* Compose the full file name */
HDsnprintf(*full_name, (path1_len + path2_len + 2), "%s%s%s", path1,
(H5_CHECK_DELIMITER(path1[path1_len - 1]) ? "" : H5_DIR_SEPS), path2);
} /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5_combine_path() */
/*--------------------------------------------------------------------------
* Function: H5_nanosleep
*
* Purpose: Sleep for a given # of nanoseconds
*
* Return: SUCCEED/FAIL
*
* Programmer: Quincey Koziol
* October 01, 2016
*--------------------------------------------------------------------------
*/
void
H5_nanosleep(uint64_t nanosec)
{
struct timespec sleeptime; /* Struct to hold time to sleep */
FUNC_ENTER_NOAPI_NOINIT_NOERR
/* Set up time to sleep */
sleeptime.tv_sec = 0;
sleeptime.tv_nsec = (long)nanosec;
HDnanosleep(&sleeptime, NULL);
FUNC_LEAVE_NOAPI_VOID
} /* end H5_nanosleep() */
/*--------------------------------------------------------------------------
* Function: H5_get_time
*
* Purpose: Get the current time, as the time of seconds after the UNIX epoch
*
* Return: SUCCEED/FAIL
*
* Programmer: Quincey Koziol
* October 05, 2016
*--------------------------------------------------------------------------
*/
double
H5_get_time(void)
{
#ifdef H5_HAVE_GETTIMEOFDAY
struct timeval curr_time;
#endif /* H5_HAVE_GETTIMEOFDAY */
double ret_value = (double)0.0f;
FUNC_ENTER_NOAPI_NOINIT_NOERR
#ifdef H5_HAVE_GETTIMEOFDAY
HDgettimeofday(&curr_time, NULL);
ret_value = (double)curr_time.tv_sec + ((double)curr_time.tv_usec / (double)1000000.0f);
#endif /* H5_HAVE_GETTIMEOFDAY */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5_get_time() */
#ifdef H5_HAVE_WIN32_API
#define H5_WIN32_ENV_VAR_BUFFER_SIZE 32767
/*-------------------------------------------------------------------------
* Function: H5_expand_windows_env_vars()
*
* Purpose: Replaces windows environment variables of the form %foo%
* with user-specific values.
*
* Return: SUCCEED/FAIL
*
*-------------------------------------------------------------------------
*/
herr_t
H5_expand_windows_env_vars(char **env_var)
{
long n_chars = 0;
char *temp_buf = NULL;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
/* Allocate buffer for expanded environment variable string */
if (NULL == (temp_buf = (char *)H5MM_calloc((size_t)H5_WIN32_ENV_VAR_BUFFER_SIZE)))
HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for expanded path")
/* Expand the environment variable string */
if ((n_chars = ExpandEnvironmentStringsA(*env_var, temp_buf, H5_WIN32_ENV_VAR_BUFFER_SIZE)) > H5_WIN32_ENV_VAR_BUFFER_SIZE)
HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "expanded path is too long")
if (0 == n_chars)
HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "failed to expand path")
*env_var = (char *)H5MM_xfree(*env_var);
*env_var = temp_buf;
done:
if (FAIL == ret_value && temp_buf)
temp_buf = (char *)H5MM_xfree(temp_buf);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5_expand_windows_env_vars() */
#endif /* H5_HAVE_WIN32_API */