/ libdarwin / stdlib.c
stdlib.c
  1  /*
  2   * Copyright (c) 2018 Apple Inc. All rights reserved.
  3   *
  4   * @APPLE_LICENSE_HEADER_START@
  5   *
  6   * This file contains Original Code and/or Modifications of Original Code
  7   * as defined in and that are subject to the Apple Public Source License
  8   * Version 2.0 (the 'License'). You may not use this file except in
  9   * compliance with the License. Please obtain a copy of the License at
 10   * http://www.opensource.apple.com/apsl/ and read it before using this
 11   * file.
 12   *
 13   * The Original Code and all software distributed under the License are
 14   * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 15   * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 16   * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 17   * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 18   * Please see the License for the specific language governing rights and
 19   * limitations under the License.
 20   *
 21   * @APPLE_LICENSE_HEADER_END@
 22   */
 23  #include "internal.h"
 24  
 25  #pragma mark API
 26  void
 27  os_localtime_file(char buff[static 32])
 28  {
 29  	struct timeval tv;
 30  	struct tm curtime;
 31  
 32  	posix_assert_zero(gettimeofday(&tv, NULL));
 33  	(void)localtime_r(&tv.tv_sec, &curtime);
 34  
 35  	// Return a time representation that is ideal for use in filenames, so no
 36  	// spaces or things that need to be escaped.
 37  	snprintf(buff, 32, "%d-%02d-%02d_%02d.%02d.%02d.%06d",
 38  			curtime.tm_year + 1900, curtime.tm_mon + 1, curtime.tm_mday,
 39  			curtime.tm_hour, curtime.tm_min, curtime.tm_sec, tv.tv_usec);
 40  }
 41  
 42  // MurmurHash2 was written by Austin Appleby, and is placed in the public
 43  // domain. The author hereby disclaims copyright to this source code.
 44  uint64_t
 45  os_simple_hash_with_seed(const void *buff, size_t len, uint64_t seed)
 46  {
 47  #ifdef __LP64__
 48  	// MurmurHash64A
 49  	const uint64_t m = 0xc6a4a7935bd1e995;
 50  	const int r = 47;
 51  	uint64_t h = seed ^ (len * m);
 52  	const uint64_t * data = (const uint64_t *)buff;
 53  	const uint64_t * end = data + (len / 8);
 54  	while(data != end) {
 55  		uint64_t k = *data++;
 56  		k *= m;
 57  		k ^= k >> r;
 58  		k *= m;
 59  		h ^= k;
 60  		h *= m;
 61  	}
 62  	const unsigned char * data2 = (const unsigned char *)data;
 63  	switch(len & 7) {
 64  	case 7: h ^= ((uint64_t)data2[6]) << 48;
 65  	case 6: h ^= ((uint64_t)data2[5]) << 40;
 66  	case 5: h ^= ((uint64_t)data2[4]) << 32;
 67  	case 4: h ^= ((uint64_t)data2[3]) << 24;
 68  	case 3: h ^= ((uint64_t)data2[2]) << 16;
 69  	case 2: h ^= ((uint64_t)data2[1]) << 8;
 70  	case 1: h ^= ((uint64_t)data2[0]);
 71  			h *= m;
 72  	};
 73  	h ^= h >> r;
 74  	h *= m;
 75  	h ^= h >> r;
 76  #else // __LP64__
 77  	// MurmurHash64B
 78  	const uint32_t m = 0x5bd1e995;
 79  	const int r = 24;
 80  
 81  	uint32_t h1 = (uint32_t)(seed) ^ len;
 82  	uint32_t h2 = (uint32_t)(seed >> 32);
 83  
 84  	const uint32_t * data = (const uint32_t *)buff;
 85  
 86  #define MIX(k, h) \
 87  	(k) *= m; (k) ^= (k) >> r; (k) *= m; (h) *= m; (h) ^= (k); len -= 4;
 88  
 89  	while(len >= 8) {
 90  		uint32_t k[2];
 91  		memcpy(k, (const char*)data, sizeof(k));
 92  		data += sizeof(k)/sizeof(k[0]);
 93  
 94  		MIX(k[0], h1)
 95  		MIX(k[1], h2)
 96  	}
 97  
 98  	if(len >= 4) {
 99  		uint32_t k[1];
100  		memcpy(k, (const char *)data, sizeof(k));
101  		data += sizeof(k)/sizeof(k[0]);
102  
103  		MIX(k[0], h1);
104  	}
105  
106  #undef MIX
107  
108  	switch(len) {
109  	case 3: h2 ^= ((unsigned char*)data)[2] << 16;
110  	case 2: h2 ^= ((unsigned char*)data)[1] << 8;
111  	case 1: h2 ^= ((unsigned char*)data)[0];
112  			h2 *= m;
113  	};
114  
115  	h1 ^= h2 >> 18; h1 *= m;
116  	h2 ^= h1 >> 22; h2 *= m;
117  	h1 ^= h2 >> 17; h1 *= m;
118  	h2 ^= h1 >> 19; h2 *= m;
119  
120  	uint64_t h = h1;
121  
122  	h = (h << 32) | h2;
123  #endif // __LP64__
124  	return h;
125  }
126  
127  uint64_t
128  os_simple_hash(const void *buff, size_t len)
129  {
130  	return os_simple_hash_with_seed(buff, len, 0);
131  }
132  
133  uint64_t
134  os_simple_hash_string_with_seed(const char *string, uint64_t seed)
135  {
136  	size_t len = strlen(string);
137  	return os_simple_hash_with_seed(string, len, seed);
138  }
139  
140  uint64_t
141  os_simple_hash_string(const char *string)
142  {
143  	return os_simple_hash_string_with_seed(string, 0);
144  }
145  
146  errno_t
147  realpath_np(os_fd_t fd, char buff[static PATH_MAX])
148  {
149  	errno_t error = -1;
150  	int ret = -1;
151  
152  	ret = fcntl(fd, F_GETPATH, buff);
153  	if (ret) {
154  		error = errno;
155  	} else {
156  		error = 0;
157  	}
158  
159  	return error;
160  }
161  
162  errno_t
163  memdup_np(void **_new, const void *src, size_t len)
164  {
165  	void *mynew = NULL;
166  
167  	mynew = malloc(len);
168  	if (!mynew) {
169  		return errno;
170  	}
171  
172  	memcpy(mynew, src, len);
173  	*_new = mynew;
174  	return 0;
175  }
176  
177  void *
178  memdup2_np(const void *src, size_t len)
179  {
180  	void *_new = os_malloc(len);
181  	memcpy(_new, src, len);
182  	return _new;
183  }