void moloch_config_load() { gboolean status; GError *error = 0; GKeyFile *keyfile; int i; keyfile = molochKeyFile = g_key_file_new(); status = g_key_file_load_from_file(keyfile, config.configFile, G_KEY_FILE_NONE, &error); if (!status || error) { printf("Couldn't load config file (%s) %s\n", config.configFile, (error?error->message:"")); exit(1); } char **includes = moloch_config_str_list(keyfile, "includes", NULL); if (includes) { moloch_config_load_includes(includes); g_strfreev(includes); //LOG("KEYFILE:\n%s", g_key_file_to_data(molochKeyFile, NULL, NULL)); } char *rotateIndex = moloch_config_str(keyfile, "rotateIndex", "daily"); if (strcmp(rotateIndex, "hourly") == 0) config.rotate = MOLOCH_ROTATE_HOURLY; else if (strcmp(rotateIndex, "hourly6") == 0) config.rotate = MOLOCH_ROTATE_HOURLY6; else if (strcmp(rotateIndex, "daily") == 0) config.rotate = MOLOCH_ROTATE_DAILY; else if (strcmp(rotateIndex, "weekly") == 0) config.rotate = MOLOCH_ROTATE_WEEKLY; else if (strcmp(rotateIndex, "monthly") == 0) config.rotate = MOLOCH_ROTATE_MONTHLY; else { printf("Unknown rotateIndex '%s'\n", rotateIndex); exit(1); } g_free(rotateIndex); config.nodeClass = moloch_config_str(keyfile, "nodeClass", NULL); gchar **tags = moloch_config_str_list(keyfile, "dontSaveTags", NULL); if (tags) { for (i = 0; tags[i]; i++) { if (!(*tags[i])) continue; int num = 1; char *colon = strchr(tags[i], ':'); if (colon) { *colon = 0; num = atoi(colon+1); if (num < 1) num = 1; if (num > 0xffff) num = 0xffff; } moloch_string_add((MolochStringHash_t *)(char*)&config.dontSaveTags, tags[i], (gpointer)(long)num, TRUE); } g_strfreev(tags); } config.plugins = moloch_config_str_list(keyfile, "plugins", NULL); config.rootPlugins = moloch_config_str_list(keyfile, "rootPlugins", NULL); config.smtpIpHeaders = moloch_config_str_list(keyfile, "smtpIpHeaders", NULL); if (config.smtpIpHeaders) { for (i = 0; config.smtpIpHeaders[i]; i++) { int len = strlen(config.smtpIpHeaders[i]); char *lower = g_ascii_strdown(config.smtpIpHeaders[i], len); g_free(config.smtpIpHeaders[i]); config.smtpIpHeaders[i] = lower; if (lower[len-1] == ':') lower[len-1] = 0; } } config.prefix = moloch_config_str(keyfile, "prefix", ""); int len = strlen(config.prefix); if (len > 0 && config.prefix[len - 1] != '_') { char *tmp = malloc(len + 2); memcpy(tmp, config.prefix, len); tmp[len] = '_'; tmp[len+1] = 0; g_free(config.prefix); config.prefix = tmp; } config.elasticsearch = moloch_config_str(keyfile, "elasticsearch", "localhost:9200"); config.interface = moloch_config_str_list(keyfile, "interface", NULL); config.pcapDir = moloch_config_str_list(keyfile, "pcapDir", NULL); config.bpf = moloch_config_str(keyfile, "bpf", NULL); config.yara = moloch_config_str(keyfile, "yara", NULL); config.emailYara = moloch_config_str(keyfile, "emailYara", NULL); config.rirFile = moloch_config_str(keyfile, "rirFile", NULL); config.ouiFile = moloch_config_str(keyfile, "ouiFile", NULL); config.geoLite2ASN = moloch_config_str(keyfile, "geoLite2ASN", "/data/moloch/etc/GeoLite2-ASN.mmdb"); config.geoLite2Country = moloch_config_str(keyfile, "geoLite2Country", "/data/moloch/etc/GeoLite2-Country.mmdb"); config.dropUser = moloch_config_str(keyfile, "dropUser", NULL); config.dropGroup = moloch_config_str(keyfile, "dropGroup", NULL); config.pluginsDir = moloch_config_str_list(keyfile, "pluginsDir", NULL); config.parsersDir = moloch_config_str_list(keyfile, "parsersDir", " /data/moloch/parsers ; ./parsers "); char *offlineRegex = moloch_config_str(keyfile, "offlineFilenameRegex", "(?i)\\.(pcap|cap)$"); config.offlineRegex = g_regex_new(offlineRegex, 0, 0, &error); if (!config.offlineRegex || error) { printf("Couldn't parse offlineRegex (%s) %s\n", offlineRegex, (error?error->message:"")); exit(1); } g_free(offlineRegex); config.pcapDirTemplate = moloch_config_str(keyfile, "pcapDirTemplate", NULL); if (config.pcapDirTemplate && config.pcapDirTemplate[0] != '/') { printf("pcapDirTemplate MUST start with a / '%s'\n", config.pcapDirTemplate); exit(1); } config.pcapDirAlgorithm = moloch_config_str(keyfile, "pcapDirAlgorithm", "round-robin"); if (strcmp(config.pcapDirAlgorithm, "round-robin") != 0 && strcmp(config.pcapDirAlgorithm, "max-free-percent") != 0 && strcmp(config.pcapDirAlgorithm, "max-free-bytes") != 0) { printf("'%s' is not a valid value for pcapDirAlgorithm. Supported algorithms are round-robin, max-free-percent, and max-free-bytes.\n", config.pcapDirAlgorithm); exit(1); } config.maxFileSizeG = moloch_config_double(keyfile, "maxFileSizeG", 4, 0.01, 1024); config.maxFileSizeB = config.maxFileSizeG*1024LL*1024LL*1024LL; config.maxFileTimeM = moloch_config_int(keyfile, "maxFileTimeM", 0, 0, 0xffff); config.timeouts[SESSION_ICMP]= moloch_config_int(keyfile, "icmpTimeout", 10, 1, 0xffff); config.timeouts[SESSION_UDP] = moloch_config_int(keyfile, "udpTimeout", 60, 1, 0xffff); config.timeouts[SESSION_TCP] = moloch_config_int(keyfile, "tcpTimeout", 60*8, 10, 0xffff); config.timeouts[SESSION_SCTP]= moloch_config_int(keyfile, "sctpTimeout", 60, 10, 0xffff); config.timeouts[SESSION_ESP] = moloch_config_int(keyfile, "espTimeout", 60*10, 10, 0xffff); config.tcpSaveTimeout = moloch_config_int(keyfile, "tcpSaveTimeout", 60*8, 10, 60*120); int maxStreams = moloch_config_int(keyfile, "maxStreams", 1500000, 1, 16777215); config.maxPackets = moloch_config_int(keyfile, "maxPackets", 10000, 1, 0xffff); config.maxPacketsInQueue = moloch_config_int(keyfile, "maxPacketsInQueue", 200000, 10000, 5000000); config.dbBulkSize = moloch_config_int(keyfile, "dbBulkSize", 200000, MOLOCH_HTTP_BUFFER_SIZE*2, 1000000); config.dbFlushTimeout = moloch_config_int(keyfile, "dbFlushTimeout", 5, 1, 60*30); config.maxESConns = moloch_config_int(keyfile, "maxESConns", 20, 5, 1000); config.maxESRequests = moloch_config_int(keyfile, "maxESRequests", 500, 10, 5000); config.logEveryXPackets = moloch_config_int(keyfile, "logEveryXPackets", 50000, 1000, 0xffffffff); config.pcapBufferSize = moloch_config_int(keyfile, "pcapBufferSize", 300000000, 100000, 0xffffffff); config.pcapWriteSize = moloch_config_int(keyfile, "pcapWriteSize", 0x40000, 0x10000, 0x800000); config.maxFreeOutputBuffers = moloch_config_int(keyfile, "maxFreeOutputBuffers", 50, 0, 0xffff); config.fragsTimeout = moloch_config_int(keyfile, "fragsTimeout", 60*8, 60, 0xffff); config.maxFrags = moloch_config_int(keyfile, "maxFrags", 10000, 100, 0xffffff); config.snapLen = moloch_config_int(keyfile, "snapLen", 16384, 1, MOLOCH_PACKET_MAX_LEN); config.maxMemPercentage = moloch_config_int(keyfile, "maxMemPercentage", 100, 5, 100); config.maxReqBody = moloch_config_int(keyfile, "maxReqBody", 256, 0, 0x7fff); config.packetThreads = moloch_config_int(keyfile, "packetThreads", 1, 1, MOLOCH_MAX_PACKET_THREADS); config.logUnknownProtocols = moloch_config_boolean(keyfile, "logUnknownProtocols", config.debug); config.logESRequests = moloch_config_boolean(keyfile, "logESRequests", config.debug); config.logFileCreation = moloch_config_boolean(keyfile, "logFileCreation", config.debug); config.logHTTPConnections = moloch_config_boolean(keyfile, "logHTTPConnections", TRUE); config.parseSMTP = moloch_config_boolean(keyfile, "parseSMTP", TRUE); config.parseSMB = moloch_config_boolean(keyfile, "parseSMB", TRUE); config.parseQSValue = moloch_config_boolean(keyfile, "parseQSValue", FALSE); config.parseCookieValue = moloch_config_boolean(keyfile, "parseCookieValue", FALSE); config.supportSha256 = moloch_config_boolean(keyfile, "supportSha256", FALSE); config.reqBodyOnlyUtf8 = moloch_config_boolean(keyfile, "reqBodyOnlyUtf8", TRUE); config.compressES = moloch_config_boolean(keyfile, "compressES", FALSE); config.antiSynDrop = moloch_config_boolean(keyfile, "antiSynDrop", TRUE); config.readTruncatedPackets = moloch_config_boolean(keyfile, "readTruncatedPackets", FALSE); config.trackESP = moloch_config_boolean(keyfile, "trackESP", FALSE); config.maxStreams[SESSION_TCP] = maxStreams/config.packetThreads*1.25; config.maxStreams[SESSION_UDP] = maxStreams/config.packetThreads/20; config.maxStreams[SESSION_SCTP] = maxStreams/config.packetThreads/20; config.maxStreams[SESSION_ICMP] = maxStreams/config.packetThreads/200; config.maxStreams[SESSION_ESP] = maxStreams/config.packetThreads/200; gchar **saveUnknownPackets = moloch_config_str_list(keyfile, "saveUnknownPackets", NULL); if (saveUnknownPackets) { for (i = 0; saveUnknownPackets[i]; i++) { char *s = saveUnknownPackets[i]; if (strcmp(s, "all") == 0) { memset(&config.etherSavePcap, 0xff, 1024); memset(&config.ipSavePcap, 0xff, 4); } else if (strcmp(s, "ip:all") == 0) { memset(&config.ipSavePcap, 0xff, 4); } else if (strcmp(s, "ether:all") == 0) { memset(&config.etherSavePcap, 0xff, 1024); } else if (strncmp(s, "ip:", 3) == 0) { int n = atoi(s+3); if (n < 0 || n > 0xff) LOGEXIT("Bad value: %s", s); BIT_SET(n, config.ipSavePcap); } else if (strncmp(s, "-ip:", 4) == 0) { int n = atoi(s+4); if (n < 0 || n > 0xff) LOGEXIT("Bad value: %s", s); BIT_CLR(n, config.ipSavePcap); } else if (strncmp(s, "ether:", 6) == 0) { int n = atoi(s+6); if (n < 0 || n > 0xffff) LOGEXIT("Bad value: %s", s); BIT_SET(n, config.etherSavePcap); } else if (strncmp(s, "-ether:", 7) == 0) { int n = atoi(s+7); if (n < 0 || n > 0xffff) LOGEXIT("Bad value: %s", s); BIT_CLR(n, config.etherSavePcap); } else { LOGEXIT("Not sure what %s is", s); } } } }
/*++ Function: _splitpath See description above for _wsplitpath. --*/ void __cdecl _splitpath( const char *path, char *drive, char *dir, char *fname, char *ext) { WCHAR w_path[_MAX_PATH]; WCHAR w_dir[_MAX_DIR]; WCHAR w_fname[_MAX_FNAME]; WCHAR w_ext[_MAX_EXT]; PERF_ENTRY(_splitpath); ENTRY("_splitpath (path=%p (%s), drive=%p, dir=%p, fname=%p, ext=%p)\n", path?path:"NULL", path?path:"NULL", drive, dir, fname, ext); /* Do performance intensive error checking only in debug builds. NOTE: This function must fail predictably across all platforms. Under Windows this function throw an access violation if NULL was passed in as the value for path. */ #if _DEBUG if ( !path ) { ERROR( "path cannot be NULL!\n" ); } if( strlen( path ) >= _MAX_PATH ) { ERROR( "Path length is > _MAX_PATH (%d)!\n", _MAX_PATH); } #endif /* no drive letters in the PAL */ if(drive) { drive[0] = '\0'; } if(0 == MultiByteToWideChar(CP_ACP, 0, path, -1, w_path, _MAX_PATH)) { ASSERT("MultiByteToWideChar failed!\n"); ON_ERROR; } /* Call up to Unicode version; pass NULL for parameters the caller doesn't care about */ _wsplitpath(w_path, NULL, dir?w_dir:NULL, fname?w_fname:NULL, ext?w_ext:NULL); /* Convert result back to MultiByte; report conversion errors but don't stop because of them */ if(dir) { if(0 == WideCharToMultiByte(CP_ACP, 0, w_dir, -1, dir, _MAX_DIR, NULL, NULL)) { ASSERT("WideCharToMultiByte failed!\n"); ON_ERROR; } } if(fname) { if(0 == WideCharToMultiByte(CP_ACP, 0, w_fname, -1, fname, _MAX_FNAME, NULL, NULL)) { ASSERT("WideCharToMultiByte failed!\n"); ON_ERROR; } } if(ext) { if(0 == WideCharToMultiByte(CP_ACP, 0, w_ext, -1, ext, _MAX_EXT, NULL, NULL)) { ASSERT("WideCharToMultiByte failed!\n"); ON_ERROR; } } done: LOGEXIT("_splitpath returns.\n"); PERF_EXIT(_splitpath); }
/*++ Function: _wmakepath See MSDN doc. --*/ void __cdecl _wmakepath( wchar_16 *path, const wchar_16 *drive, const wchar_16 *dir, const wchar_16 *fname, const wchar_16 *ext) { CHAR Dir[ _MAX_DIR ]={0}; CHAR FileName[ _MAX_FNAME ]={0}; CHAR Ext[ _MAX_EXT ]={0}; CHAR Path[ _MAX_PATH ]={0}; PERF_ENTRY(_wmakepath); ENTRY("_wmakepath (path=%p, drive=%p (%S), dir=%p (%S), fname=%p (%S), ext=%p (%S))\n", path, drive ? drive:W16_NULLSTRING, drive ? drive:W16_NULLSTRING, dir ? dir:W16_NULLSTRING, dir ? dir:W16_NULLSTRING, fname ? fname:W16_NULLSTRING, fname ? fname:W16_NULLSTRING, ext ? ext:W16_NULLSTRING, ext ? ext:W16_NULLSTRING); /* According to the pal documentation, host operating systems that don't support drive letters, the "drive" parameter must always be null. */ if ( drive != NULL && drive[0] != '\0' ) { ASSERT( "The drive parameter must always be NULL on systems that don't" "support drive letters. drive is being ignored!.\n" ); } if ((dir != NULL) && WideCharToMultiByte( CP_ACP, 0, dir, -1, Dir, _MAX_DIR, NULL, NULL ) == 0 ) { ASSERT( "An error occurred while converting dir to multibyte." "Possible error: Length of dir is greater than _MAX_DIR.\n" ); goto error; } if ((fname != NULL) && WideCharToMultiByte( CP_ACP, 0, fname, -1, FileName, _MAX_FNAME, NULL, NULL ) == 0 ) { ASSERT( "An error occurred while converting fname to multibyte." "Possible error: Length of fname is greater than _MAX_FNAME.\n" ); goto error; } if ((ext != NULL) && WideCharToMultiByte( CP_ACP, 0, ext, -1, Ext, _MAX_EXT, NULL, NULL ) == 0 ) { ASSERT( "An error occurred while converting ext to multibyte." "Possible error: Length of ext is greater than _MAX_EXT.\n" ); goto error; } /* Call up to the ANSI _makepath. */ _makepath_s( Path, sizeof(Path), NULL, Dir, FileName, Ext ); if ( MultiByteToWideChar( CP_ACP, 0, Path, -1, path, _MAX_PATH ) == 0 ) { ASSERT( "An error occurred while converting the back wide char." "Possible error: The length of combined path is greater " "than _MAX_PATH.\n" ); goto error; } LOGEXIT("_wmakepath returns void\n"); PERF_EXIT(_wmakepath); return; error: *path = '\0'; LOGEXIT("_wmakepath returns void\n"); PERF_EXIT(_wmakepath); }
__cdecl PAL_fopen(const char * fileName, const char * mode) { PAL_FILE *f = NULL; LPSTR supported = NULL; LPSTR UnixFileName = NULL; struct stat stat_data; BOOL bTextMode = TRUE; PERF_ENTRY(fopen); ENTRY("fopen ( fileName=%p (%s) mode=%p (%s))\n", fileName, fileName, mode , mode ); _ASSERTE(fileName != NULL); _ASSERTE(mode != NULL); THREADMarkDiagnostic("PAL_fopen"); if ( *mode == 'r' || *mode == 'w' || *mode == 'a' ) { supported = MapFileOpenModes( (char*)mode,&bTextMode); if ( !supported ) { goto done; } UnixFileName = PAL__strdup(fileName); if (UnixFileName == NULL ) { ERROR("PAL__strdup() failed\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto done; } FILEDosToUnixPathA( UnixFileName ); /*I am not checking for the case where stat fails *as fopen will handle the error more gracefully in case *UnixFileName is invalid*/ if ((stat(UnixFileName, &stat_data) == 0 ) && ((stat_data.st_mode & S_IFMT) == S_IFDIR)) { goto done; } f = (PAL_FILE*)PAL_malloc( sizeof( PAL_FILE ) ); if ( f ) { f->bsdFilePtr = (FILE*)fopen( UnixFileName, supported ); f->PALferrorCode = PAL_FILE_NOERROR; f->bTextMode = bTextMode; if ( !f->bsdFilePtr ) { /* Failed */ PAL_free( f ); f = NULL; } #if UNGETC_NOT_RETURN_EOF else { f->bWriteOnlyMode = WriteOnlyMode(f->bsdFilePtr); } #endif //UNGETC_NOT_RETURN_EOF } else { ERROR( "Unable to allocate memory to the PAL_FILE wrapper\n" ); } } else { ERROR( "The mode flags must start with either an a, w, or r.\n" ); } done: PAL_free( supported ); supported = NULL; PAL_free( UnixFileName ); LOGEXIT( "fopen returns FILE* %p\n", f ); PERF_EXIT(fopen); return f; }
/*++ Function: MessageBoxA This is a small subset of MessageBox that simply logs a message to the system logging facility and returns. A typical log entry will look like: May 23 15:48:10 rice example1: MessageBox: Caption: Error Text Note: hWnd should always be NULL. See MSDN doc. --*/ int PALAPI MessageBoxA( IN LPVOID hWnd, IN LPCSTR lpText, IN LPCSTR lpCaption, IN UINT uType) { INT rc = 0; PERF_ENTRY(MessageBoxA); ENTRY( "MessageBoxA (hWnd=%p, lpText=%p (%s), lpCaption=%p (%s), uType=%#x)\n", hWnd, lpText?lpText:"NULL", lpText?lpText:"NULL", lpCaption?lpCaption:"NULL", lpCaption?lpCaption:"NULL", uType ); if (hWnd != NULL) { ASSERT("hWnd != NULL"); } if (lpText == NULL) { WARN("No message text\n"); lpText = "(no message text)"; } if (lpCaption == NULL) { lpCaption = "Error"; } if (uType & MB_DEFMASK) { WARN("No support for alternate default buttons.\n"); } /* set default status based on the type of button */ switch(uType & MB_TYPEMASK) { case MB_OK: rc = IDOK; break; case MB_ABORTRETRYIGNORE: rc = IDABORT; break; case MB_YESNO: rc = IDNO; break; case MB_OKCANCEL : rc = IDCANCEL; break; case MB_RETRYCANCEL : rc = IDCANCEL; break; default: ASSERT("Bad uType"); rc = IDOK; break; } PALCEnterCriticalSection( &msgbox_critsec); #ifdef __APPLE__ OSStatus osstatus; SecuritySessionId secSession; SessionAttributeBits secSessionInfo; osstatus = SessionGetInfo(callerSecuritySession, &secSession, &secSessionInfo); if (noErr == osstatus && (secSessionInfo & sessionHasGraphicAccess) != 0) { CFStringRef cfsTitle = CFStringCreateWithCString(kCFAllocatorDefault, lpCaption, kCFStringEncodingUTF8); CFStringRef cfsText = CFStringCreateWithCString(kCFAllocatorDefault, lpText, kCFStringEncodingUTF8); CFStringRef cfsButton1 = NULL; CFStringRef cfsButton2 = NULL; CFStringRef cfsButton3 = NULL; CFOptionFlags alertFlags = 0; CFOptionFlags response; switch (uType & MB_TYPEMASK) { case MB_OK: // Nothing needed; since if all the buttons are null, a stock "OK" is used. break; case MB_ABORTRETRYIGNORE: // Localization? Would be needed if this were used outside of debugging. cfsButton1 = CFSTR("Abort"); cfsButton2 = CFSTR("Retry"); cfsButton3 = CFSTR("Ignore"); alertFlags = kCFUserNotificationCautionAlertLevel; break; case MB_YESNO: cfsButton1 = CFSTR("Yes"); cfsButton2 = CFSTR("No"); break; case MB_OKCANCEL: cfsButton1 = CFSTR("OK"); cfsButton2 = CFSTR("Cancel"); break; case MB_RETRYCANCEL: cfsButton1 = CFSTR("Retry"); cfsButton2 = CFSTR("Cancel"); break; } CFUserNotificationDisplayAlert(0 /* no time out */, alertFlags, NULL /* iconURL */, NULL /* soundURL */, NULL /* localizationURL */, cfsTitle, cfsText, cfsButton1, cfsButton2, cfsButton3, &response); switch (uType & MB_TYPEMASK) { case MB_OK: break; case MB_ABORTRETRYIGNORE: switch (response) { case kCFUserNotificationDefaultResponse: rc = IDABORT; break; case kCFUserNotificationAlternateResponse: rc = IDRETRY; break; case kCFUserNotificationOtherResponse: rc = IDIGNORE; break; } break; case MB_YESNO: switch (response) { case kCFUserNotificationDefaultResponse: rc = IDYES; break; case kCFUserNotificationAlternateResponse: rc = IDNO; break; } break; case MB_OKCANCEL: switch (response) { case kCFUserNotificationDefaultResponse: rc = IDOK; break; case kCFUserNotificationAlternateResponse: rc = IDCANCEL; break; } break; case MB_RETRYCANCEL: switch (response) { case kCFUserNotificationDefaultResponse: rc = IDRETRY; break; case kCFUserNotificationAlternateResponse: rc = IDCANCEL; break; } break; } } else { // We're not in a login session, e.g., running via ssh, and so bringing // up a message box would be bad form. fprintf ( stderr, "MessageBox: %s: %s", lpCaption, lpText ); syslog(LOG_USER|LOG_ERR, "MessageBox: %s: %s", lpCaption, lpText); } #else // __APPLE__ fprintf ( stderr, "MessageBox: %s: %s", lpCaption, lpText ); syslog(LOG_USER|LOG_ERR, "MessageBox: %s: %s", lpCaption, lpText); // Some systems support displaying a GUI dialog. (This will suspend the current thread until they hit the // 'OK' button and allow a debugger to be attached). PAL_DisplayDialog(lpCaption, lpText); #endif // __APPLE__ else PALCLeaveCriticalSection( &msgbox_critsec); LOGEXIT("MessageBoxA returns %d\n", rc); PERF_EXIT(MessageBoxA); return rc; }
/* The use of ULONG is by design, to ensure that a 32 bit value is always returned from this function. If "unsigned long" is used instead of ULONG, then a 64 bit value could be returned on 64 bit platforms like HP-UX, thus breaking Windows behavior .*/ ULONG __cdecl PAL_wcstoul( const wchar_16 *nptr, wchar_16 **endptr, int base) { char *s_nptr = 0; char *s_endptr = 0; unsigned long res; int size; DWORD dwLastError = 0; PERF_ENTRY(wcstoul); ENTRY("wcstoul (nptr=%p (%S), endptr=%p, base=%d)\n", nptr?nptr:W16_NULLSTRING, nptr?nptr:W16_NULLSTRING, endptr, base); THREADMarkDiagnostic("PAL_wcstoul -> strtoul"); size = WideCharToMultiByte(CP_ACP, 0, nptr, -1, NULL, 0, NULL, NULL); if (!size) { dwLastError = GetLastError(); ASSERT("WideCharToMultiByte failed. Error is %d\n", dwLastError); SetLastError(ERROR_INVALID_PARAMETER); res = 0; goto PAL_wcstoulExit; } s_nptr = (char *)PAL_malloc(size); if (!s_nptr) { ERROR("PAL_malloc failed\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); res = 0; goto PAL_wcstoulExit; } size = WideCharToMultiByte(CP_ACP, 0, nptr, -1, s_nptr, size, NULL, NULL); if (!size) { dwLastError = GetLastError(); ASSERT("WideCharToMultiByte failed. Error is %d\n", dwLastError); SetLastError(ERROR_INVALID_PARAMETER); res = 0; goto PAL_wcstoulExit; } res = strtoul(s_nptr, &s_endptr, base); #ifdef BIT64 if (res > _UI32_MAX) { wchar_16 wc = *nptr; while (PAL_iswspace(wc)) { wc = *nptr++; } /* If the string represents a positive number that is greater than _UI32_MAX, set errno to ERANGE. Otherwise, don't set errno to match Windows behavior. */ if (wc != '-') { res = _UI32_MAX; errno = ERANGE; } } #endif /* only ASCII characters will be accepted by strtol, and those always get mapped to single-byte characters, so the first rejected character will have the same index in the multibyte and widechar strings */ if( endptr ) { size = s_endptr - s_nptr; *endptr = (wchar_16 *)&nptr[size]; } PAL_wcstoulExit: PAL_free(s_nptr); LOGEXIT("wcstoul returning unsigned long %lu\n", res); PERF_EXIT(wcstoul); /* When returning unsigned long res from this function, it will be implicitly cast to ULONG. This handles situations where a string that represents a negative number is passed in to wcstoul. The Windows behavior is analogous to taking the binary equivalent of the negative value and treating it as a positive number. Returning a ULONG from this function, as opposed to native unsigned long, allows us to match this behavior. The explicit case to ULONG below is used to silence any potential warnings due to the implicit casting. */ return (ULONG)res; }
BOOL PALAPI PAL_Random( IN BOOL bStrong, IN OUT LPVOID lpBuffer, IN DWORD dwLength) { int rand_des = -1; BOOL bRet = FALSE; DWORD i; char buf; long num = 0; static BOOL sMissingDevRandom; static BOOL sMissingDevURandom; static BOOL sInitializedMRand; PERF_ENTRY(PAL_Random); ENTRY("PAL_Random(bStrong=%d, lpBuffer=%p, dwLength=%d)\n", bStrong, lpBuffer, dwLength); i = 0; if (bStrong == TRUE && i < dwLength && !sMissingDevRandom) { // request non-blocking access to avoid hangs if the /dev/random is exhausted // or just simply broken if ((rand_des = PAL__open(RANDOM_DEVICE_NAME, O_RDONLY | O_NONBLOCK)) == -1) { if (errno == ENOENT) { sMissingDevRandom = TRUE; } else { ASSERT("PAL__open() failed, errno:%d (%s)\n", errno, strerror(errno)); } // Back off and try /dev/urandom. } else { for( ; i < dwLength; i++) { if (read(rand_des, &buf, 1) < 1) { // the /dev/random pool has been exhausted. Fall back // to /dev/urandom for the remainder of the buffer. break; } *(((BYTE*)lpBuffer) + i) ^= buf; } close(rand_des); } } if (i < dwLength && !sMissingDevURandom) { if ((rand_des = PAL__open(URANDOM_DEVICE_NAME, O_RDONLY)) == -1) { if (errno == ENOENT) { sMissingDevURandom = TRUE; } else { ASSERT("PAL__open() failed, errno:%d (%s)\n", errno, strerror(errno)); } // Back off and try mrand48. } else { for( ; i < dwLength; i++) { if (read(rand_des, &buf, 1) < 1) { // Fall back to srand48 for the remainder of the buffer. break; } *(((BYTE*)lpBuffer) + i) ^= buf; } close(rand_des); } } if (!sInitializedMRand) { srand48(time(NULL)); sInitializedMRand = TRUE; } // always xor srand48 over the whole buffer to get some randomness // in case /dev/random is not really random for(i = 0; i < dwLength; i++) { if (i % sizeof(long) == 0) { num = mrand48(); } *(((BYTE*)lpBuffer) + i) ^= num; num >>= 8; } bRet = TRUE; LOGEXIT("PAL_Random returns %d\n", bRet); PERF_EXIT(PAL_Random); return bRet; }
/*++ Function: SetCurrentDirectoryW See MSDN doc. --*/ BOOL PALAPI SetCurrentDirectoryW( IN LPCWSTR lpPathName) { BOOL bRet; DWORD dwLastError = 0; PathCharString dirPathString; int size; size_t length; char * dir; PERF_ENTRY(SetCurrentDirectoryW); ENTRY("SetCurrentDirectoryW(lpPathName=%p (%S))\n", lpPathName?lpPathName:W16_NULLSTRING, lpPathName?lpPathName:W16_NULLSTRING); /*check if the given path is null. If so return FALSE*/ if (lpPathName == NULL ) { ERROR("Invalid path/directory name\n"); dwLastError = ERROR_INVALID_NAME; bRet = FALSE; goto done; } length = (PAL_wcslen(lpPathName)+1) * 3; dir = dirPathString.OpenStringBuffer(length); if (NULL == dir) { dwLastError = ERROR_NOT_ENOUGH_MEMORY; bRet = FALSE; goto done; } size = WideCharToMultiByte( CP_ACP, 0, lpPathName, -1, dir, length, NULL, NULL ); dirPathString.CloseBuffer(size); if( size == 0 ) { dwLastError = GetLastError(); if( dwLastError == ERROR_INSUFFICIENT_BUFFER ) { WARN("lpPathName is larger than MAX_LONGPATH (%d)!\n", MAX_LONGPATH); dwLastError = ERROR_FILENAME_EXCED_RANGE; } else { ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError); dwLastError = ERROR_INTERNAL_ERROR; } bRet = FALSE; goto done; } bRet = SetCurrentDirectoryA(dir); done: if( dwLastError ) { SetLastError(dwLastError); } LOGEXIT("SetCurrentDirectoryW returns BOOL %d\n", bRet); PERF_EXIT(SetCurrentDirectoryW); return bRet; }
/*++ Function: CreateDirectoryA Note: lpSecurityAttributes always NULL. See MSDN doc. --*/ BOOL PALAPI CreateDirectoryA( IN LPCSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes) { BOOL bRet = FALSE; DWORD dwLastError = 0; char *realPath; LPSTR UnixPathName = NULL; int pathLength; int i; const int mode = S_IRWXU | S_IRWXG | S_IRWXO; PERF_ENTRY(CreateDirectoryA); ENTRY("CreateDirectoryA(lpPathName=%p (%s), lpSecurityAttr=%p)\n", lpPathName?lpPathName:"NULL", lpPathName?lpPathName:"NULL", lpSecurityAttributes); if ( lpSecurityAttributes ) { ASSERT("lpSecurityAttributes is not NULL as it should be\n"); dwLastError = ERROR_INVALID_PARAMETER; goto done; } // Windows returns ERROR_PATH_NOT_FOUND when called with NULL. // If we don't have this check, strdup(NULL) segfaults. if (lpPathName == NULL) { ERROR("CreateDirectoryA called with NULL pathname!\n"); dwLastError = ERROR_PATH_NOT_FOUND; goto done; } UnixPathName = PAL__strdup(lpPathName); if (UnixPathName == NULL ) { ERROR("PAL__strdup() failed\n"); dwLastError = ERROR_NOT_ENOUGH_MEMORY; goto done; } FILEDosToUnixPathA( UnixPathName ); // Remove any trailing slashes at the end because mkdir might not // handle them appropriately on all platforms. pathLength = strlen(UnixPathName); i = pathLength; while(i > 1) { if(UnixPathName[i - 1] =='/') { UnixPathName[i - 1]='\0'; i--; } else { break; } } // Check the constraint for the real path length (should be < MAX_LONGPATH). // Get an absolute path. if (UnixPathName[0] == '/') { realPath = UnixPathName; } else { const char *cwd = PAL__getcwd(NULL, MAX_LONGPATH); if (NULL == cwd) { WARN("Getcwd failed with errno=%d [%s]\n", errno, strerror(errno)); dwLastError = DIRGetLastErrorFromErrno(); goto done; } // Copy cwd, '/', path int iLen = strlen(cwd) + 1 + pathLength + 1; realPath = static_cast<char *>(alloca(iLen)); sprintf_s(realPath, iLen, "%s/%s", cwd, UnixPathName); PAL_free((char *)cwd); } // Canonicalize the path so we can determine its length. FILECanonicalizePath(realPath); if (strlen(realPath) >= MAX_LONGPATH) { WARN("UnixPathName is larger than MAX_LONGPATH (%d)!\n", MAX_LONGPATH); dwLastError = ERROR_FILENAME_EXCED_RANGE; goto done; } if ( mkdir(realPath, mode) != 0 ) { TRACE("Creation of directory [%s] was unsuccessful, errno = %d.\n", UnixPathName, errno); switch( errno ) { case ENOTDIR: /* FALL THROUGH */ case ENOENT: FILEGetProperNotFoundError( realPath, &dwLastError ); goto done; case EEXIST: dwLastError = ERROR_ALREADY_EXISTS; break; default: dwLastError = ERROR_ACCESS_DENIED; } } else { TRACE("Creation of directory [%s] was successful.\n", UnixPathName); bRet = TRUE; } done: if( dwLastError ) { SetLastError( dwLastError ); } PAL_free( UnixPathName ); LOGEXIT("CreateDirectoryA returns BOOL %d\n", bRet); PERF_EXIT(CreateDirectoryA); return bRet; }
__cdecl PAL_wcstok(wchar_16 *strToken, const wchar_16 *strDelimit) { wchar_16 *retval = NULL; wchar_16 *delim_ptr; wchar_16 *next_context; /* string to save in TLS for future calls */ int ret; ENTRY("wcstok (strToken=%p (%S), strDelimit=%p (%S))\n", strToken?strToken:W16_NULLSTRING, strToken?strToken:W16_NULLSTRING, strDelimit?strDelimit:W16_NULLSTRING, strDelimit?strDelimit:W16_NULLSTRING); if(NULL == strDelimit) { ERROR("delimiter string is NULL\n"); goto done; } /* get token string from TLS if none is provided */ if(NULL == strToken) { TRACE("wcstok() called with NULL string, using previous string\n"); strToken = pthread_getspecific(wcstokKey); if(NULL == strToken) { ERROR("wcstok called with NULL string without a previous call\n"); goto done; } } /* first, skip all leading delimiters */ while(PAL_wcschr(strDelimit,*strToken)) { strToken++; } /* if there were only delimiters, there's no string */ if('\0' == strToken[0]) { TRACE("end of string already reached, returning NULL\n"); goto done; } /* we're now at the beginning of the token; look for the first delimiter */ delim_ptr = PAL_wcspbrk(strToken,strDelimit); if(NULL == delim_ptr) { TRACE("no delimiters found, this is the last token\n"); /* place the next context at the end of the string, so that subsequent calls will return NULL */ next_context = strToken+PAL_wcslen(strToken); retval = strToken; } else { /* null-terminate current token */ *delim_ptr=0; /* place the next context right after the delimiter */ next_context = delim_ptr+1; retval = strToken; TRACE("found delimiter; next token will be %p\n",next_context); } if ((ret = pthread_setspecific(wcstokKey, next_context)) != 0) { ERROR("pthread_setspecific() failed error:%d (%s)\n", ret, strerror(ret)); retval = NULL; } done: LOGEXIT("wcstok() returns %p (%S)\n", retval?retval:W16_NULLSTRING, retval?retval:W16_NULLSTRING); return(retval); }
/*++ Function: RemoveDirectoryW See MSDN doc. --*/ BOOL PALAPI RemoveDirectoryW( IN LPCWSTR lpPathName) { PathCharString mb_dirPathString; int mb_size; DWORD dwLastError = 0; BOOL bRet = FALSE; size_t length; char * mb_dir; PERF_ENTRY(RemoveDirectoryW); ENTRY("RemoveDirectoryW(lpPathName=%p (%S))\n", lpPathName?lpPathName:W16_NULLSTRING, lpPathName?lpPathName:W16_NULLSTRING); if (lpPathName == NULL) { dwLastError = ERROR_PATH_NOT_FOUND; goto done; } length = (PAL_wcslen(lpPathName)+1) * 3; mb_dir = mb_dirPathString.OpenStringBuffer(length); if (NULL == mb_dir) { dwLastError = ERROR_NOT_ENOUGH_MEMORY; goto done; } mb_size = WideCharToMultiByte( CP_ACP, 0, lpPathName, -1, mb_dir, length, NULL, NULL ); mb_dirPathString.CloseBuffer(mb_size); if( mb_size == 0 ) { dwLastError = GetLastError(); if( dwLastError == ERROR_INSUFFICIENT_BUFFER ) { WARN("lpPathName is larger than MAX_LONGPATH (%d)!\n", MAX_LONGPATH); dwLastError = ERROR_FILENAME_EXCED_RANGE; } else { ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError); dwLastError = ERROR_INTERNAL_ERROR; } goto done; } if ((bRet = RemoveDirectoryHelper (mb_dir, &dwLastError))) { TRACE("Removal of directory [%s] was successful.\n", mb_dir); } done: if( dwLastError ) { SetLastError( dwLastError ); } LOGEXIT("RemoveDirectoryW returns BOOL %d\n", bRet); PERF_EXIT(RemoveDirectoryW); return bRet; }
int moloch_field_define_text(char *text, int *shortcut) { int count = 0; char *field = 0; char *kind = 0; char *help = 0; char *db = 0; char *group = 0; char *friendly = 0; char *category = 0; if (config.debug) LOG("Parsing %s", text); char **elements = g_strsplit(text, ";", 0); int e; for (e = 0; elements[e]; e++) { char *colon = strchr(elements[e], ':'); if (!colon) continue; *colon = 0; colon++; if (strcmp(elements[e], "field") == 0) field = colon; else if (strcmp(elements[e], "kind") == 0) kind = colon; else if (strcmp(elements[e], "group") == 0) group = colon; else if (strcmp(elements[e], "count") == 0) count = strcmp(colon, "true") == 0; else if (strcmp(elements[e], "friendly") == 0) friendly = colon; else if (strcmp(elements[e], "db") == 0) db = colon; else if (strcmp(elements[e], "help") == 0) help = colon; else if (strcmp(elements[e], "category") == 0) category = colon; else if (strcmp(elements[e], "shortcut") == 0) { if (shortcut) *shortcut = atoi(colon); } } if (!field) { LOG("Didn't find field 'field:' in '%s'", text); g_strfreev(elements); return -1; } if (!db) { int pos = moloch_field_by_exp(field); g_strfreev(elements); if (pos != -1) return pos; LOG("Didn't find field 'db:' in '%s'", text); return -1; } if (!kind) { LOG("Didn't find field 'kind:' in '%s'", text); g_strfreev(elements); return -1; } if (strstr(kind, "termfield") != 0 && strstr(db, "-term") == 0) { LOGEXIT("ERROR - db field %s for %s should end with -term in '%s'", kind, db, text); } char groupbuf[100]; if (!group) { char *dot = strchr(field, '.'); if (dot) { memcpy(groupbuf, field, MIN(100, dot-field)); groupbuf[dot-field] = 0; group = groupbuf; } else { group = "general"; } } if (!friendly) friendly = field; if (!help) help = field; int type, flags = 0; if (strcmp(kind, "integer") == 0 || strcmp(kind, "seconds") == 0) type = MOLOCH_FIELD_TYPE_INT_GHASH; else if (strcmp(kind, "ip") == 0) { type = MOLOCH_FIELD_TYPE_IP_GHASH; if (!category) category = "ip"; } else type = MOLOCH_FIELD_TYPE_STR_HASH; if (count) flags |= MOLOCH_FIELD_FLAG_COUNT; int pos = moloch_field_define(group, kind, field, friendly, db, help, type, flags, "category", category, NULL); g_strfreev(elements); return pos; }
int moloch_field_define(char *group, char *kind, char *expression, char *friendlyName, char *dbField, char *help, int type, int flags, ...) { char dbField2[100]; char expression2[1000]; char friendlyName2[1000]; char help2[1000]; char rawField[100]; MolochFieldInfo_t *minfo = 0; HASH_FIND(d_, fieldsByDb, dbField, minfo); if (!minfo) { minfo = MOLOCH_TYPE_ALLOC0(MolochFieldInfo_t); minfo->dbFieldFull = g_strdup(dbField); minfo->dbField = minfo->dbFieldFull; minfo->dbFieldLen = strlen(minfo->dbField); minfo->pos = -1; minfo->expression = g_strdup(expression); minfo->group = g_strdup(group); minfo->kind = g_strdup(kind); HASH_ADD(d_, fieldsByDb, minfo->dbField, minfo); HASH_ADD(e_, fieldsByExp, minfo->expression, minfo); if ((flags & MOLOCH_FIELD_FLAG_NODB) == 0) { va_list args; va_start(args, flags); moloch_db_add_field(group, kind, expression, friendlyName, dbField, help, TRUE, args); va_end(args); } } else { char *category = NULL; if (strcmp(kind, minfo->kind) != 0) { LOG("WARNING - Field kind in db %s doesn't match field kind %s in capture for field %s", minfo->kind, kind, expression); } va_list args; va_start(args, flags); while(1) { char *field = va_arg(args, char *); if (!field) break; char *value = va_arg(args, char *); if (strcmp(field, "category") == 0 && value) { category = value; } } va_end(args); if (category && (!minfo->category || strcmp(category, minfo->category) != 0)) { LOG("UPDATING - Field category in db %s doesn't match field category %s in capture for field %s", minfo->category, category, expression); moloch_db_update_field(expression, "category", category); } } // Hack to remove trailing .snow on capture side int dbLen = strlen(minfo->dbField); if (dbLen > 5 && memcmp(".snow", minfo->dbField+dbLen-5, 5) == 0) { minfo->dbField[dbLen-5] = 0; minfo->dbFieldLen -= 5; } minfo->type = type; minfo->flags = flags; if ((flags & MOLOCH_FIELD_FLAG_FAKE) == 0) { if (minfo->pos == -1) { minfo->pos = config.maxField++; if (config.maxField > 255) { LOGEXIT("ERROR - Max Fields is too large %d", config.maxField); } } config.fields[minfo->pos] = minfo; // Change leading part to dbGroup char *firstdot = strchr(minfo->dbField, '.'); if (firstdot) { static char lastGroup[100] = ""; static int groupNum = 0; if (memcmp(minfo->dbField, lastGroup, (firstdot-minfo->dbField)+1) == 0) { minfo->dbGroupNum = groupNum; } else { groupNum++; minfo->dbGroupNum = groupNum; memcpy(lastGroup, minfo->dbField, (firstdot-minfo->dbField)+1); } minfo->dbGroup = minfo->dbField; minfo->dbGroupLen = firstdot - minfo->dbField; minfo->dbField += (firstdot - minfo->dbField) + 1; minfo->dbFieldLen = strlen(minfo->dbField); } } if (flags & MOLOCH_FIELD_FLAG_NODB) return minfo->pos; MolochFieldInfo_t *info = 0; if (flags & MOLOCH_FIELD_FLAG_CNT) { snprintf(dbField2, sizeof(dbField2), "%scnt", dbField); HASH_FIND(d_, fieldsByDb, dbField2, info); if (!info) { snprintf(expression2, sizeof(expression2), "%s.cnt", expression); snprintf(friendlyName2, sizeof(friendlyName2), "%s Cnt", friendlyName); snprintf(help2, sizeof(help2), "Unique number of %s", help); moloch_db_add_field(group, "integer", expression2, friendlyName2, dbField2, help2, FALSE, empty_va_list); } } if (flags & MOLOCH_FIELD_FLAG_SCNT) { snprintf(dbField2, sizeof(dbField2), "%sscnt", dbField); HASH_FIND(d_, fieldsByDb, dbField2, info); if (!info) { snprintf(expression2, sizeof(expression2), "%s.cnt", expression); snprintf(friendlyName2, sizeof(friendlyName2), "%s Cnt", friendlyName); snprintf(help2, sizeof(help2), "Unique number of %s", help); moloch_db_add_field(group, "integer", expression2, friendlyName2, dbField2, help2, FALSE, empty_va_list); } } if (flags & MOLOCH_FIELD_FLAG_COUNT) { snprintf(dbField2, sizeof(dbField2), "%s-cnt", dbField); HASH_FIND(d_, fieldsByDb, dbField2, info); if (!info) { snprintf(expression2, sizeof(expression2), "%s.cnt", expression); snprintf(friendlyName2, sizeof(friendlyName2), "%s Cnt", friendlyName); snprintf(help2, sizeof(help2), "Unique number of %s", help); moloch_db_add_field(group, "integer", expression2, friendlyName2, dbField2, help2, FALSE, empty_va_list); } } if (flags & MOLOCH_FIELD_FLAG_FAKE) { g_free(minfo->expression); g_free(minfo->dbField); g_free(minfo->group); g_free(minfo->kind); HASH_REMOVE(d_, fieldsByDb, minfo); HASH_REMOVE(e_, fieldsByExp, minfo); MOLOCH_TYPE_FREE(MolochFieldInfo_t, minfo); return -1; } if (flags & MOLOCH_FIELD_FLAG_IPPRE) { int fnlen = strlen(friendlyName); snprintf(dbField2, sizeof(dbField2), "g%s", dbField); HASH_FIND(d_, fieldsByDb, dbField2, info); if (!info) { snprintf(expression2, sizeof(expression2), "country.%s", expression+3); snprintf(friendlyName2, sizeof(friendlyName2), "%.*s GEO", fnlen-2, friendlyName); snprintf(help2, sizeof(help2), "GeoIP country string calculated from the %s", help); moloch_db_add_field(group, "uptermfield", expression2, friendlyName2, dbField2, help2, FALSE, empty_va_list); } snprintf(dbField2, sizeof(dbField2), "as%s", dbField); HASH_FIND(d_, fieldsByDb, dbField2, info); if (!info) { snprintf(expression2, sizeof(expression2), "asn.%s", expression+3); snprintf(friendlyName2, sizeof(friendlyName2), "%.*s ASN", fnlen-2, friendlyName); snprintf(help2, sizeof(help2), "GeoIP ASN string calculated from the %s", help); snprintf(rawField, sizeof(rawField), "raw%s", dbField2); moloch_session_add_field_proxy(group, "textfield", expression2, friendlyName2, dbField2, help2, "rawField", rawField, NULL); } snprintf(dbField2, sizeof(dbField2), "rir%s", dbField); HASH_FIND(d_, fieldsByDb, dbField2, info); if (!info) { snprintf(expression2, sizeof(expression2), "rir.%s", expression+3); snprintf(friendlyName2, sizeof(friendlyName2), "%.*s RIR", fnlen-2, friendlyName); snprintf(help2, sizeof(help2), "Regional Internet Registry string calculated from %s", help); moloch_db_add_field(group, "uptermfield", expression2, friendlyName2, dbField2, help2, FALSE, empty_va_list); } } else if (type == MOLOCH_FIELD_TYPE_IP || type == MOLOCH_FIELD_TYPE_IP_HASH || type == MOLOCH_FIELD_TYPE_IP_GHASH) { snprintf(dbField2, sizeof(dbField2), "%s-geo", dbField); HASH_FIND(d_, fieldsByDb, dbField2, info); if (!info) { snprintf(expression2, sizeof(expression2), "%s.country", expression); snprintf(friendlyName2, sizeof(friendlyName2), "%s GEO", friendlyName); snprintf(help2, sizeof(help2), "GeoIP country string calculated from the %s", help); moloch_db_add_field(group, "uptermfield", expression2, friendlyName2, dbField2, help2, FALSE, empty_va_list); } snprintf(dbField2, sizeof(dbField2), "%s-asn.snow", dbField); HASH_FIND(d_, fieldsByDb, dbField2, info); if (!info) { snprintf(dbField2, sizeof(dbField2), "%s-asn.snow", dbField); snprintf(expression2, sizeof(expression2), "%s.asn", expression); snprintf(friendlyName2, sizeof(friendlyName2), "%s ASN", friendlyName); snprintf(rawField, sizeof(rawField), "%s-asn.raw", dbField); snprintf(help2, sizeof(help2), "GeoIP ASN string calculated from the %s", help); moloch_session_add_field_proxy(group, "textfield", expression2, friendlyName2, dbField2, help2, "rawField", rawField, NULL); } snprintf(dbField2, sizeof(dbField2), "%s-rir", dbField); HASH_FIND(d_, fieldsByDb, dbField2, info); if (!info) { snprintf(expression2, sizeof(expression2), "%s.rir", expression); snprintf(friendlyName2, sizeof(friendlyName2), "%s RIR", friendlyName); snprintf(help2, sizeof(help2), "Regional Internet Registry string calculated from %s", help); moloch_db_add_field(group, "uptermfield", expression2, friendlyName2, dbField2, help2, FALSE, empty_va_list); } } return minfo->pos; }
void moloch_config_load_header(char *section, char *group, char *helpBase, char *expBase, char *dbBase, MolochStringHashStd_t *hash, int flags) { GError *error = 0; char name[100]; if (!g_key_file_has_group(molochKeyFile, section)) return; gsize keys_len; gchar **keys = g_key_file_get_keys (molochKeyFile, section, &keys_len, &error); if (error) { LOGEXIT("Error with %s: %s", section, error->message); } gsize k, v; for (k = 0 ; k < keys_len; k++) { gsize values_len; gchar **values = g_key_file_get_string_list(molochKeyFile, section, keys[k], &values_len, NULL); snprintf(name, sizeof(name), "%s", keys[k]); int type = 0; int t = 0; int unique = 1; int count = 0; char *kind = 0; for (v = 0; v < values_len; v++) { if (strcmp(values[v], "type:integer") == 0 || strcmp(values[v], "type:seconds") == 0) { type = 1; kind = values[v] + 5; } else if (strcmp(values[v], "type:ip") == 0) { type = 2; } else if (strcmp(values[v], "unique:false") == 0) { unique = 0; } else if (strcmp(values[v], "count:true") == 0) { count = 1; } } int f = flags; if (count) f |= MOLOCH_FIELD_FLAG_CNT; switch (type) { case 0: kind = "termfield"; if (unique) t = MOLOCH_FIELD_TYPE_STR_HASH; else t = MOLOCH_FIELD_TYPE_STR_ARRAY; break; case 1: if (unique) t = MOLOCH_FIELD_TYPE_INT_GHASH; else t = MOLOCH_FIELD_TYPE_INT_ARRAY; break; case 2: kind = "ip"; t = MOLOCH_FIELD_TYPE_IP_GHASH; break; } MolochString_t *hstring; HASH_FIND(s_, *hash, keys[k], hstring); if (hstring) { LOG("WARNING - ignoring field %s for %s", keys[k], section); g_strfreev(values); continue; } char expression[100]; char field[100]; char help[100]; snprintf(expression, sizeof(expression), "%s%s", expBase, name); snprintf(field, sizeof(field), "%s%s", dbBase, name); snprintf(help, sizeof(help), "%s%s", helpBase, name); int pos; pos = moloch_field_define(group, kind, expression, expression, field, help, t, f, NULL); moloch_config_add_header(hash, g_strdup(keys[k]), pos); g_strfreev(values); } g_strfreev(keys); }
__cdecl _ui64tow( unsigned __int64 value , wchar_16 * string , int radix ) { UINT ReversedIndex = 0; WCHAR ReversedString[ 65 ]; LPWSTR lpString = string; UINT Index = 0; PERF_ENTRY(_ui64tow); ENTRY( "_ui64tow( value=%I64d, string=%p (%S), radix=%d )\n", value, string, string, radix ); if ( !string ) { ERROR( "string has to be a valid pointer.\n" ); LOGEXIT( "_ui64tow returning NULL.\n" ); PERF_EXIT(_ui64tow); return NULL; } if ( radix < 2 || radix > 36 ) { ERROR( "radix has to be between 2 and 36.\n" ); LOGEXIT( "_ui64tow returning NULL.\n" ); PERF_EXIT(_ui64tow); return NULL; } if(0 == value) { ReversedString[0] = '0'; Index++; } else while ( value ) { int temp = value % radix; value /= radix; if ( temp < 10 ) { ReversedString[ Index ] = temp + '0'; Index++; } else { ReversedString[ Index ] = temp - 10 + 'a'; Index++; } } /* Reverse the string. */ ReversedIndex = Index; for ( Index = 0; ReversedIndex > 0; ReversedIndex--, Index++ ) { string[ Index ] = ReversedString[ ReversedIndex - 1 ]; } string[ Index ] = '\0'; LOGEXIT( "_ui64tow returning %p (%S).\n", lpString , lpString ); PERF_EXIT(_ui64tow); return lpString; }
/*++ Function: SetCurrentDirectoryA See MSDN doc. --*/ BOOL PALAPI SetCurrentDirectoryA( IN LPCSTR lpPathName) { BOOL bRet = FALSE; DWORD dwLastError = 0; int result; LPSTR UnixPathName = NULL; PERF_ENTRY(SetCurrentDirectoryA); ENTRY("SetCurrentDirectoryA(lpPathName=%p (%s))\n", lpPathName?lpPathName:"NULL", lpPathName?lpPathName:"NULL"); /*check if the given path is null. If so return FALSE*/ if (lpPathName == NULL ) { ERROR("Invalid path/directory name\n"); dwLastError = ERROR_INVALID_NAME; goto done; } if (strlen(lpPathName) >= MAX_LONGPATH) { WARN("Path/directory name longer than MAX_LONGPATH characters\n"); dwLastError = ERROR_FILENAME_EXCED_RANGE; goto done; } UnixPathName = PAL__strdup(lpPathName); if (UnixPathName == NULL ) { ERROR("PAL__strdup() failed\n"); dwLastError = ERROR_NOT_ENOUGH_MEMORY; goto done; } FILEDosToUnixPathA( UnixPathName ); TRACE("Attempting to open Unix dir [%s]\n", UnixPathName); result = chdir(UnixPathName); if ( result == 0 ) { bRet = TRUE; } else { if ( errno == ENOTDIR || errno == ENOENT ) { struct stat stat_data; if ( stat( UnixPathName, &stat_data) == 0 && (stat_data.st_mode & S_IFMT) == S_IFREG ) { /* Not a directory, it is a file. */ dwLastError = ERROR_DIRECTORY; } else { FILEGetProperNotFoundError( UnixPathName, &dwLastError ); } TRACE("chdir() failed, path was invalid.\n"); } else { dwLastError = ERROR_ACCESS_DENIED; ERROR("chdir() failed; errno is %d (%s)\n", errno, strerror(errno)); } } done: if( dwLastError ) { SetLastError(dwLastError); } if(UnixPathName != NULL) { PAL_free( UnixPathName ); } LOGEXIT("SetCurrentDirectoryA returns BOOL %d\n", bRet); PERF_EXIT(SetCurrentDirectoryA); return bRet; }
/* The use of LONG is by design, to ensure that a 32 bit value is always returned from this function. If "long" is used instead of LONG, then a 64 bit value could be returned on 64 bit platforms like HP-UX, thus breaking Windows behavior. */ LONG __cdecl PAL_wcstol( const wchar_16 *nptr, wchar_16 **endptr, int base) { char *s_nptr = 0; char *s_endptr = 0; long res; int size; DWORD dwLastError = 0; PERF_ENTRY(wcstol); ENTRY("wcstol (nptr=%p (%S), endptr=%p, base=%d)\n", nptr?nptr:W16_NULLSTRING, nptr?nptr:W16_NULLSTRING, endptr, base); size = WideCharToMultiByte(CP_ACP, 0, nptr, -1, NULL, 0, NULL, NULL); if (!size) { dwLastError = GetLastError(); ASSERT("WideCharToMultiByte failed. Error is %d\n", dwLastError); SetLastError(ERROR_INVALID_PARAMETER); res = 0; goto PAL_wcstolExit; } s_nptr = (char *)PAL_malloc(size); if (!s_nptr) { ERROR("PAL_malloc failed\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); res = 0; goto PAL_wcstolExit; } size = WideCharToMultiByte(CP_ACP, 0, nptr, -1, s_nptr, size, NULL, NULL); if( size==0 ) { dwLastError = GetLastError(); ASSERT("WideCharToMultiByte failed. Error is %d\n", dwLastError); SetLastError(ERROR_INVALID_PARAMETER); res = 0; goto PAL_wcstolExit; } res = strtol(s_nptr, &s_endptr, base); #ifdef BIT64 if (res > _I32_MAX) { res = _I32_MAX; errno = ERANGE; } else if (res < _I32_MIN) { res = _I32_MIN; errno = ERANGE; } #endif /* only ASCII characters will be accepted by strtol, and those always get mapped to single-byte characters, so the first rejected character will have the same index in the multibyte and widechar strings */ if( endptr ) { size = s_endptr - s_nptr; *endptr = (wchar_16 *)&nptr[size]; } PAL_wcstolExit: PAL_free(s_nptr); LOGEXIT("wcstol returning long %ld\n", res); PERF_EXIT(wcstol); /* This explicit cast to LONG is used to silence any potential warnings due to implicitly casting the native long res to LONG when returning. */ return (LONG)res; }
/*++ Function: MessageBoxW This is a small subset of MessageBox that simply logs a message to the system logging facility and returns. A typical log entry will look like: May 23 15:48:10 rice example1: MessageBox: Caption: Error Text Note: hWnd should always be NULL. See MSDN doc. --*/ int PALAPI MessageBoxW( IN LPVOID hWnd, IN LPCWSTR lpText, IN LPCWSTR lpCaption, IN UINT uType) { CHAR *text = NULL; CHAR *caption = NULL; INT len = 0; INT rc = 0; ENTRY( "MessageBoxW (hWnd=%p, lpText=%p (%S), lpCaption=%p (%S), uType=%#x)\n", hWnd, lpText?lpText:W16_NULLSTRING, lpText?lpText:W16_NULLSTRING, lpCaption?lpCaption:W16_NULLSTRING, lpCaption?lpCaption:W16_NULLSTRING, uType ); if (hWnd != NULL) { ASSERT("hWnd != NULL"); } if(lpText) { len = WideCharToMultiByte(CP_ACP, 0, lpText, -1, NULL, 0, NULL, NULL); if(len) { text = (LPSTR)malloc(len); if(!text) { ERROR("malloc() failed!\n"); SetLastError( ERROR_NOT_ENOUGH_MEMORY ); goto error; } if( !WideCharToMultiByte( CP_ACP, 0, lpText, -1, text, len, NULL, NULL)) { ASSERT("WideCharToMultiByte failure\n"); SetLastError( ERROR_INTERNAL_ERROR ); goto error; } } else { ASSERT("WideCharToMultiByte failure\n"); SetLastError( ERROR_INTERNAL_ERROR ); goto error; } } else { WARN("No message text\n"); if (NULL == (text = strdup("(no message text)"))) { ASSERT("strdup() failed\n"); SetLastError( ERROR_INTERNAL_ERROR ); goto error; } } if (lpCaption) { len = WideCharToMultiByte( CP_ACP, 0, lpCaption, -1, NULL, 0, NULL, NULL); if(len) { caption = (CHAR*)malloc(len); if(!caption) { ERROR("malloc() failed!\n"); SetLastError( ERROR_NOT_ENOUGH_MEMORY ); goto error; } if( !WideCharToMultiByte( CP_ACP, 0, lpCaption, -1, caption, len, NULL, NULL)) { ASSERT("WideCharToMultiByte failure\n"); SetLastError( ERROR_INTERNAL_ERROR ); goto error; } } else { ASSERT("WideCharToMultiByte failure\n"); SetLastError( ERROR_INTERNAL_ERROR ); goto error; } } else { if (NULL == (caption = strdup("Error"))) { ERROR("strdup() failed\n"); SetLastError( ERROR_NOT_ENOUGH_MEMORY ); goto error; } } SYNCEnterCriticalSection( &msgbox_critsec, TRUE ); syslog(LOG_USER|LOG_ERR, "MessageBox: %s: %s", caption, text); SYNCLeaveCriticalSection( &msgbox_critsec, TRUE ); error: free(caption); free(text); /* return a status based on the type of button */ switch(uType & MB_TYPEMASK) { case MB_OK: rc = IDOK; break; case MB_ABORTRETRYIGNORE: rc = IDABORT; break; case MB_YESNO: rc = IDNO; break; case MB_OKCANCEL : rc = IDCANCEL; break; case MB_RETRYCANCEL : rc = IDCANCEL; break; default: ASSERT("Bad uType"); rc = IDOK; break; } LOGEXIT("MessageBoxW returns %d\n", rc); return rc; }
ULONGLONG __cdecl PAL__wcstoui64( const wchar_16 *nptr, wchar_16 **endptr, int base) { char *s_nptr = 0; char *s_endptr = 0; unsigned long long res; int size; DWORD dwLastError = 0; PERF_ENTRY(wcstoul); ENTRY("_wcstoui64 (nptr=%p (%S), endptr=%p, base=%d)\n", nptr?nptr:W16_NULLSTRING, nptr?nptr:W16_NULLSTRING, endptr, base); THREADMarkDiagnostic("PAL__wcstoui64 -> strtoull"); size = WideCharToMultiByte(CP_ACP, 0, nptr, -1, NULL, 0, NULL, NULL); if (!size) { dwLastError = GetLastError(); ASSERT("WideCharToMultiByte failed. Error is %d\n", dwLastError); SetLastError(ERROR_INVALID_PARAMETER); res = 0; goto PAL__wcstoui64Exit; } s_nptr = (char *)PAL_malloc(size); if (!s_nptr) { ERROR("PAL_malloc failed\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); res = 0; goto PAL__wcstoui64Exit; } size = WideCharToMultiByte(CP_ACP, 0, nptr, -1, s_nptr, size, NULL, NULL); if (!size) { dwLastError = GetLastError(); ASSERT("WideCharToMultiByte failed. Error is %d\n", dwLastError); SetLastError(ERROR_INVALID_PARAMETER); res = 0; goto PAL__wcstoui64Exit; } res = strtoull(s_nptr, &s_endptr, base); /* only ASCII characters will be accepted by strtoull, and those always get mapped to single-byte characters, so the first rejected character will have the same index in the multibyte and widechar strings */ if( endptr ) { size = s_endptr - s_nptr; *endptr = (wchar_16 *)&nptr[size]; } PAL__wcstoui64Exit: PAL_free(s_nptr); LOGEXIT("_wcstoui64 returning unsigned long long %llu\n", res); PERF_EXIT(_wcstoui64); return res; }
/*++ Function: GetDiskFreeSpaceW See MSDN doc. --*/ PALIMPORT BOOL PALAPI GetDiskFreeSpaceW( LPCWSTR lpDirectoryName, LPDWORD lpSectorsPerCluster, LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters, /* Caller will ignore output value */ LPDWORD lpTotalNumberOfClusters) /* Caller will ignore output value */ { BOOL bRetVal = FALSE; pal_statfs fsInfoBuffer; INT statfsRetVal = 0; DWORD dwLastError = NO_ERROR; CHAR DirNameBuffer[ MAX_PATH ]; PERF_ENTRY(GetDiskFreeSpaceW); ENTRY( "GetDiskFreeSpaceW( lpDirectoryName=%p (%S), lpSectorsPerCluster=%p," "lpBytesPerSector=%p, lpNumberOfFreeClusters=%p, " "lpTotalNumberOfClusters=%p )\n", lpDirectoryName ? lpDirectoryName : W16_NULLSTRING, lpDirectoryName ? lpDirectoryName : W16_NULLSTRING, lpSectorsPerCluster, lpBytesPerSector, lpNumberOfFreeClusters, lpTotalNumberOfClusters ); /* Sanity checks. */ if ( !lpSectorsPerCluster ) { ERROR( "lpSectorsPerCluster cannot be NULL!\n" ); dwLastError = ERROR_INVALID_PARAMETER; goto exit; } if ( !lpBytesPerSector ) { ERROR( "lpBytesPerSector cannot be NULL!\n" ); dwLastError = ERROR_INVALID_PARAMETER; goto exit; } if ( lpNumberOfFreeClusters || lpTotalNumberOfClusters ) { TRACE("GetDiskFreeSpaceW is ignoring lpNumberOfFreeClusters" " and lpTotalNumberOfClusters\n" ); } if ( lpDirectoryName && PAL_wcslen( lpDirectoryName ) == 0 ) { ERROR( "lpDirectoryName is empty.\n" ); dwLastError = ERROR_INVALID_PARAMETER; goto exit; } /* Fusion uses this API to round file sizes up to their actual size on-disk based on the BytesPerSector * SectorsPerCluster. The intent is to avoid computing the sum of all file sizes in the cache just in bytes and not account for the cluster-sized slop, when determining if the cache is too large or not. */ if ( lpDirectoryName ) { if ( WideCharToMultiByte( CP_ACP, 0, lpDirectoryName, -1, DirNameBuffer,MAX_PATH, 0, 0 ) != 0 ) { FILEDosToUnixPathA( DirNameBuffer ); statfsRetVal = statfs( DirNameBuffer, &fsInfoBuffer ); } else { ASSERT( "Unable to convert the lpDirectoryName to multibyte.\n" ); dwLastError = ERROR_INTERNAL_ERROR; goto exit; } } else { statfsRetVal = statfs( "/", &fsInfoBuffer ); } if ( statfsRetVal == 0 ) { *lpBytesPerSector = fsInfoBuffer.f_bsize; *lpSectorsPerCluster = 1; bRetVal = TRUE; } else { if ( errno == ENOTDIR || errno == ENOENT ) { FILEGetProperNotFoundError( DirNameBuffer, &dwLastError ); goto exit; } dwLastError = FILEGetLastErrorFromErrno(); if ( ERROR_INTERNAL_ERROR == dwLastError ) { ASSERT("statfs() not expected to fail with errno:%d (%s)\n", errno, strerror(errno)); } else { TRACE("statfs() failed, errno:%d (%s)\n", errno, strerror(errno)); } } exit: if ( NO_ERROR != dwLastError ) { SetLastError( dwLastError ); } LOGEXIT( "GetDiskFreeSpace returning %s.\n", bRetVal == TRUE ? "TRUE" : "FALSE" ); PERF_EXIT(GetDiskFreeSpaceW); return bRetVal; }
/*++ Function : PAL_GetPALDirectoryW Returns the fully qualified path name where the PALL DLL was loaded from. On failure it returns FALSE and sets the proper LastError code. See rotor_pal.doc for more details. --*/ BOOL PALAPI PAL_GetPALDirectoryW( OUT LPWSTR lpDirectoryName, IN UINT cchDirectoryName ) { LPWSTR lpFullPathAndName = NULL; LPWSTR lpEndPoint = NULL; BOOL bRet = FALSE; PERF_ENTRY(PAL_GetPALDirectoryW); ENTRY( "PAL_GetPALDirectoryW( %p, %d )\n", lpDirectoryName, cchDirectoryName ); MODSTRUCT *module = LOADGetPalLibrary(); if (!module) { SetLastError(ERROR_INTERNAL_ERROR); goto EXIT; } lpFullPathAndName = module->lib_name; if (lpFullPathAndName == NULL) { SetLastError(ERROR_INTERNAL_ERROR); goto EXIT; } lpEndPoint = PAL_wcsrchr( lpFullPathAndName, '/' ); if ( lpEndPoint ) { /* The path that we return is required to have the trailing slash on the end.*/ lpEndPoint++; } if ( lpFullPathAndName && lpEndPoint && *lpEndPoint != '\0' ) { while ( cchDirectoryName - 1 && lpFullPathAndName != lpEndPoint ) { *lpDirectoryName = *lpFullPathAndName; lpFullPathAndName++; lpDirectoryName++; cchDirectoryName--; } if ( lpFullPathAndName == lpEndPoint ) { *lpDirectoryName = '\0'; bRet = TRUE; goto EXIT; } else { ASSERT( "The buffer was not large enough.\n" ); SetLastError( ERROR_INSUFFICIENT_BUFFER ); goto EXIT; } } else { ASSERT( "Unable to determine the path.\n" ); } /* Error path, should not be executed. */ SetLastError( ERROR_INTERNAL_ERROR ); EXIT: LOGEXIT( "PAL_GetPALDirectoryW returns BOOL %d.\n", bRet); PERF_EXIT(PAL_GetPALDirectoryW); return bRet; }
/*++ Function: FormatMessageW See MSDN doc. --*/ DWORD PALAPI FormatMessageW( IN DWORD dwFlags, IN LPCVOID lpSource, IN DWORD dwMessageId, IN DWORD dwLanguageId, OUT LPWSTR lpBuffer, IN DWORD nSize, IN va_list *Arguments) { BOOL bIgnoreInserts = FALSE; BOOL bIsVaList = TRUE; BOOL bIsLocalAlloced = FALSE; LPWSTR lpSourceString = NULL; UINT nCount = 0; LPWSTR lpReturnString = NULL; LPWSTR lpWorkingString = NULL; PERF_ENTRY(FormatMessageW); ENTRY( "FormatMessageW(dwFlags=%#x, lpSource=%p, dwMessageId=%#x, " "dwLanguageId=%#x, lpBuffer=%p, nSize=%u, va_list=%p)\n", dwFlags, lpSource, dwMessageId, dwLanguageId, lpBuffer, nSize, Arguments); /* Sanity checks. */ if ( dwFlags & FORMAT_MESSAGE_FROM_STRING && !lpSource ) { /* This behavior is different then in Windows. Windows would just crash.*/ ERROR( "lpSource cannot be NULL.\n" ); SetLastError( ERROR_INVALID_PARAMETER ); goto exit; } if ( !(dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER ) && !lpBuffer ) { /* This behavior is different then in Windows. Windows would just crash.*/ ERROR( "lpBuffer cannot be NULL, if " " FORMAT_MESSAGE_ALLOCATE_BUFFER is not specified.\n" ); SetLastError( ERROR_INVALID_PARAMETER ); goto exit; } if ( ( dwFlags & FORMAT_MESSAGE_FROM_STRING ) && ( dwFlags & FORMAT_MESSAGE_FROM_SYSTEM ) ) { ERROR( "These flags cannot co-exist. You can either " "specify FORMAT_MESSAGE_FROM_STRING, or " "FORMAT_MESSAGE_FROM_SYSTEM.\n" ); SetLastError( ERROR_INVALID_PARAMETER ); goto exit; } if ( !( dwFlags & FORMAT_MESSAGE_FROM_STRING ) && ( dwLanguageId != 0 #if ENABLE_DOWNLEVEL_FOR_NLS && dwLanguageId != MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ) #endif ) ) { ERROR( "Invalid language indentifier.\n" ); SetLastError( ERROR_RESOURCE_LANG_NOT_FOUND ); goto exit; } /* Parameter processing. */ if ( dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER ) { TRACE( "Allocated %d TCHARs. Don't forget to call LocalFree to " "free the memory when done.\n", nSize ); bIsLocalAlloced = TRUE; } if ( dwFlags & FORMAT_MESSAGE_IGNORE_INSERTS ) { bIgnoreInserts = TRUE; } if ( dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY ) { if ( !Arguments && !bIgnoreInserts ) { ERROR( "The va_list cannot be NULL.\n" ); SetLastError( ERROR_INVALID_PARAMETER ); goto exit; } else { bIsVaList = FALSE; } } if ( dwFlags & FORMAT_MESSAGE_FROM_STRING ) { lpSourceString = (LPWSTR)lpSource; } else if ( dwFlags & FORMAT_MESSAGE_FROM_SYSTEM ) { if ((dwMessageId & 0xFFFF0000) == 0x80070000) { // This message has been produced by HRESULT_FROM_WIN32. Undo its work. dwMessageId &= 0xFFFF; } lpWorkingString = lpReturnString = FMTMSG_GetMessageString( dwMessageId ); if ( !lpWorkingString ) { ERROR( "Unable to find the message %d.\n", dwMessageId ); SetLastError( ERROR_INTERNAL_ERROR ); nCount = 0; goto exit; } nCount = PAL_wcslen( lpWorkingString ); if ( !bIsLocalAlloced && nCount > nSize ) { ERROR( "Insufficient buffer.\n" ); SetLastError( ERROR_INSUFFICIENT_BUFFER ); lpWorkingString = NULL; nCount = 0; goto exit; } if ( !lpWorkingString ) { ERROR( "Invalid error indentifier.\n" ); SetLastError( ERROR_INVALID_ADDRESS ); } goto exit; } else { ERROR( "Unknown flag.\n" ); SetLastError( ERROR_INVALID_PARAMETER ); goto exit; } if ( nSize == 0 && bIsLocalAlloced ) { nSize = 1; } lpWorkingString = static_cast<WCHAR *>( LocalAlloc( LMEM_FIXED, nSize * sizeof( WCHAR ) ) ); if ( !lpWorkingString ) { ERROR( "Unable to allocate memory for the working string.\n" ); SetLastError( ERROR_INSUFFICIENT_BUFFER ); goto exit; } /* Process the string. */ lpReturnString = lpWorkingString; while ( *lpSourceString ) { if ( *lpSourceString == '%' && !bIgnoreInserts ) { lpSourceString++; /* Escape sequences. */ if ( *lpSourceString == '0' ) { /* Terminates a message without a newline character. */ *lpWorkingString = '\0'; goto exit; } else if ( PAL_iswdigit( *lpSourceString ) ) { /* Get the insert number. */ WCHAR Number[] = { '\0', '\0', '\0' }; SIZE_T Index = 0; Number[ 0 ] = *lpSourceString; lpSourceString++; if ( PAL_iswdigit( *lpSourceString ) ) { Number[ 1 ] = *lpSourceString; lpSourceString++; if ( PAL_iswdigit( *lpSourceString ) ) { ERROR( "Invalid insert indentifier.\n" ); SetLastError( ERROR_INVALID_PARAMETER ); lpWorkingString = NULL; nCount = 0; goto exit; } } Index = FMTMSG__watoi( Number ); if ( Index == 0 ) { ERROR( "Invalid insert indentifier.\n" ); SetLastError( ERROR_INVALID_PARAMETER ); lpWorkingString = NULL; nCount = 0; goto exit; } if ( *lpSourceString == '!' ) { LPWSTR lpInsertString = NULL; LPWSTR lpPrintfString = NULL; LPWSTR lpStartOfFormattedString = NULL; UINT nPrintfLength = 0; LPWSTR lpFormattedString = NULL; UINT nFormattedLength = 0; if ( !bIsVaList ) { lpInsertString = ((LPWSTR*)Arguments)[ Index - 1 ]; } else { va_list TheArgs; va_copy(TheArgs, *Arguments); UINT i = 0; for ( ; i < Index; i++ ) { lpInsertString = va_arg( TheArgs, LPWSTR ); } } /* Calculate the length, and extract the printf string.*/ lpSourceString++; { LPWSTR p = PAL_wcschr( lpSourceString, '!' ); if ( NULL == p ) { nPrintfLength = 0; } else { nPrintfLength = p - lpSourceString; } } lpPrintfString = (LPWSTR)PAL_malloc( ( nPrintfLength + 1 ) * sizeof( WCHAR ) ); if ( !lpPrintfString ) { ERROR( "Unable to allocate memory.\n" ); SetLastError( ERROR_NOT_ENOUGH_MEMORY ); lpWorkingString = NULL; nCount = 0; goto exit; } PAL_wcsncpy( lpPrintfString, lpSourceString, nPrintfLength ); *( lpPrintfString + nPrintfLength ) = '\0'; lpStartOfFormattedString = lpFormattedString = FMTMSG_ProcessPrintf( *lpPrintfString, lpPrintfString, lpInsertString); if ( !lpFormattedString ) { ERROR( "Unable to process the format string.\n" ); /* Function will set the error code. */ PAL_free( lpPrintfString ); lpWorkingString = NULL; goto exit; } nFormattedLength = PAL_wcslen( lpFormattedString ); /* Append the processed printf string into the working string */ while ( *lpFormattedString ) { _CHECKED_ADD_TO_STRING( *lpFormattedString ); lpFormattedString++; } lpSourceString += nPrintfLength + 1; PAL_free( lpPrintfString ); PAL_free( lpStartOfFormattedString ); lpPrintfString = lpFormattedString = NULL; } else { /* The printf format string defaults to 's'.*/ LPWSTR lpInsert = NULL; if ( !bIsVaList ) { lpInsert = ((LPWSTR*)Arguments)[Index - 1]; } else { va_list TheArgs; va_copy(TheArgs, *Arguments); UINT i = 0; for ( ; i < Index; i++ ) { lpInsert = va_arg( TheArgs, LPWSTR ); } } while ( *lpInsert ) { _CHECKED_ADD_TO_STRING( *lpInsert ); lpInsert++; } } } /* Format specifiers. */ else if ( *lpSourceString == '%' ) { _CHECKED_ADD_TO_STRING( '%' ); lpSourceString++; } else if ( *lpSourceString == 'n' ) { /* Hard line break. */ _CHECKED_ADD_TO_STRING( '\n' ); lpSourceString++; } else if ( *lpSourceString == '.' ) { _CHECKED_ADD_TO_STRING( '.' ); lpSourceString++; } else if ( *lpSourceString == '!' ) { _CHECKED_ADD_TO_STRING( '!' ); lpSourceString++; } else if ( !*lpSourceString ) { ERROR( "Invalid parameter.\n" ); SetLastError( ERROR_INVALID_PARAMETER ); lpWorkingString = NULL; nCount = 0; goto exit; } else /* Append the character. */ { _CHECKED_ADD_TO_STRING( *lpSourceString ); lpSourceString++; } }/* END if ( *lpSourceString == '%' ) */ else { /* In Windows if FormatMessage is called with ignore inserts, then FormatMessage strips %1!s! down to %1, since string is the default. */ if ( bIgnoreInserts && *lpSourceString == '!' && *( lpSourceString + 1 ) == 's' ) { LPWSTR lpLastBang = PAL_wcschr( lpSourceString + 1, '!' ); if ( lpLastBang && ( 2 == lpLastBang - lpSourceString ) ) { lpSourceString = lpLastBang + 1; } else { ERROR( "Mal-formed string\n" ); SetLastError( ERROR_INVALID_PARAMETER ); lpWorkingString = NULL; nCount = 0; goto exit; } } else { /* Append to the string. */ _CHECKED_ADD_TO_STRING( *lpSourceString ); lpSourceString++; } } } /* Terminate the message. */ _CHECKED_ADD_TO_STRING( '\0' ); /* NULL does not count. */ nCount--; exit: /* Function clean-up and exit. */ if ( lpWorkingString ) { if ( bIsLocalAlloced ) { TRACE( "Assigning the buffer to the pointer.\n" ); // when FORMAT_MESSAGE_ALLOCATE_BUFFER is specified, nSize // does not specify the size of lpBuffer, rather it specifies // the minimum size of the string // as such we have to blindly assume that lpBuffer has enough space to // store PVOID // might cause a prefast warning, but there is no good way to suppress it yet _ASSERTE(dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER); *((LPVOID*)lpBuffer) = (LPVOID)lpReturnString; } else /* Only delete lpReturnString if the caller has their own buffer.*/ { TRACE( "Copying the string into the buffer.\n" ); PAL_wcsncpy( lpBuffer, lpReturnString, nCount + 1 ); LocalFree( lpReturnString ); } } else /* Error, something occurred. */ { if ( lpReturnString ) { LocalFree( lpReturnString ); } } LOGEXIT( "FormatMessageW returns %d.\n", nCount ); PERF_EXIT(FormatMessageW); return nCount; }
/*++ Function: pow See MSDN. --*/ PALIMPORT double __cdecl PAL_pow(double x, double y) { double ret; PERF_ENTRY(pow); ENTRY("pow (x=%f, y=%f)\n", x, y); #if !HAVE_COMPATIBLE_POW if (y == 1.0 / 0.0 && !isnan(x)) // +Inf { if (x == 1.0 || x == -1.0) { ret = 0.0 / 0.0; // NaN } else if (x > -1.0 && x < 1.0) { ret = 0.0; } else { ret = 1.0 / 0.0; // +Inf } } else if (y == -1.0 / 0.0 && !isnan(x)) // -Inf { if (x == 1.0 || x == -1.0) { ret = 0.0 / 0.0; // NaN } else if (x > -1.0 && x < 1.0) { ret = 1.0 / 0.0; // +Inf } else { ret = 0.0; } } else if (x == 0.0 && y < 0.0) { ret = 1.0 / 0.0; // +Inf } else #endif // !HAVE_COMPATIBLE_POW if (y == 0.0 && isnan(x)) { // Windows returns NaN for pow(NaN, 0), but POSIX specifies // a return value of 1 for that case. We need to return // the same result as Windows. ret = 0.0 / 0.0; // NaN } else { ret = pow(x, y); } #if !HAVE_VALID_NEGATIVE_INF_POW if (ret == 1.0 / 0.0 && x < 0 && finite(x) && ceil(y/2) != floor(y/2)) { ret = -1.0 / 0.0; // -Inf } #endif // !HAVE_VALID_NEGATIVE_INF_POW #if !HAVE_VALID_POSITIVE_INF_POW /* * The even/odd test in the if (this one and the one above) used to be ((long long) y % 2 == 0) * on SPARC (long long) y for large y (>2**63) is always 0x7fffffff7fffffff, which * is an odd number, so the test ((long long) y % 2 == 0) will always fail for * large y. Since large double numbers are always even (e.g., the representation of * 1E20+1 is the same as that of 1E20, the last “+1” is too insignificant to be part * of the representation), this test will always return the wrong result for large y. * * The (ceil(y/2) == floor(y/2)) test is slower, but more robust. */ if (ret == -1.0 / 0.0 && x < 0 && finite(x) && ceil(y/2) == floor(y/2)) { ret = 1.0 / 0.0; // +Inf } #endif // !HAVE_VALID_POSITIVE_INF_POW LOGEXIT("pow returns double %f\n", ret); PERF_EXIT(pow); return ret; }
/*++ Function: GetSystemInfo GetSystemInfo The GetSystemInfo function returns information about the current system. Parameters lpSystemInfo [out] Pointer to a SYSTEM_INFO structure that receives the information. Return Values This function does not return a value. Note: fields returned by this function are: dwNumberOfProcessors dwPageSize Others are set to zero. --*/ VOID PALAPI GetSystemInfo( OUT LPSYSTEM_INFO lpSystemInfo) { int nrcpus = 0; long pagesize; PERF_ENTRY(GetSystemInfo); ENTRY("GetSystemInfo (lpSystemInfo=%p)\n", lpSystemInfo); pagesize = getpagesize(); lpSystemInfo->wProcessorArchitecture_PAL_Undefined = 0; lpSystemInfo->wReserved_PAL_Undefined = 0; lpSystemInfo->dwPageSize = pagesize; lpSystemInfo->dwActiveProcessorMask_PAL_Undefined = 0; #if HAVE_SYSCONF #if defined(__hppa__) || ( defined (_IA64_) && defined (_HPUX_) ) struct pst_dynamic psd; if (pstat_getdynamic(&psd, sizeof(psd), (size_t)1, 0) != -1) { nrcpus = psd.psd_proc_cnt; } else { ASSERT("pstat_getdynamic failed (%d)\n", errno); } #else // !__hppa__ nrcpus = sysconf(_SC_NPROCESSORS_ONLN); if (nrcpus < 1) { ASSERT("sysconf failed for _SC_NPROCESSORS_ONLN (%d)\n", errno); } #endif // __hppa__ #elif HAVE_SYSCTL int rc; size_t sz; int mib[2]; sz = sizeof(nrcpus); mib[0] = CTL_HW; mib[1] = HW_NCPU; rc = sysctl(mib, 2, &nrcpus, &sz, NULL, 0); if (rc != 0) { ASSERT("sysctl failed for HW_NCPU (%d)\n", errno); } #endif // HAVE_SYSCONF TRACE("dwNumberOfProcessors=%d\n", nrcpus); lpSystemInfo->dwNumberOfProcessors = nrcpus; #ifdef VM_MAXUSER_ADDRESS lpSystemInfo->lpMaximumApplicationAddress = (PVOID) VM_MAXUSER_ADDRESS; #elif defined(__sun__) || defined(_AIX) || defined(__hppa__) || ( defined (_IA64_) && defined (_HPUX_) ) || defined(__LINUX__) lpSystemInfo->lpMaximumApplicationAddress = (PVOID) -1; #elif defined(USERLIMIT) lpSystemInfo->lpMaximumApplicationAddress = (PVOID) USERLIMIT; #elif defined(_WIN64) #if defined(USRSTACK64) lpSystemInfo->lpMaximumApplicationAddress = (PVOID) USRSTACK64; #else // !USRSTACK64 #error How come USRSTACK64 is not defined for 64bit? #endif // USRSTACK64 #elif defined(USRSTACK) lpSystemInfo->lpMaximumApplicationAddress = (PVOID) USRSTACK; #else #error The maximum application address is not known on this platform. #endif lpSystemInfo->lpMinimumApplicationAddress = (PVOID) pagesize; lpSystemInfo->dwProcessorType_PAL_Undefined = 0; lpSystemInfo->dwAllocationGranularity = pagesize; lpSystemInfo->wProcessorLevel_PAL_Undefined = 0; lpSystemInfo->wProcessorRevision_PAL_Undefined = 0; LOGEXIT("GetSystemInfo returns VOID\n"); PERF_EXIT(GetSystemInfo); }
/*++ Function: MessageBoxW This is a small subset of MessageBox that simply logs a message to the system logging facility and returns. A typical log entry will look like: May 23 15:48:10 rice example1: MessageBox: Caption: Error Text Note: hWnd should always be NULL. See MSDN doc. --*/ int PALAPI MessageBoxW( IN LPVOID hWnd, IN LPCWSTR lpText, IN LPCWSTR lpCaption, IN UINT uType) { CHAR *text = NULL; CHAR *caption = NULL; INT len = 0; INT rc = 0; PERF_ENTRY(MessageBoxW); ENTRY( "MessageBoxW (hWnd=%p, lpText=%p (%S), lpCaption=%p (%S), uType=%#x)\n", hWnd, lpText?lpText:W16_NULLSTRING, lpText?lpText:W16_NULLSTRING, lpCaption?lpCaption:W16_NULLSTRING, lpCaption?lpCaption:W16_NULLSTRING, uType ); if (hWnd != NULL) { ASSERT("hWnd != NULL"); } if(lpText) { len = WideCharToMultiByte(CP_ACP, 0, lpText, -1, NULL, 0, NULL, NULL); if(len) { text = (LPSTR)PAL_malloc(len); if(!text) { ERROR("malloc() failed!\n"); SetLastError( ERROR_NOT_ENOUGH_MEMORY ); goto error; } if( !WideCharToMultiByte( CP_ACP, 0, lpText, -1, text, len, NULL, NULL)) { ASSERT("WideCharToMultiByte failure\n"); SetLastError( ERROR_INTERNAL_ERROR ); goto error; } } else { ASSERT("WideCharToMultiByte failure\n"); SetLastError( ERROR_INTERNAL_ERROR ); goto error; } } else { WARN("No message text\n"); if (NULL == (text = PAL__strdup("(no message text)"))) { ASSERT("strdup() failed\n"); SetLastError( ERROR_INTERNAL_ERROR ); goto error; } } if (lpCaption) { len = WideCharToMultiByte( CP_ACP, 0, lpCaption, -1, NULL, 0, NULL, NULL); if(len) { caption = (CHAR*)PAL_malloc(len); if(!caption) { ERROR("malloc() failed!\n"); SetLastError( ERROR_NOT_ENOUGH_MEMORY ); goto error; } if( !WideCharToMultiByte( CP_ACP, 0, lpCaption, -1, caption, len, NULL, NULL)) { ASSERT("WideCharToMultiByte failure\n"); SetLastError( ERROR_INTERNAL_ERROR ); goto error; } } else { ASSERT("WideCharToMultiByte failure\n"); SetLastError( ERROR_INTERNAL_ERROR ); goto error; } } else { if (NULL == (caption = PAL__strdup("Error"))) { ERROR("strdup() failed\n"); SetLastError( ERROR_NOT_ENOUGH_MEMORY ); goto error; } } rc = MessageBoxA(hWnd, text, caption, uType); error: PAL_free(caption); PAL_free(text); LOGEXIT("MessageBoxW returns %d\n", rc); PERF_EXIT(MessageBoxW); return rc; }
/*++ Function: GlobalMemoryStatusEx GlobalMemoryStatusEx Retrieves information about the system's current usage of both physical and virtual memory. Return Values This function returns a BOOL to indicate its success status. --*/ BOOL PALAPI GlobalMemoryStatusEx( IN OUT LPMEMORYSTATUSEX lpBuffer) { PERF_ENTRY(GlobalMemoryStatusEx); ENTRY("GlobalMemoryStatusEx (lpBuffer=%p)\n", lpBuffer); lpBuffer->dwMemoryLoad = 0; lpBuffer->ullTotalPhys = 0; lpBuffer->ullAvailPhys = 0; lpBuffer->ullTotalPageFile = 0; lpBuffer->ullAvailPageFile = 0; lpBuffer->ullTotalVirtual = 0; lpBuffer->ullAvailVirtual = 0; lpBuffer->ullAvailExtendedVirtual = 0; BOOL fRetVal = FALSE; // Get the physical memory size #if HAVE_SYSCONF && HAVE__SC_PHYS_PAGES int64_t physical_memory; // Get the Physical memory size physical_memory = sysconf( _SC_PHYS_PAGES ) * sysconf( _SC_PAGE_SIZE ); lpBuffer->ullTotalPhys = (DWORDLONG)physical_memory; fRetVal = TRUE; #elif HAVE_SYSCTL int mib[2]; int64_t physical_memory; size_t length; // Get the Physical memory size mib[0] = CTL_HW; mib[1] = HW_MEMSIZE; length = sizeof(INT64); int rc = sysctl(mib, 2, &physical_memory, &length, NULL, 0); if (rc != 0) { ASSERT("sysctl failed for HW_MEMSIZE (%d)\n", errno); } else { lpBuffer->ullTotalPhys = (DWORDLONG)physical_memory; fRetVal = TRUE; } #elif // HAVE_SYSINFO // TODO: implement getting memory details via sysinfo. On Linux, it provides swap file details that // we can use to fill in the xxxPageFile members. #endif // HAVE_SYSCONF // Get the physical memory in use - from it, we can get the physical memory available. // We do this only when we have the total physical memory available. if (lpBuffer->ullTotalPhys > 0) { #ifndef __APPLE__ lpBuffer->ullAvailPhys = sysconf(SYSCONF_PAGES) * sysconf(_SC_PAGE_SIZE); INT64 used_memory = lpBuffer->ullTotalPhys - lpBuffer->ullAvailPhys; lpBuffer->dwMemoryLoad = (DWORD)((used_memory * 100) / lpBuffer->ullTotalPhys); #else vm_size_t page_size; mach_port_t mach_port; mach_msg_type_number_t count; vm_statistics_data_t vm_stats; mach_port = mach_host_self(); count = sizeof(vm_stats) / sizeof(natural_t); if (KERN_SUCCESS == host_page_size(mach_port, &page_size)) { if (KERN_SUCCESS == host_statistics(mach_port, HOST_VM_INFO, (host_info_t)&vm_stats, &count)) { lpBuffer->ullAvailPhys = (int64_t)vm_stats.free_count * (int64_t)page_size; INT64 used_memory = ((INT64)vm_stats.active_count + (INT64)vm_stats.inactive_count + (INT64)vm_stats.wire_count) * (INT64)page_size; lpBuffer->dwMemoryLoad = (DWORD)((used_memory * 100) / lpBuffer->ullTotalPhys); } } #endif // __APPLE__ } // There is no API to get the total virtual address space size on // Unix, so we use a constant value representing 128TB, which is // the approximate size of total user virtual address space on // the currently supported Unix systems. static const UINT64 _128TB = (1ull << 47); lpBuffer->ullTotalVirtual = _128TB; lpBuffer->ullAvailVirtual = lpBuffer->ullAvailPhys; LOGEXIT("GlobalMemoryStatusEx returns %d\n", fRetVal); PERF_EXIT(GlobalMemoryStatusEx); return fRetVal; }
/*++ Function: _makepath See MSDN doc. --*/ void __cdecl _makepath( char *path, const char *drive, const char *dir, const char *fname, const char *ext) { UINT Length = 0; PERF_ENTRY(_makepath); ENTRY( "_makepath (path=%p, drive=%p (%s), dir=%p (%s), fname=%p (%s), ext=%p (%s))\n", path, drive ? drive:"NULL", drive ? drive:"NULL", dir ? dir:"NULL", dir ? dir:"NULL", fname ? fname:"NULL", fname ? fname:"NULL", ext ? ext:"NULL", ext ? ext:"NULL"); path[ 0 ] = '\0'; /* According to the pal documentation, host operating systems that don't support drive letters, the "drive" parameter must always be null. */ if ( drive != NULL && drive[0] != '\0' ) { ASSERT( "The drive parameter must always be NULL on systems that don't" "support drive letters. drive is being ignored!.\n" ); } if ( dir != NULL && dir[ 0 ] != '\0' ) { UINT DirLength = strlen( dir ); Length += DirLength ; if ( Length < _MAX_PATH ) { strncat( path, dir, DirLength ); if ( dir[ DirLength - 1 ] != '/' && dir[ DirLength - 1 ] != '\\' ) { if ( Length + 1 < _MAX_PATH ) { path[ Length ] = '/'; Length++; path[ Length ] = '\0'; } else { goto Max_Path_Error; } } } else { goto Max_Path_Error; } } if ( fname != NULL && fname[ 0 ] != '\0' ) { UINT fNameLength = strlen( fname ); Length += fNameLength; if ( Length < _MAX_PATH ) { strncat( path, fname, fNameLength ); } else { goto Max_Path_Error; } } if ( ext != NULL && ext[ 0 ] != '\0' ) { UINT ExtLength = strlen( ext ); Length += ExtLength; if ( ext[ 0 ] != '.' ) { /* Add a '.' */ if ( Length + 1 < _MAX_PATH ) { path[ Length - ExtLength ] = '.'; Length++; path[ Length - ExtLength ] = '\0'; strncat( path, ext, ExtLength ); } else { goto Max_Path_Error; } } else { /* Already has a '.' */ if ( Length < _MAX_PATH ) { strncat( path, ext, ExtLength ); } else { goto Max_Path_Error; } } } FILEDosToUnixPathA( path ); LOGEXIT( "_makepath returning void.\n" ); PERF_EXIT(_makepath); return; Max_Path_Error: ERROR( "path cannot be greater then _MAX_PATH\n" ); path[ 0 ] = '\0'; LOGEXIT( "_makepath returning void \n" ); PERF_EXIT(_makepath); return; }
/*++ Function : wcstod There is a slight difference between the Windows version of wcstod and the BSD versio of wcstod. Under Windows the string " -1b " returns -1.000000 stop char = 'b' Under BSD the same string returns 0.000000 stop ' ' see msdn doc. --*/ double __cdecl PAL_wcstod( const wchar_16 * nptr, wchar_16 **endptr ) { double RetVal = 0.0; LPSTR lpStringRep = NULL; LPWSTR lpStartOfExpression = (LPWSTR)nptr; LPWSTR lpEndOfExpression = NULL; UINT Length = 0; PERF_ENTRY(wcstod); ENTRY( "wcstod( %p (%S), %p (%S) )\n", nptr, nptr, endptr , endptr ); THREADMarkDiagnostic("PAL_wcstod -> strtod"); if ( !nptr ) { ERROR( "nptr is invalid.\n" ); LOGEXIT( "wcstod returning 0.0\n" ); PERF_EXIT(wcstod); return 0.0; } /* Eat white space. */ while ( PAL_iswspace( *lpStartOfExpression ) ) { lpStartOfExpression++; } /* Get the end of the expression. */ lpEndOfExpression = lpStartOfExpression; while ( *lpEndOfExpression ) { if ( !MISC_CRT_WCSTOD_IsValidCharacter( *lpEndOfExpression ) ) { break; } lpEndOfExpression++; } if ( lpEndOfExpression != lpStartOfExpression ) { Length = lpEndOfExpression - lpStartOfExpression; lpStringRep = (LPSTR)PAL_malloc( Length + 1); if ( lpStringRep ) { if ( WideCharToMultiByte( CP_ACP, 0, lpStartOfExpression, Length, lpStringRep, Length + 1 , NULL, 0 ) != 0 ) { LPSTR ScanStop = NULL; lpStringRep[Length]= 0; RetVal = strtod( lpStringRep, &ScanStop ); /* See if strtod failed. */ if ( RetVal == 0.0 && ScanStop == lpStringRep ) { ASSERT( "An error occured in the conversion.\n" ); lpEndOfExpression = (LPWSTR)nptr; } } else { ASSERT( "Wide char to multibyte conversion failed.\n" ); lpEndOfExpression = (LPWSTR)nptr; } } else { ERROR( "Not enough memory.\n" ); lpEndOfExpression = (LPWSTR)nptr; } } else { ERROR( "Malformed expression.\n" ); lpEndOfExpression = (LPWSTR)nptr; } /* Set the stop scan character. */ if ( endptr != NULL ) { *endptr = lpEndOfExpression; } PAL_free( lpStringRep ); LOGEXIT( "wcstod returning %f.\n", RetVal ); PERF_EXIT(wcstod); return RetVal; }
__cdecl _fullpath( char *absPath, const char *relPath, size_t maxLength) { char realpath_buf[PATH_MAX+1]; char path_copy[PATH_MAX+1]; char *retval = NULL; DWORD cPathCopy = sizeof(path_copy)/sizeof(path_copy[0]); size_t min_length; BOOL fBufAllocated = FALSE; PERF_ENTRY(_fullpath); ENTRY("_fullpath (absPath=%p, relPath=%p (%s), maxLength = %lu)\n", absPath, relPath ? relPath:"NULL", relPath ? relPath:"NULL", maxLength); if (strncpy_s(path_copy, sizeof(path_copy), relPath ? relPath : ".", cPathCopy) != SAFECRT_SUCCESS) { TRACE("_fullpath: strncpy_s failed!\n"); goto fullpathExit; } FILEDosToUnixPathA(path_copy); if(NULL == realpath(path_copy, realpath_buf)) { ERROR("realpath() failed; problem path is '%s'. errno is %d (%s)\n", realpath_buf, errno, strerror(errno)); goto fullpathExit; } TRACE("real path is %s\n", realpath_buf); min_length = strlen(realpath_buf)+1; // +1 for the NULL terminator if(NULL == absPath) { absPath = static_cast<char *>( PAL_malloc(_MAX_PATH * sizeof(char))); if (!absPath) { ERROR("PAL_malloc failed with error %d\n", errno); goto fullpathExit; } maxLength = _MAX_PATH; fBufAllocated = TRUE; } if(min_length > maxLength) { ERROR("maxLength is %lu, we need at least %lu\n", maxLength, min_length); if (fBufAllocated) { PAL_free(absPath); fBufAllocated = FALSE; } goto fullpathExit; } strcpy_s(absPath, maxLength, realpath_buf); retval = absPath; fullpathExit: LOGEXIT("_fullpath returns char * %p\n", retval); PERF_EXIT(_fullpath); return retval; }
/*++ Function: GetFullPathNameA See MSDN doc. --*/ DWORD PALAPI GetFullPathNameA( IN LPCSTR lpFileName, IN DWORD nBufferLength, OUT LPSTR lpBuffer, OUT LPSTR *lpFilePart) { DWORD nReqPathLen, nRet = 0; LPSTR lpUnixPath = NULL; BOOL fullPath = FALSE; PERF_ENTRY(GetFullPathNameA); ENTRY("GetFullPathNameA(lpFileName=%p (%s), nBufferLength=%u, lpBuffer=%p, " "lpFilePart=%p)\n", lpFileName?lpFileName:"NULL", lpFileName?lpFileName:"NULL", nBufferLength, lpBuffer, lpFilePart); if(NULL == lpFileName) { WARN("lpFileName is NULL\n"); SetLastError(ERROR_INVALID_PARAMETER); goto done; } /* find out if lpFileName is a partial or full path */ if ('\\' == *lpFileName || '/' == *lpFileName) { fullPath = TRUE; } if(fullPath) { lpUnixPath = PAL__strdup( lpFileName ); if(NULL == lpUnixPath) { ERROR("strdup() failed; error is %d (%s)\n", errno, strerror(errno)); SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto done; } } else { size_t max_len; /* allocate memory for full non-canonical path */ max_len = strlen(lpFileName)+1; /* 1 for the slash to append */ max_len += MAX_LONGPATH + 1; lpUnixPath = (LPSTR)PAL_malloc(max_len); if(NULL == lpUnixPath) { ERROR("PAL_malloc() failed; error is %d (%s)\n", errno, strerror(errno)); SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto done; } /* build full path */ if(!GetCurrentDirectoryA(MAX_LONGPATH + 1, lpUnixPath)) { /* no reason for this to fail now... */ ASSERT("GetCurrentDirectoryA() failed! lasterror is %#xd\n", GetLastError()); SetLastError(ERROR_INTERNAL_ERROR); goto done; } if (strcat_s(lpUnixPath, max_len, "/") != SAFECRT_SUCCESS) { ERROR("strcat_s failed!\n"); SetLastError(ERROR_FILENAME_EXCED_RANGE); goto done; } if (strcat_s(lpUnixPath, max_len, lpFileName) != SAFECRT_SUCCESS) { ERROR("strcat_s failed!\n"); SetLastError(ERROR_FILENAME_EXCED_RANGE); goto done; } } /* do conversion to Unix path */ FILEDosToUnixPathA( lpUnixPath ); /* now we can canonicalize this */ FILECanonicalizePath(lpUnixPath); /* at last, we can figure out how long this path is */ nReqPathLen = strlen(lpUnixPath)+1; if(nBufferLength < nReqPathLen) { TRACE("reporting insufficient buffer : minimum is %d, caller " "provided %d\n", nReqPathLen, nBufferLength); nRet = nReqPathLen; goto done; } nRet = nReqPathLen-1; strcpy_s(lpBuffer, nBufferLength, lpUnixPath); /* locate the filename component if caller cares */ if(lpFilePart) { *lpFilePart = strrchr(lpBuffer, '/'); if (*lpFilePart == NULL) { ASSERT("Not able to find '/' in the full path.\n"); SetLastError( ERROR_INTERNAL_ERROR ); nRet = 0; goto done; } else { (*lpFilePart)++; } } done: PAL_free (lpUnixPath); LOGEXIT("GetFullPathNameA returns DWORD %u\n", nRet); PERF_EXIT(GetFullPathNameA); return nRet; }