123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- /*
- * Copyright 2005 - 2016 Zarafa and its licensors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- #include <kopano/zcdefs.h>
- #include <kopano/platform.h>
- #include <kopano/ECLogger.h>
- #include <sys/select.h>
- #include <sys/time.h>
- #include <iconv.h>
- #include <cstring>
- #include <cstdio>
- #include <cctype>
- #include <ctime>
- #include <dirent.h>
- #include <mapicode.h> // return codes
- #include <unistd.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <fcntl.h>
- #include <cstdlib>
- #include <cerrno>
- #include <climits>
- #include <string>
- #include <map>
- #include <vector>
- #ifndef HAVE_UUID_CREATE
- # include <uuid/uuid.h>
- #else
- # include <uuid.h>
- #endif
- #if defined(__linux__) && defined(__GLIBC__)
- # include <cxxabi.h>
- # include <execinfo.h>
- #endif
- #include "TmpPath.h"
- #ifdef __APPLE__
- // bsd
- #define ICONV_CONST const
- #elif OPENBSD
- // bsd
- #define ICONV_CONST const
- #else
- // linux
- #define ICONV_CONST
- #endif
- static bool rand_init_done = false;
- bool operator!=(const GUID &a, const GUID &b)
- {
- return memcmp(&a, &b, sizeof(GUID)) != 0;
- }
- bool operator==(REFIID a, const GUID &b)
- {
- return memcmp(&a, &b, sizeof(GUID)) == 0;
- }
- HRESULT CoCreateGuid(LPGUID pNewGUID) {
- if (!pNewGUID)
- return MAPI_E_INVALID_PARAMETER;
- #if HAVE_UUID_CREATE
- #ifdef OPENBSD
- uuid_t *g = NULL;
- void *vp = NULL;
- size_t n = 0;
- // error codes are not checked!
- uuid_create(&g);
- uuid_make(g, UUID_MAKE_V1);
- uuid_export(g, UUID_FMT_BIN, &vp, &n);
- memcpy(pNewGUID, &vp, UUID_LEN_BIN);
- uuid_destroy(g);
- #else
- uuid_t g;
- uint32_t uid_ret;
- uuid_create(&g, &uid_ret);
- memcpy(pNewGUID, &g, sizeof(g));
- #endif // OPENBSD
- #else
- uuid_t g;
- uuid_generate(g);
- memcpy(pNewGUID, g, sizeof(g));
- #endif
- return S_OK;
- }
- void GetSystemTimeAsFileTime(FILETIME *ft) {
- struct timeval now;
- __int64_t l;
- gettimeofday(&now,NULL); // null==timezone
- l = ((__int64_t)now.tv_sec * 10000000) + ((__int64_t)now.tv_usec * 10) + (__int64_t)NANOSECS_BETWEEN_EPOCHS;
- ft->dwLowDateTime = (unsigned int)(l & 0xffffffff);
- ft->dwHighDateTime = l >> 32;
- }
- /**
- * copies the path of the temp directory, including trailing /, into
- * given buffer.
- *
- * @param[in] inLen size of buffer, inclusive \0 char
- * @param[in,out] lpBuffer buffer to place path in
- *
- * @return length used or what would've been required if it would fit in lpBuffer
- */
- DWORD GetTempPath(DWORD inLen, char *lpBuffer) {
- unsigned int outLen = snprintf(lpBuffer, inLen, "%s/", TmpPath::getInstance() -> getTempPath().c_str());
- if (outLen > inLen)
- return 0;
- return outLen;
- }
- void Sleep(unsigned int msec) {
- struct timespec ts;
- unsigned int rsec;
- ts.tv_sec = msec/1000;
- rsec = msec - (ts.tv_sec*1000);
- ts.tv_nsec = rsec*1000*1000;
- nanosleep(&ts, NULL);
- }
- namespace KC {
- static void rand_fail(void)
- {
- fprintf(stderr, "Cannot access/use /dev/urandom, this is fatal (%s)\n", strerror(errno));
- kill(0, SIGTERM);
- exit(1);
- }
-
- void rand_get(char *p, int n)
- {
- int fd = open("/dev/urandom", O_RDONLY);
- if (fd == -1)
- rand_fail();
-
- // handle EINTR
- while(n > 0)
- {
- int rc = read(fd, p, n);
- if (rc == 0)
- rand_fail();
- if (rc == -1)
- {
- if (errno == EINTR)
- continue;
- rand_fail();
- }
- p += rc;
- n -= rc;
- }
- close(fd);
- }
-
- void rand_init() {
- unsigned int seed = 0;
- rand_get((char *)&seed, sizeof(seed));
- srand(seed);
- rand_init_done = true;
- }
- int rand_mt() {
- int dummy = 0;
- rand_get((char *)&dummy, sizeof dummy);
- if (dummy == INT_MIN)
- dummy = INT_MAX;
- else
- dummy = abs(dummy);
- // this gives a slighly bias to the value 0
- // also RAND_MAX is never returned which the
- // regular rand() does do
- return dummy % RAND_MAX;
- }
- void rand_free() {
- //Nothing to free
- }
- char * get_password(const char *prompt) {
- return getpass(prompt);
- }
- } /* namespace */
- HGLOBAL GlobalAlloc(UINT uFlags, ULONG ulSize)
- {
- // always returns NULL, as required by CreateStreamOnHGlobal implementation in mapi4linux/src/mapiutil.cpp
- return NULL;
- }
- namespace KC {
- time_t GetProcessTime()
- {
- time_t t;
- time(&t);
- return t;
- }
- std::vector<std::string> get_backtrace(void)
- {
- #define BT_MAX 256
- std::vector<std::string> result;
- void *addrlist[BT_MAX];
- int addrlen = backtrace(addrlist, BT_MAX);
- if (addrlen == 0)
- return result;
- char **symbollist = backtrace_symbols(addrlist, addrlen);
- for (int i = 0; i < addrlen; ++i)
- result.push_back(symbollist[i]);
- free(symbollist);
- return result;
- #undef BT_MAX
- }
- static void dump_fdtable_summary(pid_t pid)
- {
- char procdir[64];
- snprintf(procdir, sizeof(procdir), "/proc/%ld/fd", static_cast<long>(pid));
- DIR *dh = opendir(procdir);
- if (dh == NULL)
- return;
- std::string msg;
- struct dirent *de;
- while ((de = readdir(dh)) != nullptr) {
- if (de->d_type != DT_LNK)
- continue;
- std::string de_name(std::string(procdir) + "/" + de->d_name);
- struct stat sb;
- if (stat(de_name.c_str(), &sb) < 0) {
- msg += " ?";
- } else switch (sb.st_mode & S_IFMT) {
- case S_IFREG: msg += " ."; break;
- case S_IFSOCK: msg += " s"; break;
- case S_IFDIR: msg += " d"; break;
- case S_IFIFO: msg += " p"; break;
- case S_IFCHR: msg += " c"; break;
- default: msg += " O"; break;
- }
- msg += de->d_name;
- }
- closedir(dh);
- ec_log_debug("FD map:%s", msg.c_str());
- }
- /* ALERT! Big hack!
- *
- * This function relocates an open file descriptor to a new file descriptor above 1024. The
- * reason we do this is because, although we support many open FDs up to FD_SETSIZE, libraries
- * that we use may not (most notably libldap). This means that if a new socket is allocated within
- * libldap as socket 1025, libldap will fail because it was compiled with FD_SETSIZE=1024. To fix
- * this problem, we make sure that most FDs under 1024 are free for use by external libraries, while
- * we use the range 1024 -> \infty.
- */
- int ec_relocate_fd(int fd)
- {
- static constexpr const int typical_limit = 1024;
- if (fd >= typical_limit)
- /* No action needed */
- return fd;
- int relocated = fcntl(fd, F_DUPFD, typical_limit);
- if (relocated >= 0) {
- close(fd);
- return relocated;
- }
- if (errno == EINVAL) {
- /*
- * The range start (typical_limit) was already >=RLIMIT_NOFILE.
- * Just stay silent.
- */
- static bool warned_once;
- if (warned_once)
- return fd;
- warned_once = true;
- ec_log_warn("F_DUPFD yielded EINVAL\n");
- return fd;
- }
- static time_t warned_last;
- time_t now = time(NULL);
- if (warned_last + 60 > now)
- return fd;
- ec_log_notice(
- "Relocation of FD %d into high range (%d+) could not be completed: "
- "%s. Keeping old number.\n", fd, typical_limit, strerror(errno));
- dump_fdtable_summary(getpid());
- return fd;
- }
- } /* namespace */
|