err_t sys_getnameinfo(const sys_sockaddr_t* addr, char** host_out, char** serv_out, int flags) { char* host_buf=0; char* new_host_buf; char* serv_buf=0; char* new_serv_buf; int host_buf_sz = NI_MAXHOST; int serv_buf_sz = NI_MAXSERV; int got; err_t err_out; STARTING_SLOW_SYSCALL; while( 1 ) { new_host_buf = (char*) qio_realloc(host_buf, host_buf_sz); new_serv_buf = (char*) qio_realloc(serv_buf, serv_buf_sz); if( ! new_host_buf || ! new_serv_buf ) { qio_free(host_buf); qio_free(serv_buf); err_out = ENOMEM; goto error; } host_buf = new_host_buf; serv_buf = new_serv_buf; got = getnameinfo((const struct sockaddr*) & addr->addr, addr->len, host_buf, host_buf_sz, serv_buf, serv_buf_sz, flags); #ifndef EAI_OVERFLOW break; // oddly enough... old Mac OS X does not have EAI_OVERFLOW. #else if( got != EAI_OVERFLOW ) break; host_buf_sz *= 2; serv_buf_sz *= 2; #endif } if( got == 0 ) { *host_out = NULL; *serv_out = NULL; err_out = 0; } else { *host_out = host_buf; *serv_out = serv_buf; if( got == EAI_SYSTEM ) err_out = errno; else err_out = GAI_ERROR_OFFSET + got; } error: DONE_SLOW_SYSCALL; return err_out; }
// returns an allocated string in string_out, which must be freed. err_t sys_readlink(const char* path, const char** string_out) { ssize_t got; char* buf = NULL; char* newbuf; int buf_sz = 248; err_t ret = EINVAL; while( 1 ) { newbuf = (char*) qio_realloc(buf, buf_sz); if( ! newbuf ) { qio_free(buf); return ENOMEM; } buf = newbuf; got = readlink(path, buf, buf_sz); if( got == -1 ) { qio_free(buf); *string_out = NULL; return errno; } if( got+1 < buf_sz ) { buf[got] = '\0'; // OK! *string_out = buf; ret = 0; break; } // otherwise, buffer is too small. buf_sz *= 2; } return ret; }
// This routine returns a malloc'd string through its path_out pointer. // The caller is responsible for freeing that memory. err_t sys_getcwd(const char** path_out) { int sz = 128; char* buf; char* got; err_t err = 0; buf = (char*) qio_malloc(sz); if( !buf ) return ENOMEM; while( 1 ) { got = getcwd(buf, sz); if( got != NULL ) break; else if( errno == ERANGE ) { // keep looping but with bigger buffer. sz = 2*sz; got = (char*) qio_realloc(buf, sz); if( ! got ) { qio_free(buf); return ENOMEM; } } else { // Other error, stop. err = errno; } } *path_out = buf; return err; }
// Write from curl to a string. Note that userdata is a str_t, since nuch as we have // to keep track of how much we read in buf_writer, we have to keep track of how // long our string is so that we cann lengthen it via realloc as we need to. static size_t chpl_curl_write_string(void *contents, size_t size, size_t nmemb, void *userp) { size_t realsize = size * nmemb; struct str_t *str = (struct str_t *)userp; str->mem = (char*)qio_realloc(str->mem, str->size + realsize + 1); if(str->mem == NULL) { return 0; } chpl_memcpy(&(str->mem[str->size]), contents, realsize); str->size += realsize; str->mem[str->size] = 0; return realsize; }
qioerr hdfs_getcwd(void* file, const char** path_out, void* fs) { int sz = 128; char* buf = (char*) qio_malloc(sz); qioerr err = 0; if ( !buf ) QIO_GET_CONSTANT_ERROR(err, ENOMEM, "Out of memory in hdfs_getcwd"); // hdfsGetWorkingDirectory will return 0 if buf[] is not large enough // If this happens, grow the buffer and try again while (err == 0 && hdfsGetWorkingDirectory(to_hdfs_fs(fs)->hfs, buf, sz) == 0) { if (errno == ERANGE) { int newSz = 2 * sz; char* newBuf = (char*) qio_realloc(buf, newSz); if (newBuf == 0) { QIO_GET_CONSTANT_ERROR(err, ENOMEM, "Out of memory in hdfs_getcwd"); } else { sz = newSz; buf = newBuf; } } else { // Other error, stop. QIO_GET_CONSTANT_ERROR(err, EREMOTEIO, "Unable to get path to file in HDFS"); } } if (err != 0) { qio_free(buf); buf = 0; } *path_out = buf; return err; }
// This routine returns a malloc'd string through its path_out pointer. // The caller is responsible for freeing that memory. err_t sys_getcwd(const char** path_out) { int sz = 128; char* buf = (char*) qio_malloc(sz); err_t err = (buf == 0) ? ENOMEM : 0; // getcwd() returns 0 if the provided buffer is too small // If this happens, grow the buffer and try again while (err == 0 && getcwd(buf, sz) == 0) { if (errno == ERANGE) { int newSz = 2 * sz; char* newBuf = (char*) qio_realloc(buf, newSz); if (newBuf == 0) { qio_free(buf); err = ENOMEM; } else { sz = newSz; buf = newBuf; } } else { err = errno; } } if (err != 0) { qio_free(buf); sz = 0; buf = 0; } *path_out = buf; return err; }
qioerr hdfs_getpath(void* file, const char** string_out, void* fs) { // Speculatively allocate 128 bytes for the string int sz = 128; int left = 0; char* buf; char* got; qioerr err = 0; const char* host = to_hdfs_fs(fs)->fs_name; int port = to_hdfs_fs(fs)->fs_port; const char* path = to_hdfs_file(file)->pathnm; buf = (char*) qio_malloc(sz); if( !buf ) QIO_GET_CONSTANT_ERROR(err, ENOMEM, "Out of memory in hdfs_getpath"); while (1) { left = snprintf(buf, sz, "hdfs://%s:%d/%s", host, port, path); if (left > -1 && left < sz) { break; } else { // keep looping but with bigger buffer. // We know the size that we need now if n > -1 sz = left > -1 ? left + 1 : 2*sz; got = (char*) qio_realloc(buf, sz); if( ! got ) { qio_free(buf); QIO_GET_CONSTANT_ERROR(err, ENOMEM, "Out of memory in hdfs_getpath"); } } } *string_out = buf; return err; }
// allocates and returns an error string in *string_out // which must be freed. static err_t sys_strerror_internal(err_t error, char** string_out, size_t extra_space) { // normal errors are in normal places. // EAI_AGAIN... etc are at 10000 + num. int buf_sz = 248 + extra_space; char* buf = NULL; char* newbuf; const char* errmsg; int got; err_t err_out; err_out = 0; if( error == 0 || (EXTEND_ERROR_OFFSET <= error && error < EXTEND_ERROR_OFFSET+EXTEND_ERROR_NUM) ) { if( error == 0 ) errmsg = error_string_no_error; else errmsg = extended_errors[error - EXTEND_ERROR_OFFSET]; buf_sz = strlen(errmsg) + 1; buf = (char*) qio_malloc(buf_sz + extra_space); if( ! buf ) return ENOMEM; strcpy(buf, errmsg); *string_out = buf; return 0; } while( 1 ) { newbuf = (char*) qio_realloc(buf, buf_sz + extra_space); if( ! newbuf ) { qio_free(buf); return ENOMEM; } buf = newbuf; got = sys_xsi_strerror_r(error, buf, buf_sz); if( got == 0 ) break; if( got == -1 && errno != ERANGE ) { err_out = errno; break; } buf_sz *= 2; // try again with a bigger buffer. } // maybe it's a EAI/gai error, which we add GAI_ERROR_OFFSET to. #ifdef HAS_GETADDRINFO if( got == -1 && err_out == EINVAL ) { const char* gai_str; int len; gai_str = gai_strerror(error - GAI_ERROR_OFFSET); if( ! gai_str ) { err_out = errno; } else { len = strlen(gai_str); if( len + 1 > buf_sz ) { newbuf = (char*) qio_realloc(buf, len + 1 + extra_space); if( ! newbuf ) { qio_free(buf); return ENOMEM; } buf = newbuf; } strcpy(buf, gai_str); } } #endif *string_out = buf; return err_out; }