99 #define MAIN_ERR_PREFIX "POSIX: "
105 #if CFG_USE_POSIX_API >= 200809
107 extern int posix_dummy;
123 # define MEMDEBUG_ARRAY_SIZE (size_t) 100000
124 static posix_pthread_mutex_t memdebug_mutex = POSIX_PTHREAD_MUTEX_INITIALIZER;
125 static void* memdebug_array[MEMDEBUG_ARRAY_SIZE];
126 static size_t memdebug_size[MEMDEBUG_ARRAY_SIZE];
127 static size_t memdebug_num = 0;
130 void* posix_malloc(
size_t len)
134 if(!posix_pthread_mutex_lock(&memdebug_mutex))
136 if(MEMDEBUG_ARRAY_SIZE <= memdebug_num + (
size_t) 1)
147 memdebug_array[memdebug_num] = p;
148 memdebug_size[memdebug_num] = len;
152 posix_pthread_mutex_unlock(&memdebug_mutex);
160 void posix_free(
void* p)
164 if(!posix_pthread_mutex_lock(&memdebug_mutex))
169 for(i = 0; i < memdebug_num; ++i)
171 if(memdebug_array[i] == p) {
break; }
173 if(i >= memdebug_num)
175 PRINT_ERROR(
"free(): Invalid address (thread frozen)");
180 for(ii = i; ii < memdebug_num; ++ii)
182 memdebug_array[ii] = memdebug_array[ii + 1];
183 memdebug_size[ii] = memdebug_size[ii + 1];
188 posix_pthread_mutex_unlock(&memdebug_mutex);
196 void* posix_realloc(
void* p,
size_t len)
198 void* q = posix_malloc(len);
202 if(!posix_pthread_mutex_lock(&memdebug_mutex))
206 printf(
"%s: %sMEMDBG: R: %p => %p\n", CFG_NAME,
MAIN_ERR_PREFIX, p, q);
207 for(i = 0; i < memdebug_num; ++i)
209 if(memdebug_array[i] == p) {
break; }
211 if(i >= memdebug_num)
213 PRINT_ERROR(
"realloc(): Invalid address (thread frozen)");
219 oldlen = memdebug_size[i];
220 if(len > oldlen) { len = oldlen; }
224 posix_pthread_mutex_unlock(&memdebug_mutex);
228 if(NULL == q) {
PRINT_ERROR(
"realloc(): Failed"); }
229 else { posix_free(p); }
244 static posix_pthread_mutex_t random_mutex = POSIX_PTHREAD_MUTEX_INITIALIZER;
245 static long int random_state = 1;
247 void posix_srandom(
unsigned int seed)
249 if(!posix_pthread_mutex_lock(&random_mutex))
251 random_state = (
long int) (seed * 2U);
252 posix_pthread_mutex_unlock(&random_mutex);
257 long int posix_random(
void)
261 if(!posix_pthread_mutex_lock(&random_mutex))
269 if(POSIX_LONG_MAX > random_state) { ++random_state; }
270 else { random_state = 0; }
271 posix_pthread_mutex_unlock(&random_mutex);
286 int posix_fsync(
int fd)
294 #if CFG_USE_POSIX_API < 200809
309 static posix_pthread_mutex_t scandir_mutex = POSIX_PTHREAD_MUTEX_INITIALIZER;
310 static int scandir_readentry(POSIX_DIR* dirp, struct_posix_dirent** entryp,
314 struct_posix_dirent* e;
316 if(!posix_pthread_mutex_lock(&scandir_mutex))
323 e = posix_readdir(dirp);
337 *len = offsetof(struct_posix_dirent, d_name) + strlen(e->d_name)
339 *entryp = (struct_posix_dirent *) posix_malloc(*len);
342 memcpy((
void*) *entryp, (
void*) e, *len);
344 ((
char *) *entryp)[*len - (size_t) 1] = 0;
356 posix_pthread_mutex_unlock(&scandir_mutex);
361 #define SCANDIR_ENTRIES_MIN (size_t) 32
362 int posix_scandir(
const char* dir, struct_posix_dirent*** namelist,
363 int (*sel)(struct_posix_dirent*),
364 int (*compar)(
const struct_posix_dirent**,
365 const struct_posix_dirent**))
370 size_t max = SCANDIR_ENTRIES_MIN;
371 struct_posix_dirent* entryp = NULL;
372 struct_posix_dirent** entries;
373 struct_posix_dirent** p;
375 entries = (struct_posix_dirent**) posix_malloc(
sizeof(*entries) * max);
379 dirp = posix_opendir(dir);
383 while (!scandir_readentry(dirp, &entryp, &len))
392 if(NULL != sel) {
if(!sel(entryp))
continue; }
393 entries[num++] = entryp;
397 if(POSIX_INT_MAX / 2 >= (
int) max) { max *= (size_t) 2; }
403 p = (struct_posix_dirent**) posix_realloc((
void*) entries,
404 sizeof(*entries) * max);
405 if(NULL != p) { entries = p; }
409 posix_closedir(dirp);
421 qsort((
void*) entries, num,
sizeof(*entries),
422 (
int (*)(
const void*,
const void*)) compar);
431 while(num--) { posix_free((
void*) entries[num]); }
432 posix_free((
void*) entries);
440 #if CFG_USE_POSIX_API < 200809 && !CFG_USE_XSI
441 static unsigned long int mkstemp_state = 0;
442 static posix_pthread_mutex_t mkstemp_mutex = POSIX_PTHREAD_MUTEX_INITIALIZER;
443 int posix_mkstemp(
char*
template)
445 const int oflag = POSIX_O_RDWR | POSIX_O_CREAT | POSIX_O_EXCL;
446 const posix_mode_t mode = POSIX_S_IRUSR | POSIX_S_IWUSR;
448 unsigned long int unique;
454 if(!posix_pthread_mutex_lock(&mkstemp_mutex))
456 if(999999UL > mkstemp_state) { ++mkstemp_state; }
457 else { mkstemp_state = 0; }
458 unique = mkstemp_state;
459 posix_pthread_mutex_unlock(&mkstemp_mutex);
462 pos = strlen(
template);
463 if((
size_t) 6 > pos) { error = 1; }
467 if(strcmp(
"XXXXXX", &
template[pos])) { error = 1; }
469 if(error) { posix_errno = POSIX_EINVAL; }
472 rv = posix_snprintf(uni, (
size_t) 7,
"%06lu", unique);
475 strncpy(&
template[pos], uni, (
size_t) 7);
476 res = posix_open(
template, oflag, mode);
489 #if CFG_USE_POSIX_API < 200809
495 posix_locale_t posix_newlocale(
int category_mask,
const char* locale,
498 posix_locale_t res = 0;
500 if(POSIX_LC_CTYPE_MASK != category_mask) { posix_errno = POSIX_EINVAL; }
503 if(strcmp(locale,
"POSIX")) { posix_errno = POSIX_ENOENT; }
511 void posix_freelocale(posix_locale_t locobj)
520 int posix_strncasecmp_l(
const char* s1,
const char* s2,
size_t n,
521 posix_locale_t locale)
529 for(i = 0; i < n; ++i)
531 c1 = (int) (
unsigned char) s1[i];
532 c2 = (int) (
unsigned char) s2[i];
534 if(65 <= c1 && 90 >= c1) { c1 = (c1 - 65) + 97; }
535 if(65 <= c2 && 90 >= c2) { c2 = (c2 - 65) + 97; }
538 if(!c1 || !c2 || res) {
break; }
545 int posix_strcasecmp_l(
const char* s1,
const char* s2,
546 posix_locale_t locale)
548 return(posix_strncasecmp_l(s1, s2, POSIX_SIZE_MAX, locale));
556 #if CFG_USE_POSIX_API < 200112
594 # define SNPRINTF_RESET(c) \
605 int posix_snprintf(
char* s,
size_t n,
const char* f, ...)
610 int err_no = POSIX_EINVAL;
619 const size_t fn = strlen(f);
625 const char* c_s =
"";
638 unsigned long int u_p10 = 0;
639 unsigned long int u_lim;
641 unsigned long int u_p16 = 0;
642 unsigned long int u_dig;
649 unsigned long int ui;
661 PRINT_ERROR(
"snprintf(): Calling with zero buffer size is not portable");
662 err_no = POSIX_EINVAL;
668 PRINT_ERROR(
"snprintf(): NULL for buffer, but nonzero buffer size");
669 err_no = POSIX_EINVAL;
674 else if((
unsigned int) POSIX_INT_MAX < n)
676 err_no = POSIX_EOVERFLOW;
691 cn = strcspn(&f[fi],
"%");
741 mod_w = (int) cc - 48;
748 if(mod_l) { d_lim = POSIX_LONG_MAX; }
749 else { d_lim = (
long int) POSIX_INT_MAX; }
750 d_p10 = 10000L; exp = 4;
753 if(10 > d_lim / d_p10) {
break; }
757 bn = exp + (size_t) 3;
759 b = (
char*) posix_realloc((
void*) b, bn);
760 if (NULL == b) { err_no = POSIX_ENOMEM; err = 1;
break; }
762 if(mod_l) { d = va_arg(ap,
long int); }
763 else { d = (
long int) va_arg(ap,
int); }
772 if(!mod_w) { b[ci++] =
'-'; }
776 if (mod_z) { b[ci++] =
'-'; }
788 if(ds) { b[ci++] =
'-'; ds = 0; }
789 b[ci++] = (char) (48L + d / i);
794 if(!d && -1L == i) { b[ci++] =
'0'; }
800 if(!mod_z) { b[ci++] =
' '; }
801 else { b[ci++] =
'0'; }
805 else { b[ci++] =
'0'; }
807 if(ci >= bn) {
break; }
810 if(ci >= bn) { si = POSIX_SIZE_MAX; err = 1;
break; }
821 if(mod_l) { u_lim = POSIX_ULONG_MAX; }
822 else { u_lim = (
long int) POSIX_UINT_MAX; }
823 u_p10 = 10000UL; exp = 4;
826 if(10 > u_lim / u_p10) {
break; }
830 bn = exp + (size_t) 2;
832 b = (
char*) posix_realloc((
void*) b, bn);
833 if (NULL == b) { err_no = POSIX_ENOMEM; err = 1;
break; }
835 if(mod_l) { u = va_arg(ap,
unsigned long int); }
836 else { u = (
unsigned long int) va_arg(ap,
unsigned int); }
845 b[ci++] = (char) (48UL + u / ui);
850 if(!u && 1UL == ui) { b[ci++] =
'0'; }
856 if(!mod_z) { b[ci++] =
' '; }
857 else { b[ci++] =
'0'; }
861 else { b[ci++] =
'0'; }
863 if(ci >= bn) {
break; }
866 if(ci >= bn) { si = POSIX_SIZE_MAX; err = 1;
break; }
882 if(mod_l) { u_lim = POSIX_ULONG_MAX; }
883 else { u_lim = (
long int) POSIX_UINT_MAX; }
884 u_p16 = 4096UL; exp = 3;
887 if(16 > u_lim / u_p16) {
break; }
891 bn = exp + (size_t) 2;
893 b = (
char*) posix_realloc((
void*) b, bn);
894 if (NULL == b) { err_no = POSIX_ENOMEM; err = 1;
break; }
896 if(mod_l) { u = va_arg(ap,
unsigned long int); }
897 else { u = (
unsigned long int) va_arg(ap,
unsigned int); }
907 if(10UL > u_dig) { b[ci++] = (char) (48UL + u_dig); }
911 if(hex_capital) { b[ci++] = (char) (65UL + u_dig); }
912 else { b[ci++] = (char) (97UL + u_dig); }
918 if(!u && 1UL == ui) { b[ci++] =
'0'; }
924 if(!mod_z) { b[ci++] =
' '; }
925 else { b[ci++] =
'0'; }
929 else { b[ci++] =
'0'; }
931 if(ci >= bn) {
break; }
934 if(ci >= bn) { si = POSIX_SIZE_MAX; err = 1;
break; }
945 PRINT_ERROR(
"snprintf(): Invalid modifier in conversion");
950 c_s = va_arg(ap,
char*);
956 PRINT_ERROR(
"snprintf(): Conversion type not supported");
970 if(POSIX_SIZE_MAX - sn < cn) { sn = POSIX_SIZE_MAX; }
975 if(n && (si < n - 1) && cn)
977 if(n - 1 - si < cn) { cn = n - 1 - si; }
978 memcpy(&s[si], c_s, cn);
983 posix_free((
void*) b);
989 PRINT_ERROR(
"snprintf(): AAARGHHH, buffer overflow detected!");
992 err_no = POSIX_EOVERFLOW;
997 if(!err) { res = (int) sn; }
1000 posix_errno = err_no;
1011 #if CFG_USE_POSIX_API < 200809
1016 #define GETLINE_BLOCKSIZE (size_t) 128
1017 posix_ssize_t posix_getline(
char** lineptr,
size_t* n, FILE* stream)
1019 posix_ssize_t res = -1;
1023 size_t mems = GETLINE_BLOCKSIZE;
1028 if(NULL == lineptr || NULL == n) { posix_errno = POSIX_EINVAL; }
1032 if (NULL == *lineptr)
1034 *lineptr = (
char*) posix_malloc(GETLINE_BLOCKSIZE);
1035 if(NULL == *lineptr) { posix_errno = POSIX_ENOMEM; }
1036 else { len = *n = GETLINE_BLOCKSIZE; }
1040 if(NULL != *lineptr)
1043 if((
size_t) POSIX_SSIZE_MAX < len) { len = (size_t) POSIX_SSIZE_MAX; }
1046 while((
size_t) POSIX_SSIZE_MAX > pos && mems)
1051 if(GETLINE_BLOCKSIZE > POSIX_SIZE_MAX - len)
1053 mems = POSIX_SIZE_MAX - len;
1056 posix_errno = POSIX_ENOMEM;
1060 memp = posix_realloc(*lineptr, *n + mems);
1063 posix_errno = POSIX_ENOMEM;
1078 (*lineptr)[pos] = 0;
1079 res = (posix_ssize_t) pos;
1084 rv = posix_fgetc(stream);
1085 if(EOF == rv)
break;
1086 (*lineptr)[pos++] = (char) rv;
1087 if(
'\n' == (
char) rv)
1095 if((
size_t) POSIX_SSIZE_MAX <= pos)
1097 posix_errno = POSIX_EOVERFLOW;
1110 #if CFG_USE_POSIX_API < 200112 && !CFG_USE_IP6
1112 void posix_freeaddrinfo(struct_posix_addrinfo* info)
1114 struct_posix_addrinfo* next;
1119 next = info->ai_next;
1121 posix_free((
void*) info);
1139 static posix_pthread_mutex_t getaddrinfo_mutex
1140 = POSIX_PTHREAD_MUTEX_INITIALIZER;
1141 int posix_getaddrinfo(
const char* nodename,
const char* servname,
1142 const struct_posix_addrinfo* hints,
1143 struct_posix_addrinfo** result)
1146 struct_posix_addrinfo* info = NULL;
1147 struct_posix_addrinfo* tmp = NULL;
1148 struct_posix_servent* se;
1149 struct_posix_hostent* he;
1151 posix_in_port_t port = 0;
1153 int family = hints->ai_family;
1158 if(POSIX_AF_UNSPEC == family) { family = POSIX_AF_INET; }
1161 if(NULL == nodename)
1163 PRINT_ERROR(
"getaddrinfo(): Call without nodename not supported");
1164 res = POSIX_EAI_FAIL;
1166 else if(POSIX_AF_INET != family)
1169 res = POSIX_EAI_FAMILY;
1171 else if (POSIX_SOCK_STREAM != hints->ai_socktype)
1174 res = POSIX_EAI_SOCKTYPE;
1178 if(NULL != servname)
1181 if(posix_pthread_mutex_lock(&getaddrinfo_mutex))
1183 PRINT_ERROR(
"getaddrinfo(): Locking mutex failed");
1184 res = POSIX_EAI_AGAIN;
1192 res = POSIX_EAI_AGAIN;
1197 if(1 == sscanf(servname,
"%u", &p))
1199 port = (posix_in_port_t) posix_htons((posix_in_port_t) p);
1203 se = posix_getservbyname(servname, NULL);
1204 if(NULL != se) { port = (posix_in_port_t) se->s_port; }
1217 posix_pthread_mutex_unlock(&getaddrinfo_mutex);
1222 if(NULL != servname && !port)
1224 PRINT_ERROR(
"getaddrinfo(): Service resolution failed");
1225 res = POSIX_EAI_FAIL;
1227 else if(posix_pthread_mutex_lock(&getaddrinfo_mutex))
1229 PRINT_ERROR(
"getaddrinfo(): Locking mutex failed");
1230 res = POSIX_EAI_AGAIN;
1238 res = POSIX_EAI_AGAIN;
1242 he = posix_gethostbyname(nodename);
1243 if(NULL == he) { res = POSIX_EAI_NONAME; }
1244 else if(POSIX_AF_INET != he->h_addrtype || 4 != he->h_length)
1246 PRINT_ERROR(
"getaddrinfo(): Address type not supported");
1247 res = POSIX_EAI_FAIL;
1254 tmp = (struct_posix_addrinfo*)
1255 posix_malloc(
sizeof(struct_posix_addrinfo)
1256 +
sizeof(struct_posix_sockaddr_in));
1257 if(NULL == tmp) { res = POSIX_EAI_MEMORY;
break; }
1260 if(NULL == info) { *result = info = tmp; }
1261 else { info = info->ai_next = tmp; }
1263 memset((
void*) info, 0,
sizeof(struct_posix_addrinfo));
1264 info->ai_family = POSIX_AF_INET;
1265 info->ai_socktype = hints->ai_socktype;
1266 info->ai_protocol = hints->ai_protocol;
1268 = (posix_socklen_t)
sizeof(struct_posix_sockaddr_in);
1270 = (struct_posix_sockaddr*) (
void*)
1271 ((
char*) (
void*) info +
sizeof(struct_posix_addrinfo));
1272 ((struct_posix_sockaddr_in*) info->ai_addr)->sin_family
1273 = (posix_sa_family_t) info->ai_family;
1274 ((struct_posix_sockaddr_in*) info->ai_addr)->sin_port
1276 ((struct_posix_sockaddr_in*) info->ai_addr)
1278 = *((posix_in_addr_t*) he->h_addr_list[num++]);
1279 info->ai_next = NULL;
1282 printf(
"%s: %sgetaddrinfo(): Resolve result: "
1285 inet_ntoa(((struct_posix_sockaddr_in*)info->ai_addr)
1287 (
unsigned int) posix_ntohs(port));
1292 while(NULL != he->h_addr_list[num]);
1305 posix_pthread_mutex_unlock(&getaddrinfo_mutex);
1307 printf(
"%s: %sgetaddrinfo(): %u result(s)\n",
1315 printf(
"%s: %sgetaddrinfo(): Result: %d\n",
1318 if(res) { posix_freeaddrinfo(*result); }
1325 const char* posix_gai_strerror(
int ecode)
1331 case POSIX_EAI_AGAIN:
1333 res =
"Name could not be resolved at this time";
1336 case POSIX_EAI_BADFLAGS:
1338 res =
"Parameter had an invalid value";
1341 case POSIX_EAI_FAIL:
1343 res =
"Non-recoverable error occurred while resolving the name";
1346 case POSIX_EAI_FAMILY:
1348 res =
"Address family was not recognized";
1351 case POSIX_EAI_MEMORY:
1353 res =
"Memory allocation failed";
1356 case POSIX_EAI_NONAME:
1358 res =
"Name does not resolve for the supplied parameters";
1361 case POSIX_EAI_OVERFLOW:
1363 res =
"Argument buffer overflowed (passed buffer too small)";
1366 case POSIX_EAI_SERVICE:
1368 res =
"Service passed not recognized for the specified socket type";
1371 case POSIX_EAI_SOCKTYPE:
1373 res =
"Intended socket type was not recognized";
1376 case POSIX_EAI_SYSTEM:
1378 res =
"System error occurred";
1383 res =
"Unknown error occurred";
1396 #if CFG_USE_POSIX_API < 200112
1397 int posix_inet_pton(
int af,
const char* src,
void* dst)
1400 posix_in_addr_t addr;
1411 errno = EAFNOSUPPORT;
1419 addr = (posix_in_addr_t) posix_inet_addr(src);
1420 if((posix_in_addr_t) -1 == addr) { res = 0; }
1424 *((
unsigned char*) dst) = *((
unsigned char*) &addr);
1425 *((
unsigned char*) dst + 1) = *((
unsigned char*) &addr + 1);
1426 *((
unsigned char*) dst + 2) = *((
unsigned char*) &addr + 2);
1427 *((
unsigned char*) dst + 3) = *((
unsigned char*) &addr + 3);