/** Spawn a thread to read from the pipe connected to the specified fd. * Returns a Future that will hold a string with the entire output from * that stream. */ Future<w_string> ChildProcess::readPipe(int fd) { auto it = pipes_.find(fd); if (it == pipes_.end()) { return makeFuture(w_string(nullptr)); } auto p = std::make_shared<Promise<w_string>>(); std::thread thr([this, fd, p] { std::string result; try { auto& pipe = pipes_[fd]; while (true) { char buf[4096]; auto x = read(pipe->read.fd(), buf, sizeof(buf)); if (x == 0) { // all done break; } if (x == -1) { p->setException(std::make_exception_ptr(std::system_error( errno, std::generic_category(), "reading from child process"))); return; } result.append(buf, x); } p->setValue(w_string(result.data(), result.size())); } catch (const std::exception& exc) { p->setException(std::current_exception()); } }); thr.detach(); return p->getFuture(); }
w_string w_string::pathCat(std::initializer_list<w_string_piece> elems) { uint32_t length = 0; w_string_t *s; char *buf; for (auto &p : elems) { length += p.size() + 1; } s = (w_string_t*)(new char[sizeof(*s) + length]); new (s) watchman_string(); s->refcnt = 1; buf = (char *)(s + 1); s->buf = buf; for (auto &p : elems) { if (p.size() == 0) { // Skip empty strings continue; } if (buf != s->buf) { *buf = '/'; ++buf; } memcpy(buf, p.data(), p.size()); buf += p.size(); } *buf = 0; s->len = buf - s->buf; return w_string(s, false); }
SavedStateInterface::SavedStateResult LocalSavedStateInterface::getMostRecentSavedStateImpl( w_string_piece lookupCommitId) const { auto commitIds = scm_->getCommitsPriorToAndIncluding(lookupCommitId, maxCommits_); for (auto& commitId : commitIds) { auto path = getLocalPath(commitId); // We could return a path that no longer exists if the path is removed // (for example by saved state GC) after we check that the path exists // here, but before the client reads the state. We've explicitly chosen to // return the state without additional safety guarantees, and leave it to // the client to ensure GC happens only after states are no longer likely // to be used. if (w_path_exists(path.c_str())) { log(DBG, "Found saved state for commit ", commitId, "\n"); SavedStateInterface::SavedStateResult result; result.commitId = commitId; result.savedStateInfo = json_object({{"local-path", w_string_to_json(path)}, {"commit-id", w_string_to_json(commitId)}}); return result; } } SavedStateInterface::SavedStateResult result; result.commitId = w_string(); result.savedStateInfo = json_object( {{"error", w_string_to_json("No suitable saved state found")}}); return result; }
w_string w_string::asNullTerminated() const { if (w_string_is_null_terminated(str_)) { return *this; } return w_string(str_->buf, str_->len, str_->type); }
void test_pointers() { bool foo = true; char lowerBuf[20]; auto str = w_string::build(&foo); snprintf( lowerBuf, sizeof(lowerBuf), "0x%" PRIx64, (uint64_t)(uintptr_t)(&foo)); ok(str.size() == strlen_uint32(lowerBuf), "reasonable seeming bool pointer len, got %" PRIu32 " vs expected %" PRIu32, str.size(), strlen_uint32(lowerBuf)); ok(str.size() == strlen_uint32(str.c_str()), "string is really nul terminated, size %" PRIu32 " strlen of c_str %" PRIu32, str.size(), strlen_uint32(str.c_str())); ok(!strcmp(lowerBuf, str.c_str()), "bool pointer rendered right hex value sprintf->%s, str->%s", lowerBuf, str.c_str()); str = w_string::build(nullptr); ok(str.size() > 0, "nullptr has reasonable size: %" PRIsize_t, str.size()); ok(str == w_string("0x0"), "nullptr looks right %s", str.c_str()); void* zero = 0; ok(w_string::build(zero) == "0x0", "zero pointer looks right"); }
void test_strings() { { auto hello = w_string::build("hello"); ok(hello == w_string("hello"), "hello"); ok(hello.size() == 5, "there are 5 chars in hello"); ok(!strcmp("hello", hello.c_str()), "looks nul terminated `%s` %" PRIu32, hello.c_str(), strlen_uint32(hello.c_str())); } { w_string_piece piece("hello"); ok(piece.size() == 5, "piece has 5 char size"); auto hello = w_string::build(piece); ok(hello.size() == 5, "hello has 5 char size"); ok(!strcmp("hello", hello.c_str()), "looks nul terminated"); } { char foo[] = "foo"; auto str = w_string::build(foo); ok(str.size() == 3, "foo has 3 char size"); ok(!strcmp("foo", foo), "foo matches"); } }
w_string realPath(const char *path) { auto options = OpenFileHandleOptions::queryFileInfo(); // Follow symlinks, because that's really the point of this function options.followSymlinks = 1; options.strictNameChecks = 0; #ifdef _WIN32 // Special cases for cwd w_string_piece pathPiece(path); // On Windows, "" is used to refer to the CWD. // We also allow using "." for parity with unix, even though that // doesn't generally work for that purpose on windows. // This allows `watchman watch-project .` to succeeed on windows. if (pathPiece.size() == 0 || pathPiece == ".") { std::wstring wchar; wchar.resize(WATCHMAN_NAME_MAX); auto len = GetCurrentDirectoryW(wchar.size(), &wchar[0]); auto err = GetLastError(); if (len == 0) { throw std::system_error(err, std::system_category(), "GetCurrentDirectoryW"); } // Assumption: that the OS maintains the CWD in canonical form return w_string(wchar.data(), len); } #endif auto handle = openFileHandle(path, options); return handle.getOpenedPath(); }
w_string w_string::vprintf(const char* format, va_list args) { w_string_t *s; int len; char *buf; va_list args_copy; va_copy(args_copy, args); // Get the length needed len = vsnprintf(nullptr, 0, format, args_copy); va_end(args_copy); s = (w_string_t*)(new char[sizeof(*s) + len + 1]); if (!s) { perror("no memory available"); abort(); } new (s) watchman_string(); s->refcnt = 1; s->len = len; buf = (char*)(s + 1); vsnprintf(buf, len + 1, format, args); s->buf = buf; return w_string(s, false); }
void add_strings(struct watchman_ignore *ignore, const char **strings, uint32_t num_strings, bool is_vcs_ignore) { uint32_t i; for (i = 0; i < num_strings; i++) { ignore->add(w_string(strings[i], W_STRING_UNICODE), is_vcs_ignore); } }
void test_double() { auto str = w_string::build(5.5); char buf[16]; snprintf(buf, sizeof(buf), "%f", 5.5); ok(str.size() == 8, "size is %" PRIsize_t, str.size()); ok(!strcmp(str.c_str(), buf), "str.c_str=%s, buf=%s", str.c_str(), buf); ok(str == w_string("5.500000"), "double looks good '%s'", str.c_str()); }
void write_string(const char* s, WFILE* p) { int len = (int)strlen(s); w_byte(TYPE_STRING, p); w_long((long)len, p); w_string(s, len, p); //log_message(s,p->r); }
char * ACE_NS_String::char_rep (void) const { ACE_TRACE ("ACE_NS_String::char_rep"); ACE_NS_WString w_string (this->rep_, (this->len_ / sizeof (ACE_WCHAR_T)) - 1); return w_string.char_rep (); }
QSize StringToSize(const QString &a_string) { QString w_string(a_string); removeWithespaceRef(w_string); w_string.remove("Size("); w_string.remove(")"); int c_index = w_string.indexOf("|"); return QSize(w_string.left(c_index).toInt(), w_string.right(w_string.size() - 1 - c_index).toInt()); }
w_string LocalSavedStateInterface::getLocalPath(w_string_piece commitId) const { w_string filename; if (!projectMetadata_) { filename = w_string::build(commitId); } else { filename = w_string::build(commitId, w_string("_"), projectMetadata_); } return w_string::pathCat({localStoragePath_, project_, filename}); }
void CInifile::w_s64 ( LPCSTR S, LPCSTR L, s64 V, LPCSTR comment ) { string128 temp; #ifndef _EDITOR _i64toa_s (V, temp, sizeof(temp), 10); #else _i64toa (V, temp, 10); #endif w_string (S,L,temp,comment); }
void test_suffix() { ok(!w_string("").suffix(), "empty string suffix"); ok(w_string(".").suffix() == w_string(""), "only one dot suffix"); ok(w_string("endwithdot.").suffix() == w_string(""), "end with dot"); ok(!w_string("nosuffix").suffix(), "no suffix"); ok(w_string(".beginwithdot").suffix() == w_string("beginwithdot"), "begin with dot"); ok(w_string("MainActivity.java").suffix() == w_string("java"), "java suffix"); std::string longName(128, 'a'); auto str = w_string::build(".", longName.c_str()); ok(!str.suffix(), "too long suffix"); std::string nearlongName(127, 'a'); str = w_string::build("I am not long enough.", nearlongName.c_str()); ok(str.suffix().size() == 127, "nearly too long suffix"); // 255 is the longest suffix among some systems std::string toolongName(255, 'a'); str = w_string::build(".", toolongName.c_str()); ok(!str.suffix(), "too long suffix"); }
w_string w_dir_path_cat_str( const struct watchman_dir* dir, w_string_piece extra) { uint32_t length = 0; const struct watchman_dir* d; w_string_t *s; char *buf, *end; if (extra.size()) { length = extra.size() + 1 /* separator */; } for (d = dir; d; d = d->parent) { length += d->name.size() + 1 /* separator OR final NUL terminator */; } s = (w_string_t*)(new char[sizeof(*s) + length]); new (s) watchman_string(); s->refcnt = 1; s->len = length - 1; buf = (char *)(s + 1); end = buf + s->len; *end = 0; if (extra.size()) { end -= extra.size(); memcpy(end, extra.data(), extra.size()); } for (d = dir; d; d = d->parent) { if (d != dir || (extra.size())) { --end; *end = '/'; } end -= d->name.size(); memcpy(end, d->name.data(), d->name.size()); } s->buf = buf; return w_string(s, false); }
w_string readSymbolicLink(const char* path) { #ifndef _WIN32 std::string result; // Speculatively assume that this is large enough to read the // symlink text. This helps to avoid an extra lstat call. result.resize(256); for (int retry = 0; retry < 2; ++retry) { auto len = readlink(path, &result[0], result.size()); if (len < 0) { throw std::system_error( errno, std::generic_category(), "readlink for readSymbolicLink"); } if (size_t(len) < result.size()) { return w_string(result.data(), len); } // Truncated read; we need to figure out the right size to use struct stat st; if (lstat(path, &st)) { throw std::system_error( errno, std::generic_category(), "lstat for readSymbolicLink"); } result.resize(st.st_size + 1, 0); } throw std::system_error( E2BIG, std::generic_category(), "readlink for readSymbolicLink: symlink changed while reading it"); #else return openFileHandle(path, OpenFileHandleOptions::queryFileInfo()) .readSymbolicLink(); #endif }
w_string w_string_piece::asLowerCase(w_string_type_t stringType) const { char* buf; w_string_t* s; /* need to make a lowercase version */ s = (w_string_t*)(new char[sizeof(*s) + size() + 1]); new (s) watchman_string(); s->refcnt = 1; s->len = size(); buf = (char*)(s + 1); s->buf = buf; s->type = stringType; auto cursor = s_; while (cursor < e_) { *buf = (char)tolower((uint8_t)*cursor); ++cursor; ++buf; } *buf = 0; return w_string(s, false); }
void CInifile::w_fvector4 ( LPCSTR S, LPCSTR L, const Fvector4& V, LPCSTR comment ) { string128 temp; sprintf_s (temp,sizeof(temp),"%f,%f,%f,%f", V.x, V.y, V.z, V.w); w_string (S,L,temp,comment); }
std::pair<w_string, w_string> ChildProcess::pollingCommunicate( pipeWriteCallback writeCallback) { std::unordered_map<int, std::string> outputs; for (auto& it : pipes_) { if (it.first != STDIN_FILENO) { // We only want output streams here continue; } watchman::log( watchman::DBG, "Setting up output buffer for fd ", it.first, "\n"); outputs.emplace(std::make_pair(it.first, "")); } std::vector<pollfd> pfds; std::unordered_map<int, int> revmap; pfds.reserve(pipes_.size()); revmap.reserve(pipes_.size()); while (!pipes_.empty()) { revmap.clear(); pfds.clear(); watchman::log( watchman::DBG, "Setting up pollfds for ", pipes_.size(), " fds\n"); for (auto& it : pipes_) { pollfd pfd; if (it.first == STDIN_FILENO) { pfd.fd = it.second->write.fd(); pfd.events = POLLOUT; } else { pfd.fd = it.second->read.fd(); pfd.events = POLLIN; } pfds.emplace_back(std::move(pfd)); revmap[pfd.fd] = it.first; } int r; do { watchman::log(watchman::DBG, "waiting for ", pfds.size(), " fds\n"); r = ::poll(pfds.data(), pfds.size(), -1); } while (r == -1 && errno == EINTR); if (r == -1) { watchman::log(watchman::ERR, "poll error\n"); throw std::system_error(errno, std::generic_category(), "poll"); } for (auto& pfd : pfds) { watchman::log( watchman::DBG, "fd ", pfd.fd, " revmap to ", revmap[pfd.fd], " has events ", pfd.revents, "\n"); if ((pfd.revents & (POLLHUP | POLLIN)) && revmap[pfd.fd] != STDIN_FILENO) { watchman::log( watchman::DBG, "fd ", pfd.fd, " rev=", revmap[pfd.fd], " is readable\n"); char buf[BUFSIZ]; auto l = ::read(pfd.fd, buf, sizeof(buf)); if (l == -1 && (errno == EAGAIN || errno == EINTR)) { watchman::log( watchman::DBG, "fd ", pfd.fd, " rev=", revmap[pfd.fd], " read give EAGAIN\n"); continue; } if (l == -1) { int err = errno; watchman::log( watchman::ERR, "failed to read from pipe fd ", pfd.fd, " err ", strerror(err), "\n"); throw std::system_error( err, std::generic_category(), "reading from child process"); } watchman::log( watchman::DBG, "fd ", pfd.fd, " rev=", revmap[pfd.fd], " read ", l, " bytes\n"); if (l == 0) { // Stream is done; close it out. pipes_.erase(revmap[pfd.fd]); continue; } outputs[revmap[pfd.fd]].append(buf, l); } if ((pfd.revents & POLLOUT) && revmap[pfd.fd] == STDIN_FILENO && writeCallback(pipes_.at(revmap[pfd.fd])->write)) { // We should close it watchman::log( watchman::DBG, "fd ", pfd.fd, " rev ", revmap[pfd.fd], " writer says to close\n"); pipes_.erase(revmap[pfd.fd]); continue; } if (pfd.revents & (POLLHUP | POLLERR)) { // Something wrong with it, so close it pipes_.erase(revmap[pfd.fd]); watchman::log( watchman::DBG, "fd ", pfd.fd, " rev ", revmap[pfd.fd], " error status, so closing\n"); continue; } } watchman::log(watchman::DBG, "remaining pipes ", pipes_.size(), "\n"); } auto optBuffer = [&](int fd) -> w_string { auto it = outputs.find(fd); if (it == outputs.end()) { watchman::log(watchman::DBG, "communicate fd ", fd, " nullptr\n"); return nullptr; } watchman::log( watchman::DBG, "communicate fd ", fd, " gives ", it->second, "\n"); return w_string(it->second.data(), it->second.size()); }; return std::make_pair(optBuffer(STDOUT_FILENO), optBuffer(STDERR_FILENO)); }
void CInifile::w_s32 ( LPCSTR S, LPCSTR L, s32 V, LPCSTR comment ) { string128 temp; sprintf_s (temp,sizeof(temp),"%d",V); w_string (S,L,temp,comment); }
w_string FileDescriptor::readSymbolicLink() const { #ifndef _WIN32 struct stat st; if (fstat(fd_, &st)) { throw std::system_error( errno, std::generic_category(), "fstat for readSymbolicLink"); } std::string result; result.resize(st.st_size + 1, 0); #ifdef __linux__ // Linux 2.6.39 and later provide this interface auto atlen = readlinkat(fd_, "", &result[0], result.size()); if (atlen == int(result.size())) { // It's longer than we expected; TOCTOU detected! throw std::system_error( ENAMETOOLONG, std::generic_category(), "readlinkat: link contents grew while examining file"); } if (atlen >= 0) { return w_string(result.data(), atlen); } // if we get ENOTDIR back then we're probably on an older linux and // should fall back to the technique used below. if (errno != ENOTDIR) { throw std::system_error( errno, std::generic_category(), "readlinkat for readSymbolicLink"); } #endif auto myName = getOpenedPath(); auto len = readlink(myName.c_str(), &result[0], result.size()); if (len == int(result.size())) { // It's longer than we expected; TOCTOU detected! throw std::system_error( ENAMETOOLONG, std::generic_category(), "readlink: link contents grew while examining file"); } if (len >= 0) { return w_string(result.data(), len); } throw std::system_error( errno, std::generic_category(), "readlink for readSymbolicLink"); #else // _WIN32 DWORD len = 64 * 1024; auto buf = malloc(len); if (!buf) { throw std::bad_alloc(); } SCOPE_EXIT { free(buf); }; WCHAR* target; USHORT targetlen; auto result = DeviceIoControl( (HANDLE)fd_, FSCTL_GET_REPARSE_POINT, nullptr, 0, buf, len, &len, nullptr); // We only give one retry; if the size changed again already, we'll // have another pending notify from the OS to go look at it again // later, and it's totally fine to give up here for now. if (!result && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { free(buf); buf = malloc(len); if (!buf) { throw std::bad_alloc(); } result = DeviceIoControl( (HANDLE)fd_, FSCTL_GET_REPARSE_POINT, nullptr, 0, buf, len, &len, nullptr); } if (!result) { throw std::system_error( GetLastError(), std::system_category(), "FSCTL_GET_REPARSE_POINT"); } auto rep = reinterpret_cast<REPARSE_DATA_BUFFER*>(buf); switch (rep->ReparseTag) { case IO_REPARSE_TAG_SYMLINK: target = rep->SymbolicLinkReparseBuffer.PathBuffer + (rep->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)); targetlen = rep->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(WCHAR); break; case IO_REPARSE_TAG_MOUNT_POINT: target = rep->MountPointReparseBuffer.PathBuffer + (rep->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)); targetlen = rep->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR); break; default: throw std::system_error( ENOSYS, std::generic_category(), "Unsupported ReparseTag"); } return w_string(target, targetlen); #endif }
w_string FileDescriptor::getOpenedPath() const { #if defined(F_GETPATH) // macOS. The kernel interface only allows MAXPATHLEN char buf[MAXPATHLEN + 1]; if (fcntl(fd_, F_GETPATH, buf) == -1) { throw std::system_error(errno, std::generic_category(), "fcntl for getOpenedPath"); } return w_string(buf); #elif defined(__linux__) || defined(__sun) char procpath[1024]; #if defined(__linux__) snprintf(procpath, sizeof(procpath), "/proc/%d/fd/%d", getpid(), fd_); #elif defined(__sun) snprintf(procpath, sizeof(procpath), "/proc/%d/path/%d", getpid(), fd_); #endif // Avoid an extra stat by speculatively attempting to read into // a reasonably sized buffer. char buf[WATCHMAN_NAME_MAX]; auto len = readlink(procpath, buf, sizeof(buf)); if (len == sizeof(buf)) { len = -1; // We need to stat it to discover the required length errno = ENAMETOOLONG; } if (len >= 0) { return w_string(buf, len); } if (errno == ENOENT) { // For this path to not exist must mean that /proc is not mounted. // Report this with an actionable message throw std::system_error(ENOSYS, std::generic_category(), "getOpenedPath: need /proc to be mounted!"); } if (errno != ENAMETOOLONG) { throw std::system_error(errno, std::generic_category(), "readlink for getOpenedPath"); } // Figure out how much space we need struct stat st; if (fstat(fd_, &st)) { throw std::system_error(errno, std::generic_category(), "fstat for getOpenedPath"); } std::string result; result.resize(st.st_size + 1, 0); len = readlink(procpath, &result[0], result.size()); if (len == int(result.size())) { // It's longer than we expected; TOCTOU detected! throw std::system_error( ENAMETOOLONG, std::generic_category(), "readlinkat: link contents grew while examining file"); } if (len >= 0) { return w_string(&result[0], len); } throw std::system_error(errno, std::generic_category(), "readlink for getOpenedPath"); #elif defined(_WIN32) std::wstring wchar; wchar.resize(WATCHMAN_NAME_MAX); auto len = GetFinalPathNameByHandleW( (HANDLE)fd_, &wchar[0], wchar.size(), FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); auto err = GetLastError(); if (len >= wchar.size()) { // Grow it wchar.resize(len); len = GetFinalPathNameByHandleW( (HANDLE)fd_, &wchar[0], len, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); err = GetLastError(); } if (len == 0) { throw std::system_error( GetLastError(), std::system_category(), "GetFinalPathNameByHandleW"); } return w_string(wchar.data(), len); #else throw std::system_error(ENOSYS, std::generic_category(), "getOpenedPath not implemented on this platform"); #endif }
static fse_stream* fse_stream_make( const std::shared_ptr<w_root_t>& root, FSEventStreamEventId since, w_string& failure_reason) { FSEventStreamContext ctx; CFMutableArrayRef parray = nullptr; CFStringRef cpath = nullptr; double latency; struct stat st; auto watcher = watcherFromRoot(root); struct fse_stream* fse_stream = new struct fse_stream(root, since); // Each device has an optional journal maintained by fseventsd that keeps // track of the change events. The journal may not be available if the // filesystem was mounted read-only. The journal has an associated UUID // to track the version of the data. In some cases the journal can become // invalidated and it will have a new UUID generated. This can happen // if the EventId rolls over. // We need to lookup up the UUID for the associated path and use that to // help decide whether we can use a value of `since` other than SinceNow. if (stat(root->root_path.c_str(), &st)) { failure_reason = w_string::printf( "failed to stat(%s): %s\n", root->root_path.c_str(), strerror(errno)); goto fail; } // Obtain the UUID for the device associated with the root fse_stream->uuid = FSEventsCopyUUIDForDevice(st.st_dev); if (since != kFSEventStreamEventIdSinceNow) { CFUUIDBytes a, b; if (!fse_stream->uuid) { // If there is no UUID available and we want to use an event offset, // we fail: a nullptr UUID means that the journal is not available. failure_reason = w_string::printf( "fsevents journal is not available for dev_t=%d\n", st.st_dev); goto fail; } // Compare the UUID with that of the current stream if (!watcher->stream->uuid) { failure_reason = w_string( "fsevents journal was not available for prior stream", W_STRING_UNICODE); goto fail; } a = CFUUIDGetUUIDBytes(fse_stream->uuid); b = CFUUIDGetUUIDBytes(watcher->stream->uuid); if (memcmp(&a, &b, sizeof(a)) != 0) { failure_reason = w_string("fsevents journal UUID is different", W_STRING_UNICODE); goto fail; } } memset(&ctx, 0, sizeof(ctx)); ctx.info = fse_stream; parray = CFArrayCreateMutable(nullptr, 0, &kCFTypeArrayCallBacks); if (!parray) { failure_reason = w_string("CFArrayCreateMutable failed", W_STRING_UNICODE); goto fail; } cpath = CFStringCreateWithBytes( nullptr, (const UInt8*)root->root_path.data(), root->root_path.size(), kCFStringEncodingUTF8, false); if (!cpath) { failure_reason = w_string("CFStringCreateWithBytes failed", W_STRING_UNICODE); goto fail; } CFArrayAppendValue(parray, cpath); latency = root->config.getDouble("fsevents_latency", 0.01), w_log( W_LOG_DBG, "FSEventStreamCreate for path %s with latency %f seconds\n", root->root_path.c_str(), latency); fse_stream->stream = FSEventStreamCreate( nullptr, fse_callback, &ctx, parray, since, latency, kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagWatchRoot | kFSEventStreamCreateFlagFileEvents); if (!fse_stream->stream) { failure_reason = w_string("FSEventStreamCreate failed", W_STRING_UNICODE); goto fail; } FSEventStreamScheduleWithRunLoop(fse_stream->stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); #ifdef HAVE_FSEVENTSTREAMSETEXCLUSIONPATHS if (!root->ignore.dirs_vec.empty() && root->config.getBool("_use_fsevents_exclusions", true)) { CFMutableArrayRef ignarray; size_t i, nitems = std::min(root->ignore.dirs_vec.size(), MAX_EXCLUSIONS); ignarray = CFArrayCreateMutable(nullptr, 0, &kCFTypeArrayCallBacks); if (!ignarray) { failure_reason = w_string("CFArrayCreateMutable failed", W_STRING_UNICODE); goto fail; } for (i = 0; i < nitems; ++i) { const auto& path = root->ignore.dirs_vec[i]; CFStringRef ignpath; ignpath = CFStringCreateWithBytes( nullptr, (const UInt8*)path.data(), path.size(), kCFStringEncodingUTF8, false); if (!ignpath) { failure_reason = w_string("CFStringCreateWithBytes failed", W_STRING_UNICODE); CFRelease(ignarray); goto fail; } CFArrayAppendValue(ignarray, ignpath); CFRelease(ignpath); } if (!FSEventStreamSetExclusionPaths(fse_stream->stream, ignarray)) { failure_reason = w_string("FSEventStreamSetExclusionPaths failed", W_STRING_UNICODE); CFRelease(ignarray); goto fail; } CFRelease(ignarray); } #endif out: if (parray) { CFRelease(parray); } if (cpath) { CFRelease(cpath); } return fse_stream; fail: delete fse_stream; fse_stream = nullptr; goto out; }
void CInifile::w_fcolor ( LPCSTR S, LPCSTR L, const Fcolor& V, LPCSTR comment ) { string128 temp; sprintf_s (temp,sizeof(temp),"%f,%f,%f,%f", V.r, V.g, V.b, V.a); w_string (S,L,temp,comment); }
void CInifile::w_ivector3 ( LPCSTR S, LPCSTR L, const Ivector3& V, LPCSTR comment ) { string128 temp; sprintf_s (temp,sizeof(temp),"%d,%d,%d", V.x, V.y, V.z); w_string (S,L,temp,comment); }
void CInifile::w_color ( LPCSTR S, LPCSTR L, u32 V, LPCSTR comment ) { string128 temp; sprintf_s (temp,sizeof(temp),"%d,%d,%d,%d", color_get_R(V), color_get_G(V), color_get_B(V), color_get_A(V)); w_string (S,L,temp,comment); }
void CInifile::w_float ( LPCSTR S, LPCSTR L, float V, LPCSTR comment ) { string128 temp; sprintf_s (temp,sizeof(temp),"%f",V); w_string (S,L,temp,comment); }
void CInifile::w_bool ( LPCSTR S, LPCSTR L, BOOL V, LPCSTR comment ) { w_string (S,L,V?"on":"off",comment); }