string strip(const StaticString &str) { const char *data = str.data(); const char *end = str.data() + str.size(); while (data < end && (*data == ' ' || *data == '\n' || *data == '\t')) { data++; } while (end > data && (end[-1] == ' ' || end[-1] == '\n' || end[-1] == '\t')) { end--; } return string(data, end - data); }
void setupNonBlockingTcpSocket(NTCP_State &state, const StaticString &hostname, int port) { int ret; memset(&state.hints, 0, sizeof(state.hints)); state.hints.ai_family = PF_UNSPEC; state.hints.ai_socktype = SOCK_STREAM; ret = getaddrinfo(hostname.toString().c_str(), toString(port).c_str(), &state.hints, &state.res); if (ret != 0) { string message = "Cannot resolve IP address '"; message.append(hostname.data(), hostname.size()); message.append(":"); message.append(toString(port)); message.append("': "); message.append(gai_strerror(ret)); throw IOException(message); } state.fd = syscalls::socket(PF_INET, SOCK_STREAM, 0); if (state.fd == -1) { int e = errno; throw SystemException("Cannot create a TCP socket file descriptor", e); } state.hostname = hostname; state.port = port; setNonBlocking(state.fd); }
static Numeric hexToUnsignedNumeric(const StaticString &hex) { const char *pos = hex.data(); const char *end = hex.data() + hex.size(); Numeric result = 0; bool done = false; while (pos < end && !done) { char c = *pos; if (c >= '0' && c <= '9') { result *= 16; result += c - '0'; } else if (c >= 'a' && c <= 'f') { result *= 16; result += 10 + (c - 'a'); } else if (c >= 'A' && c <= 'F') { result *= 16; result += 10 + (c - 'A'); } else { done = true; } pos++; } return result; }
static Numeric stringToSignedNumeric(const StaticString &str) { Numeric result = 0; string::size_type i = 0; const char *data = str.data(); bool minus = false; while (data[i] == ' ' && i < str.size()) { i++; } if (data[i] == '-') { minus = true; i++; } while (data[i] >= '0' && data[i] <= '9' && i < str.size()) { result *= 10; result += data[i] - '0'; i++; } if (minus) { return -result; } else { return result; } }
int connectToUnixServer(const StaticString &filename, const char *file, unsigned int line) { int fd = syscalls::socket(PF_UNIX, SOCK_STREAM, 0); if (fd == -1) { int e = errno; throw SystemException("Cannot create a Unix socket file descriptor", e); } FdGuard guard(fd, file, line, true); int ret; struct sockaddr_un addr; if (filename.size() > sizeof(addr.sun_path) - 1) { string message = "Cannot connect to Unix socket '"; message.append(filename.data(), filename.size()); message.append("': filename is too long."); throw RuntimeException(message); } addr.sun_family = AF_UNIX; memcpy(addr.sun_path, filename.c_str(), filename.size()); addr.sun_path[filename.size()] = '\0'; bool retry = true; int counter = 0; while (retry) { ret = syscalls::connect(fd, (const sockaddr *) &addr, sizeof(addr)); if (ret == -1) { #if defined(sun) || defined(__sun) /* Solaris has this nice kernel bug where connecting to * a newly created Unix socket which is obviously * connectable can cause an ECONNREFUSED. So we retry * in a loop. */ retry = errno == ECONNREFUSED; #else retry = false; #endif retry = retry && counter < 9; if (retry) { syscalls::usleep((useconds_t) (10000 * pow((double) 2, (double) counter))); counter++; } else { int e = errno; string message("Cannot connect to Unix socket '"); message.append(filename.toString()); message.append("'"); throw SystemException(message, e); } } else { guard.clear(); return fd; } } abort(); // Never reached. return -1; // Shut up compiler warning. }
string lookupSystemGroupnameByGid(gid_t gid, const StaticString &fallbackFormat) { OsGroup group; bool result; try { result = lookupSystemGroupByGid(gid, group); } catch (const SystemException &) { result = false; } if (result && group.grp.gr_name != NULL && group.grp.gr_name[0] != '\0') { return group.grp.gr_name; } else { // Null terminate fallback format string DynamicBuffer fallbackFormatNt(fallbackFormat.size() + 1); memcpy(fallbackFormatNt.data, fallbackFormat.data(), fallbackFormat.size()); fallbackFormatNt.data[fallbackFormat.size()] = '\0'; char buf[512]; snprintf(buf, sizeof(buf), fallbackFormatNt.data, (int) gid); buf[sizeof(buf) - 1] = '\0'; return buf; } }
string lookupSystemUsernameByUid(uid_t uid, const StaticString &fallbackFormat) { OsUser user; bool result; try { result = lookupSystemUserByUid(uid, user); } catch (const SystemException &) { result = false; } if (result && user.pwd.pw_name != NULL && user.pwd.pw_name[0] != '\0') { return user.pwd.pw_name; } else { // Null terminate fallback format string DynamicBuffer fallbackFormatNt(fallbackFormat.size() + 1); memcpy(fallbackFormatNt.data, fallbackFormat.data(), fallbackFormat.size()); fallbackFormatNt.data[fallbackFormat.size()] = '\0'; char buf[512]; snprintf(buf, sizeof(buf), fallbackFormatNt.data, (int) uid); buf[sizeof(buf) - 1] = '\0'; return buf; } }
bool constantTimeCompare(const StaticString &a, const StaticString &b) { // http://blog.jasonmooberry.com/2010/10/constant-time-string-comparison/ // See also ActiveSupport::MessageVerifier#secure_compare. if (a.size() != b.size()) { return false; } else { const char *x = a.data(); const char *y = b.data(); const char *end = a.data() + a.size(); int result = 0; while (x < end) { result |= *x ^ *y; x++; y++; } return result == 0; } }
/* {{{ Special objects that implement MongoDB\BSON\Serializable */ void VariantToBsonConverter::_convertSerializable(bson_t *bson, const char *key, Object v) { Variant result; Array properties; TypedValue args[1] = { *(Variant(v)).asCell() }; Class *cls; Func *m; cls = v.get()->getVMClass(); m = cls->lookupMethod(s_MongoDriverBsonSerializable_functionName.get()); g_context->invokeFuncFew( result.asTypedValue(), m, v.get(), nullptr, 1, args ); if ( ! ( result.isArray() || (result.isObject() && result.toObject().instanceof(s_stdClass)) ) ) { StringBuffer buf; buf.printf( "Expected %s::%s() to return an array or stdClass, %s given", cls->nameStr().c_str(), s_MongoDriverBsonSerializable_functionName.data(), result.isObject() ? result.toObject()->getVMClass()->nameStr().c_str() : HPHP::getDataTypeString(result.getType()).data() ); Variant full_name = buf.detach(); throw MongoDriver::Utils::throwUnexpectedValueException((char*) full_name.toString().c_str()); } /* Convert to array so that we can handle it well */ properties = result.toArray(); if (v.instanceof(s_MongoDriverBsonPersistable_className)) { const char *class_name = cls->nameStr().c_str(); Object obj = createMongoBsonBinaryObject( (const uint8_t *) class_name, strlen(class_name), (bson_subtype_t) 0x80 ); properties.add(String(s_MongoDriverBsonODM_fieldName), obj); } convertDocument(bson, key, result.isObject() ? Variant(Variant(properties).toObject()) : Variant(properties)); }
/** * Linux-only way to change OOM killer configuration for * current process. Requires root privileges, which we * should have. */ static void setOomScore(const StaticString &score) { if (score.empty()) { return; } FILE *f; OomFileType type; f = openOomAdjFile("w", type); if (f != NULL) { fwrite(score.data(), 1, score.size(), f); fclose(f); } }
static Numeric stringToUnsignedNumeric(const StaticString &str) { Numeric result = 0; string::size_type i = 0; const char *data = str.data(); while (data[i] == ' ' && i < str.size()) { i++; } while (data[i] >= '0' && data[i] <= '9' && i < str.size()) { result *= 10; result += data[i] - '0'; i++; } return result; }
void parseTcpSocketAddress(const StaticString &address, string &host, unsigned short &port) { if (getSocketAddressType(address) != SAT_TCP) { throw ArgumentException("Not a valid TCP socket address"); } StaticString hostAndPort(address.data() + sizeof("tcp://") - 1, address.size() - sizeof("tcp://") + 1); if (hostAndPort.empty()) { throw ArgumentException("Not a valid TCP socket address"); } if (hostAndPort[0] == '[') { // IPv6 address, e.g.: // [::1]:3000 const char *hostEnd = (const char *) memchr(hostAndPort.data(), ']', hostAndPort.size()); if (hostEnd == NULL || hostAndPort.size() <= string::size_type(hostEnd - hostAndPort.data()) + 3) { throw ArgumentException("Not a valid TCP socket address"); } const char *sep = hostEnd + 1; host.assign(hostAndPort.data() + 1, hostEnd - hostAndPort.data() - 1); port = stringToUint(StaticString( sep + 1, hostAndPort.data() + hostAndPort.size() - sep - 1 )); } else { // IPv4 address, e.g.: // 127.0.0.1:3000 const char *sep = (const char *) memchr(hostAndPort.data(), ':', hostAndPort.size()); if (sep == NULL || hostAndPort.size() <= string::size_type(sep - hostAndPort.data()) + 2) { throw ArgumentException("Not a valid TCP socket address"); } host.assign(hostAndPort.data(), sep - hostAndPort.data()); port = stringToUint(StaticString( sep + 1, hostAndPort.data() + hostAndPort.size() - sep - 1 )); } }
bool lookupSystemGroupByName(const StaticString &name, OsGroup &result) { TRACE_POINT(); // Null terminate name DynamicBuffer ntName(name.size() + 1); memcpy(ntName.data, name.data(), name.size()); ntName.data[name.size()] = '\0'; int code; struct group *output = NULL; do { code = getgrnam_r(ntName.data, &result.grp, result.buffer.data, result.buffer.size, &output); } while (code == EINTR || code == EAGAIN); if (code == 0) { return output != NULL; } else { throw SystemException("Error looking up OS group account " + name, code); } }
void writeExact(int fd, const StaticString &data, unsigned long long *timeout) { const char * restrict data_ptr = data.data(); writeExact(fd, data_ptr, data.size(), timeout); }