106 #define MAIN_ERR_PREFIX "POSIX: "
112 #if CFG_USE_POSIX_API >= 200809
114 extern int api_posix_dummy;
115 int api_posix_dummy = 0;
130 # define MEMDEBUG_ARRAY_SIZE (size_t) 100000
131 static api_posix_pthread_mutex_t memdebug_mutex
132 = API_POSIX_PTHREAD_MUTEX_INITIALIZER;
133 static void* memdebug_array[MEMDEBUG_ARRAY_SIZE];
134 static size_t memdebug_size[MEMDEBUG_ARRAY_SIZE];
135 static size_t memdebug_num = 0;
138 void* api_posix_malloc(
size_t len)
142 if(!api_posix_pthread_mutex_lock(&memdebug_mutex))
144 if(MEMDEBUG_ARRAY_SIZE <= memdebug_num + (
size_t) 1)
155 memdebug_array[memdebug_num] = p;
156 memdebug_size[memdebug_num] = len;
160 api_posix_pthread_mutex_unlock(&memdebug_mutex);
168 void api_posix_free(
void* p)
172 if(!api_posix_pthread_mutex_lock(&memdebug_mutex))
177 for(i = 0; i < memdebug_num; ++i)
179 if(memdebug_array[i] == p) {
break; }
181 if(i >= memdebug_num)
183 PRINT_ERROR(
"free(): Invalid address (thread frozen)");
188 for(ii = i; ii < memdebug_num; ++ii)
190 memdebug_array[ii] = memdebug_array[ii + 1];
191 memdebug_size[ii] = memdebug_size[ii + 1];
196 api_posix_pthread_mutex_unlock(&memdebug_mutex);
204 void* api_posix_realloc(
void* p,
size_t len)
206 void* q = api_posix_malloc(len);
210 if(!api_posix_pthread_mutex_lock(&memdebug_mutex))
214 printf(
"%s: %sMEMDBG: R: %p => %p\n", CFG_NAME,
MAIN_ERR_PREFIX, p, q);
215 for(i = 0; i < memdebug_num; ++i)
217 if(memdebug_array[i] == p) {
break; }
219 if(i >= memdebug_num)
221 PRINT_ERROR(
"realloc(): Invalid address (thread frozen)");
227 oldlen = memdebug_size[i];
228 if(len > oldlen) { len = oldlen; }
232 api_posix_pthread_mutex_unlock(&memdebug_mutex);
236 if(NULL == q) {
PRINT_ERROR(
"realloc(): Failed"); }
237 else { api_posix_free(p); }
252 static api_posix_pthread_mutex_t random_mutex
253 = API_POSIX_PTHREAD_MUTEX_INITIALIZER;
254 static long int random_state = 1;
256 void api_posix_srandom(
unsigned int seed)
258 if(!api_posix_pthread_mutex_lock(&random_mutex))
260 random_state = (
long int) (seed * 2U);
261 api_posix_pthread_mutex_unlock(&random_mutex);
266 long int api_posix_random(
void)
270 if(!api_posix_pthread_mutex_lock(&random_mutex))
278 if(API_POSIX_LONG_MAX > random_state) { ++random_state; }
279 else { random_state = 0; }
280 api_posix_pthread_mutex_unlock(&random_mutex);
295 int api_posix_fsync(
int fd)
303 #if CFG_USE_POSIX_API < 200809
318 static api_posix_pthread_mutex_t scandir_mutex
319 = API_POSIX_PTHREAD_MUTEX_INITIALIZER;
320 static int scandir_readentry(API_POSIX_DIR* dirp,
321 api_posix_struct_dirent** entryp,
325 api_posix_struct_dirent* e;
327 if(!api_posix_pthread_mutex_lock(&scandir_mutex))
334 e = api_posix_readdir(dirp);
348 *len = offsetof(api_posix_struct_dirent, d_name) + strlen(e->d_name)
350 *entryp = (api_posix_struct_dirent *) api_posix_malloc(*len);
353 memcpy((
void*) *entryp, (
void*) e, *len);
355 ((
char *) *entryp)[*len - (size_t) 1] = 0;
367 api_posix_pthread_mutex_unlock(&scandir_mutex);
372 #define SCANDIR_ENTRIES_MIN (size_t) 32
373 int api_posix_scandir(
const char* dir, api_posix_struct_dirent*** namelist,
374 int (*sel)(api_posix_struct_dirent*),
375 int (*compar)(
const api_posix_struct_dirent**,
376 const api_posix_struct_dirent**))
381 size_t max = SCANDIR_ENTRIES_MIN;
382 api_posix_struct_dirent* entryp = NULL;
383 api_posix_struct_dirent** entries;
384 api_posix_struct_dirent** p;
387 = (api_posix_struct_dirent**) api_posix_malloc(
sizeof(*entries) * max);
391 dirp = api_posix_opendir(dir);
395 while (!scandir_readentry(dirp, &entryp, &len))
404 if(NULL != sel) {
if(!sel(entryp))
continue; }
405 entries[num++] = entryp;
409 if(API_POSIX_INT_MAX / 2 >= (
int) max) { max *= (size_t) 2; }
412 api_posix_errno = API_POSIX_ENOMEM;
415 p = (api_posix_struct_dirent**) api_posix_realloc((
void*) entries,
416 sizeof(*entries) * max);
417 if(NULL != p) { entries = p; }
421 api_posix_closedir(dirp);
433 qsort((
void*) entries, num,
sizeof(*entries),
434 (
int (*)(
const void*,
const void*)) compar);
443 while(num--) { api_posix_free((
void*) entries[num]); }
444 api_posix_free((
void*) entries);
452 #if CFG_USE_POSIX_API < 200809 && !CFG_USE_XSI
453 static unsigned long int mkstemp_state = 0;
454 static api_posix_pthread_mutex_t mkstemp_mutex
455 = API_POSIX_PTHREAD_MUTEX_INITIALIZER;
456 int api_posix_mkstemp(
char*
template)
458 const int oflag = API_POSIX_O_RDWR | API_POSIX_O_CREAT | API_POSIX_O_EXCL;
459 const api_posix_mode_t mode = API_POSIX_S_IRUSR | API_POSIX_S_IWUSR;
461 unsigned long int unique;
467 if(!api_posix_pthread_mutex_lock(&mkstemp_mutex))
469 if(999999UL > mkstemp_state) { ++mkstemp_state; }
470 else { mkstemp_state = 0; }
471 unique = mkstemp_state;
472 api_posix_pthread_mutex_unlock(&mkstemp_mutex);
475 pos = strlen(
template);
476 if((
size_t) 6 > pos) { error = 1; }
480 if(strcmp(
"XXXXXX", &
template[pos])) { error = 1; }
482 if(error) { api_posix_errno = API_POSIX_EINVAL; }
485 rv = api_posix_snprintf(uni, (
size_t) 7,
"%06lu", unique);
488 strncpy(&
template[pos], uni, (
size_t) 7);
489 res = api_posix_open(
template, oflag, mode);
502 #if CFG_USE_POSIX_API < 200809
508 api_posix_locale_t api_posix_newlocale(
int category_mask,
const char* locale,
509 api_posix_locale_t base)
511 api_posix_locale_t res = 0;
515 if(API_POSIX_LC_CTYPE_MASK != category_mask)
517 api_posix_errno = API_POSIX_EINVAL;
521 if(strcmp(locale,
"POSIX")) { api_posix_errno = API_POSIX_ENOENT; }
529 void api_posix_freelocale(api_posix_locale_t locobj)
539 int api_posix_strncasecmp_l(
const char* s1,
const char* s2,
size_t n,
540 api_posix_locale_t locale)
550 for(i = 0; i < n; ++i)
552 c1 = (int) (
unsigned char) s1[i];
553 c2 = (int) (
unsigned char) s2[i];
555 if(65 <= c1 && 90 >= c1) { c1 = (c1 - 65) + 97; }
556 if(65 <= c2 && 90 >= c2) { c2 = (c2 - 65) + 97; }
559 if(!c1 || !c2 || res) {
break; }
566 int api_posix_strcasecmp_l(
const char* s1,
const char* s2,
567 api_posix_locale_t locale)
569 return(api_posix_strncasecmp_l(s1, s2, API_POSIX_SIZE_MAX, locale));
577 #if CFG_USE_POSIX_API < 200112
615 # define SNPRINTF_RESET(c) \
626 int api_posix_snprintf(
char* s,
size_t n,
const char* f, ...)
631 int err_no = API_POSIX_EINVAL;
640 const size_t fn = strlen(f);
646 const char* c_s =
"";
659 unsigned long int u_p10 = 0;
660 unsigned long int u_lim;
662 unsigned long int u_p16 = 0;
663 unsigned long int u_dig;
670 unsigned long int ui;
682 PRINT_ERROR(
"snprintf(): Calling with zero buffer size is not portable");
683 err_no = API_POSIX_EINVAL;
689 PRINT_ERROR(
"snprintf(): NULL for buffer, but nonzero buffer size");
690 err_no = API_POSIX_EINVAL;
695 else if((
unsigned int) API_POSIX_INT_MAX < n)
697 err_no = API_POSIX_EOVERFLOW;
712 cn = strcspn(&f[fi],
"%");
762 mod_w = (int) cc - 48;
769 if(mod_l) { d_lim = API_POSIX_LONG_MAX; }
770 else { d_lim = (
long int) API_POSIX_INT_MAX; }
771 d_p10 = 10000L; exp = 4;
774 if(10 > d_lim / d_p10) {
break; }
778 bn = exp + (size_t) 3;
780 b = (
char*) api_posix_realloc((
void*) b, bn);
783 err_no = API_POSIX_ENOMEM; err = 1;
787 if(mod_l) { d = va_arg(ap,
long int); }
788 else { d = (
long int) va_arg(ap,
int); }
797 if(!mod_w) { b[ci++] =
'-'; }
801 if (mod_z) { b[ci++] =
'-'; }
813 if(ds) { b[ci++] =
'-'; ds = 0; }
814 b[ci++] = (char) (48L + d / i);
819 if(!d && -1L == i) { b[ci++] =
'0'; }
825 if(!mod_z) { b[ci++] =
' '; }
826 else { b[ci++] =
'0'; }
830 else { b[ci++] =
'0'; }
832 if(ci >= bn) {
break; }
835 if(ci >= bn) { si = API_POSIX_SIZE_MAX; err = 1;
break; }
846 if(mod_l) { u_lim = API_POSIX_ULONG_MAX; }
847 else { u_lim = (
long int) API_POSIX_UINT_MAX; }
848 u_p10 = 10000UL; exp = 4;
851 if(10 > u_lim / u_p10) {
break; }
855 bn = exp + (size_t) 2;
857 b = (
char*) api_posix_realloc((
void*) b, bn);
860 err_no = API_POSIX_ENOMEM; err = 1;
864 if(mod_l) { u = va_arg(ap,
unsigned long int); }
865 else { u = (
unsigned long int) va_arg(ap,
unsigned int); }
874 b[ci++] = (char) (48UL + u / ui);
879 if(!u && 1UL == ui) { b[ci++] =
'0'; }
885 if(!mod_z) { b[ci++] =
' '; }
886 else { b[ci++] =
'0'; }
890 else { b[ci++] =
'0'; }
892 if(ci >= bn) {
break; }
895 if(ci >= bn) { si = API_POSIX_SIZE_MAX; err = 1;
break; }
911 if(mod_l) { u_lim = API_POSIX_ULONG_MAX; }
912 else { u_lim = (
long int) API_POSIX_UINT_MAX; }
913 u_p16 = 4096UL; exp = 3;
916 if(16 > u_lim / u_p16) {
break; }
920 bn = exp + (size_t) 2;
922 b = (
char*) api_posix_realloc((
void*) b, bn);
925 err_no = API_POSIX_ENOMEM; err = 1;
929 if(mod_l) { u = va_arg(ap,
unsigned long int); }
930 else { u = (
unsigned long int) va_arg(ap,
unsigned int); }
940 if(10UL > u_dig) { b[ci++] = (char) (48UL + u_dig); }
944 if(hex_capital) { b[ci++] = (char) (65UL + u_dig); }
945 else { b[ci++] = (char) (97UL + u_dig); }
951 if(!u && 1UL == ui) { b[ci++] =
'0'; }
957 if(!mod_z) { b[ci++] =
' '; }
958 else { b[ci++] =
'0'; }
962 else { b[ci++] =
'0'; }
964 if(ci >= bn) {
break; }
967 if(ci >= bn) { si = API_POSIX_SIZE_MAX; err = 1;
break; }
978 PRINT_ERROR(
"snprintf(): Invalid modifier in conversion");
983 c_s = va_arg(ap,
char*);
989 PRINT_ERROR(
"snprintf(): Conversion type not supported");
1003 if(API_POSIX_SIZE_MAX - sn < cn) { sn = API_POSIX_SIZE_MAX; }
1008 if(n && (si < n - 1) && cn)
1010 if(n - 1 - si < cn) { cn = n - 1 - si; }
1011 memcpy(&s[si], c_s, cn);
1016 api_posix_free((
void*) b);
1022 PRINT_ERROR(
"snprintf(): AAARGHHH, buffer overflow detected!");
1025 err_no = API_POSIX_EOVERFLOW;
1030 if(!err) { res = (int) sn; }
1033 api_posix_errno = err_no;
1044 #if CFG_USE_POSIX_API < 200809
1049 #define GETLINE_BLOCKSIZE (size_t) 128
1050 api_posix_ssize_t api_posix_getline(
char** lineptr,
size_t* n, FILE* stream)
1052 api_posix_ssize_t res = -1;
1056 size_t mems = GETLINE_BLOCKSIZE;
1061 if(NULL == lineptr || NULL == n) { api_posix_errno = API_POSIX_EINVAL; }
1065 if (NULL == *lineptr)
1067 *lineptr = (
char*) api_posix_malloc(GETLINE_BLOCKSIZE);
1068 if(NULL == *lineptr) { api_posix_errno = API_POSIX_ENOMEM; }
1069 else { len = *n = GETLINE_BLOCKSIZE; }
1073 if(NULL != *lineptr)
1076 if((
size_t) API_POSIX_SSIZE_MAX < len)
1078 len = (size_t) API_POSIX_SSIZE_MAX;
1082 while((
size_t) API_POSIX_SSIZE_MAX > pos && mems)
1087 if(GETLINE_BLOCKSIZE > API_POSIX_SIZE_MAX - len)
1089 mems = API_POSIX_SIZE_MAX - len;
1092 api_posix_errno = API_POSIX_ENOMEM;
1096 memp = api_posix_realloc(*lineptr, *n + mems);
1099 api_posix_errno = API_POSIX_ENOMEM;
1114 (*lineptr)[pos] = 0;
1115 res = (api_posix_ssize_t) pos;
1120 rv = api_posix_fgetc(stream);
1121 if(EOF == rv)
break;
1122 (*lineptr)[pos++] = (char) rv;
1123 if(
'\n' == (
char) rv)
1131 if((
size_t) API_POSIX_SSIZE_MAX <= pos)
1133 api_posix_errno = API_POSIX_EOVERFLOW;
1146 #if CFG_USE_POSIX_API < 200112 && !CFG_USE_IP6
1148 void api_posix_freeaddrinfo(api_posix_struct_addrinfo* info)
1150 api_posix_struct_addrinfo* next;
1155 next = info->ai_next;
1157 api_posix_free((
void*) info);
1175 static api_posix_pthread_mutex_t getaddrinfo_mutex
1176 = API_POSIX_PTHREAD_MUTEX_INITIALIZER;
1177 int api_posix_getaddrinfo(
const char* nodename,
const char* servname,
1178 const api_posix_struct_addrinfo* hints,
1179 api_posix_struct_addrinfo** result)
1182 api_posix_struct_addrinfo* info = NULL;
1183 api_posix_struct_addrinfo* tmp = NULL;
1184 api_posix_struct_servent* se;
1185 api_posix_struct_hostent* he;
1187 api_posix_in_port_t port = 0;
1189 int family = hints->ai_family;
1194 if(API_POSIX_AF_UNSPEC == family) { family = API_POSIX_AF_INET; }
1197 if(NULL == nodename)
1199 PRINT_ERROR(
"getaddrinfo(): Call without nodename not supported");
1200 res = API_POSIX_EAI_FAIL;
1202 else if(API_POSIX_AF_INET != family)
1205 res = API_POSIX_EAI_FAMILY;
1207 else if (API_POSIX_SOCK_STREAM != hints->ai_socktype)
1210 res = API_POSIX_EAI_SOCKTYPE;
1214 if(NULL != servname)
1217 if(api_posix_pthread_mutex_lock(&getaddrinfo_mutex))
1219 PRINT_ERROR(
"getaddrinfo(): Locking mutex failed");
1220 res = API_POSIX_EAI_AGAIN;
1228 res = API_POSIX_EAI_AGAIN;
1233 if(1 == sscanf(servname,
"%u", &p))
1235 port = (api_posix_in_port_t)
1236 api_posix_htons((api_posix_in_port_t) p);
1240 se = api_posix_getservbyname(servname, NULL);
1241 if(NULL != se) { port = (api_posix_in_port_t) se->s_port; }
1254 api_posix_pthread_mutex_unlock(&getaddrinfo_mutex);
1259 if(NULL != servname && !port)
1261 PRINT_ERROR(
"getaddrinfo(): Service resolution failed");
1262 res = API_POSIX_EAI_FAIL;
1264 else if(api_posix_pthread_mutex_lock(&getaddrinfo_mutex))
1266 PRINT_ERROR(
"getaddrinfo(): Locking mutex failed");
1267 res = API_POSIX_EAI_AGAIN;
1275 res = API_POSIX_EAI_AGAIN;
1279 he = api_posix_gethostbyname(nodename);
1280 if(NULL == he) { res = API_POSIX_EAI_NONAME; }
1281 else if(API_POSIX_AF_INET != he->h_addrtype || 4 != he->h_length)
1283 PRINT_ERROR(
"getaddrinfo(): Address type not supported");
1284 res = API_POSIX_EAI_FAIL;
1291 tmp = (api_posix_struct_addrinfo*)
1292 api_posix_malloc(
sizeof(api_posix_struct_addrinfo)
1293 +
sizeof(api_posix_struct_sockaddr_in));
1294 if(NULL == tmp) { res = API_POSIX_EAI_MEMORY;
break; }
1297 if(NULL == info) { *result = info = tmp; }
1298 else { info = info->ai_next = tmp; }
1300 memset((
void*) info, 0,
sizeof(api_posix_struct_addrinfo));
1301 info->ai_family = API_POSIX_AF_INET;
1302 info->ai_socktype = hints->ai_socktype;
1303 info->ai_protocol = hints->ai_protocol;
1304 info->ai_addrlen = (api_posix_socklen_t)
1305 sizeof(api_posix_struct_sockaddr_in);
1307 = (api_posix_struct_sockaddr*) (
void*)
1308 ((
char*) (
void*) info
1309 +
sizeof(api_posix_struct_addrinfo));
1310 ((api_posix_struct_sockaddr_in*) info->ai_addr)->sin_family
1311 = (api_posix_sa_family_t) info->ai_family;
1312 ((api_posix_struct_sockaddr_in*) info->ai_addr)->sin_port
1314 ((api_posix_struct_sockaddr_in*) info->ai_addr)
1316 = *((api_posix_in_addr_t*) he->h_addr_list[num++]);
1317 info->ai_next = NULL;
1320 printf(
"%s: %sgetaddrinfo(): Resolve result: "
1323 inet_ntoa(((api_posix_struct_sockaddr_in*)
1326 (
unsigned int) api_posix_ntohs(port));
1331 while(NULL != he->h_addr_list[num]);
1344 api_posix_pthread_mutex_unlock(&getaddrinfo_mutex);
1346 printf(
"%s: %sgetaddrinfo(): %u result(s)\n",
1354 printf(
"%s: %sgetaddrinfo(): Result: %d\n",
1357 if(res) { api_posix_freeaddrinfo(*result); }
1364 const char* api_posix_gai_strerror(
int ecode)
1370 case API_POSIX_EAI_AGAIN:
1372 res =
"Temporary failure in name resolution";
1375 case API_POSIX_EAI_BADFLAGS:
1377 res =
"Invalid value for parameter";
1380 case API_POSIX_EAI_FAIL:
1382 res =
"Non-recoverable failure in name resolution";
1385 case API_POSIX_EAI_FAMILY:
1387 res =
"Address family not supported";
1390 case API_POSIX_EAI_MEMORY:
1392 res =
"Memory allocation failed";
1395 case API_POSIX_EAI_NONAME:
1397 res =
"Name does not resolve for the supplied parameters";
1400 case API_POSIX_EAI_OVERFLOW:
1402 res =
"Argument buffer overflowed (buffer too small)";
1405 case API_POSIX_EAI_SERVICE:
1407 res =
"Service not recognized for the specified socket type";
1410 case API_POSIX_EAI_SOCKTYPE:
1412 res =
"Socket type was not supported";
1415 case API_POSIX_EAI_SYSTEM:
1417 res =
"System error occurred";
1422 res =
"Unknown error occurred";
1435 #if CFG_USE_POSIX_API < 200112
1436 int api_posix_inet_pton(
int af,
const char* src,
void* dst)
1439 api_posix_in_addr_t addr;
1441 if (API_POSIX_AF_INET != af)
1443 api_posix_errno = API_POSIX_EAFNOSUPPORT;
1450 addr = (api_posix_in_addr_t) api_posix_inet_addr(src);
1451 if((api_posix_in_addr_t) -1 == addr) { res = 0; }
1455 *((
unsigned char*) dst) = *((
unsigned char*) &addr);
1456 *((
unsigned char*) dst + 1) = *((
unsigned char*) &addr + 1);
1457 *((
unsigned char*) dst + 2) = *((
unsigned char*) &addr + 2);
1458 *((
unsigned char*) dst + 3) = *((
unsigned char*) &addr + 3);