static gint32 string_invariant_compare (MonoString *str1, gint32 off1, gint32 len1, MonoString *str2, gint32 off2, gint32 len2, gint32 options) { /* c translation of C# code from old string.cs.. :) */ gint32 length; gint32 charcmp; gunichar2 *ustr1; gunichar2 *ustr2; gint32 pos; if(len1 >= len2) { length=len1; } else { length=len2; } ustr1 = mono_string_chars(str1)+off1; ustr2 = mono_string_chars(str2)+off2; pos = 0; for (pos = 0; pos != length; pos++) { if (pos >= len1 || pos >= len2) break; charcmp = string_invariant_compare_char(ustr1[pos], ustr2[pos], options); if (charcmp != 0) { return(charcmp); } } /* the lesser wins, so if we have looped until length we just * need to check the last char */ if (pos == length) { return(string_invariant_compare_char(ustr1[pos - 1], ustr2[pos - 1], options)); } /* Test if one of the strings has been compared to the end */ if (pos >= len1) { if (pos >= len2) { return(0); } else { return(-1); } } else if (pos >= len2) { return(1); } /* if not, check our last char only.. (can this happen?) */ return(string_invariant_compare_char(ustr1[pos], ustr2[pos], options)); }
gpointer ves_icall_System_Threading_Semaphore_OpenSemaphore_internal (MonoString *name, gint32 rights, gint32 *error) { gpointer handle; gchar *utf8_name; *error = ERROR_SUCCESS; /* w32 seems to guarantee that opening named objects can't race each other */ mono_w32handle_namespace_lock (); utf8_name = g_utf16_to_utf8 (mono_string_chars (name), -1, NULL, NULL, NULL); mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening named sem [%s]", __func__, utf8_name); handle = mono_w32handle_namespace_search_handle (MONO_W32HANDLE_NAMEDSEM, utf8_name); if (handle == INVALID_HANDLE_VALUE) { /* The name has already been used for a different object. */ *error = ERROR_INVALID_HANDLE; goto cleanup; } else if (!handle) { /* This name doesn't exist */ *error = ERROR_FILE_NOT_FOUND; goto cleanup; } mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning named sem handle %p", __func__, handle); cleanup: g_free (utf8_name); mono_w32handle_namespace_unlock (); return handle; }
static gint32 string_invariant_indexof_char (MonoString *source, gint32 sindex, gint32 count, gunichar2 value, MonoBoolean first) { gint32 pos; gunichar2 *src; src = mono_string_chars(source); if(first) { for (pos = sindex; pos != count + sindex; pos++) { if (src [pos] == value) { return(pos); } } return(-1); } else { for (pos = sindex; pos > sindex - count; pos--) { if (src [pos] == value) return(pos); } return(-1); } }
gboolean mono_process_get_shell_arguments (MonoProcessStartInfo *proc_start_info, gunichar2 **shell_path, MonoString **cmd) { gchar *spath = NULL; gchar *new_cmd, *cmd_utf8; MonoError mono_error; *shell_path = NULL; *cmd = proc_start_info->arguments; mono_process_complete_path (mono_string_chars (proc_start_info->filename), &spath); if (spath != NULL) { /* Seems like our CreateProcess does not work as the windows one. * This hack is needed to deal with paths containing spaces */ if (*cmd) { cmd_utf8 = mono_string_to_utf8_checked (*cmd, &mono_error); if (!mono_error_set_pending_exception (&mono_error)) { new_cmd = g_strdup_printf ("%s %s", spath, cmd_utf8); *cmd = mono_string_new_wrapper (new_cmd); g_free (cmd_utf8); g_free (new_cmd); } else { *cmd = NULL; } } else { *cmd = mono_string_new_wrapper (spath); } g_free (spath); } return (*cmd != NULL) ? TRUE : FALSE; }
gpointer ves_icall_System_Threading_Semaphore_CreateSemaphore_internal (gint32 initialCount, gint32 maximumCount, MonoString *name, gint32 *error) { gpointer sem; if (maximumCount <= 0) { mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: maximumCount <= 0", __func__); *error = ERROR_INVALID_PARAMETER; return NULL; } if (initialCount > maximumCount || initialCount < 0) { mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: initialCount > maximumCount or < 0", __func__); *error = ERROR_INVALID_PARAMETER; return NULL; } /* Need to blow away any old errors here, because code tests * for ERROR_ALREADY_EXISTS on success (!) to see if a * semaphore was freshly created */ SetLastError (ERROR_SUCCESS); if (!name) sem = sem_create (initialCount, maximumCount); else sem = namedsem_create (initialCount, maximumCount, mono_string_chars (name)); *error = GetLastError (); return sem; }
gunichar2* mono_string_handle_pin_chars (MonoStringHandle handle, uint32_t *gchandle) { g_assert (gchandle != NULL); *gchandle = mono_gchandle_from_handle (MONO_HANDLE_CAST (MonoObject, handle), TRUE); MonoString *raw = MONO_HANDLE_RAW (handle); return mono_string_chars (raw); }
gpointer ves_icall_System_Security_Principal_WindowsIdentity_GetUserToken (MonoString *username) { #ifdef HOST_WIN32 gpointer token = NULL; MONO_ARCH_SAVE_REGS; /* TODO: MS has something like this working in Windows 2003 (client and * server) but works only for domain accounts (so it's quite limiting). * http://www.develop.com/kbrown/book/html/howto_logonuser.html */ g_warning ("Unsupported on Win32 (anyway requires W2K3 minimum)"); #else /* HOST_WIN32*/ #ifdef HAVE_GETPWNAM_R struct passwd pwd; size_t fbufsize; gchar *fbuf; gint32 retval; #endif gpointer token = (gpointer) -2; struct passwd *p; gchar *utf8_name; gboolean result; MONO_ARCH_SAVE_REGS; utf8_name = mono_unicode_to_external (mono_string_chars (username)); #ifdef HAVE_GETPWNAM_R #ifdef _SC_GETPW_R_SIZE_MAX fbufsize = mono_sysconf (_SC_GETPW_R_SIZE_MAX); #else fbufsize = MONO_SYSCONF_DEFAULT_SIZE; #endif fbuf = g_malloc0 (fbufsize); retval = getpwnam_r (utf8_name, &pwd, fbuf, fbufsize, &p); result = ((retval == 0) && (p == &pwd)); #else /* default to non thread-safe but posix compliant function */ p = getpwnam (utf8_name); result = (p != NULL); #endif if (result) { token = GINT_TO_POINTER (p->pw_uid); } #ifdef HAVE_GETPWNAM_R g_free (fbuf); #endif g_free (utf8_name); #endif return token; }
gpointer ves_icall_System_Threading_Semaphore_OpenSemaphore_internal (MonoString *name, gint32 rights, gint32 *error) { HANDLE sem; sem = OpenSemaphore (rights, FALSE, mono_string_chars (name)); *error = GetLastError (); return sem; }
gpointer ves_icall_System_Threading_Semaphore_CreateSemaphore_internal (gint32 initialCount, gint32 maximumCount, MonoString *name, gint32 *error) { HANDLE sem; sem = CreateSemaphore (NULL, initialCount, maximumCount, name ? mono_string_chars (name) : NULL); *error = GetLastError (); return sem; }
gpointer ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoString *name, gint32 *error) { gpointer event; event = CreateEvent (NULL, manual, initial, name ? mono_string_chars (name) : NULL); *error = GetLastError (); return event; }
MonoBoolean ves_icall_Mono_Security_Cryptography_KeyPairPersistence_IsUserProtected (MonoString *path) { gboolean ret = FALSE; /* no one, but the user, should have access to the directory */ #ifdef HOST_WIN32 ret = IsUserProtected (mono_string_chars (path)); #else ret = IsProtected (path, (S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH)); #endif return ret; }
gpointer ves_icall_System_Threading_Events_OpenEvent_internal (MonoString *name, gint32 rights, gint32 *error) { gpointer handle; *error = ERROR_SUCCESS; handle = OpenEvent (rights, FALSE, mono_string_chars (name)); if (!handle) *error = GetLastError (); return handle; }
MonoBoolean ves_icall_Mono_Security_Cryptography_KeyPairPersistence_ProtectMachine (MonoString *path) { gboolean ret = FALSE; /* read/write to owner, read to everyone else */ #ifdef HOST_WIN32 ret = ProtectMachine (mono_string_chars (path)); #else ret = Protect (path, (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH), (S_IXUSR | S_IXGRP | S_IXOTH)); #endif return ret; }
char *monostring_to_string(MonoString *string_obj) { mono_unichar2 *uni_buffer = mono_string_chars(string_obj); int len = mono_string_length(string_obj); char *buffer = new char[len + 1]; for (int i = 0; i < len; i++) { buffer[i] = get_char_from_unicode(uni_buffer[i]); } buffer[len] = '\0'; return buffer; }
MonoBoolean ves_icall_Mono_Security_Cryptography_KeyPairPersistence_ProtectUser (MonoString *path) { gboolean ret = FALSE; /* read/write to user, no access to everyone else */ #ifdef HOST_WIN32 ret = ProtectUser (mono_string_chars (path)); #else ret = Protect (path, (S_IRUSR | S_IWUSR), S_IXUSR); #endif return ret; }
gboolean ves_icall_System_Security_Principal_WindowsPrincipal_IsMemberOfGroupName (gpointer user, MonoString *group) { gboolean result = FALSE; #ifdef HOST_WIN32 MONO_ARCH_SAVE_REGS; /* Windows version use a cache built using WindowsIdentity._GetRoles */ g_warning ("IsMemberOfGroupName should never be called on Win32"); #else /* HOST_WIN32 */ gchar *utf8_groupname; MONO_ARCH_SAVE_REGS; utf8_groupname = mono_unicode_to_external (mono_string_chars (group)); if (utf8_groupname) { struct group *g = NULL; #ifdef HAVE_GETGRNAM_R struct group grp; gchar *fbuf; gint32 retval; #ifdef _SC_GETGR_R_SIZE_MAX size_t fbufsize = mono_sysconf (_SC_GETGR_R_SIZE_MAX); #else size_t fbufsize = MONO_SYSCONF_DEFAULT_SIZE; #endif fbuf = g_malloc0 (fbufsize); retval = getgrnam_r (utf8_groupname, &grp, fbuf, fbufsize, &g); result = ((retval == 0) && (g == &grp)); #else /* default to non thread-safe but posix compliant function */ g = getgrnam (utf8_groupname); result = (g != NULL); #endif if (result) { result = IsMemberOf ((uid_t) GPOINTER_TO_INT (user), g); } #ifdef HAVE_GETGRNAM_R g_free (fbuf); #endif g_free (utf8_groupname); } #endif /* HOST_WIN32 */ return result; }
static gboolean IsProtected (MonoString *path, gint32 protection) { gboolean result = FALSE; gchar *utf8_name = mono_unicode_to_external (mono_string_chars (path)); if (utf8_name) { struct stat st; if (stat (utf8_name, &st) == 0) { result = (((st.st_mode & 0777) & protection) == 0); } g_free (utf8_name); } return result; }
MonoBoolean ves_icall_Mono_Security_Cryptography_KeyPairPersistence_IsMachineProtected (MonoString *path) { gboolean ret = FALSE; MONO_ARCH_SAVE_REGS; /* no one, but the owner, should have write access to the directory */ #ifdef HOST_WIN32 ret = IsMachineProtected (mono_string_chars (path)); #else ret = IsProtected (path, (S_IWGRP | S_IWOTH)); #endif return ret; }
static gint32 string_invariant_indexof (MonoString *source, gint32 sindex, gint32 count, MonoString *value, MonoBoolean first) { gint32 lencmpstr; gunichar2 *src; gunichar2 *cmpstr; gint32 pos,i; lencmpstr = mono_string_length(value); src = mono_string_chars(source); cmpstr = mono_string_chars(value); if(first) { count -= lencmpstr; for(pos=sindex;pos <= sindex+count;pos++) { for(i=0;src[pos+i]==cmpstr[i];) { if(++i==lencmpstr) { return(pos); } } } return(-1); } else { for(pos=sindex-lencmpstr+1;pos>sindex-count;pos--) { if(memcmp (src+pos, cmpstr, lencmpstr*sizeof(gunichar2))==0) { return(pos); } } return(-1); } }
MonoBoolean ves_icall_Mono_Security_Cryptography_KeyPairPersistence_CanSecure (MonoString *root) { #if HOST_WIN32 gint32 flags; /* ACL are nice... unless you have FAT or other uncivilized filesystem */ if (!GetVolumeInformation (mono_string_chars (root), NULL, 0, NULL, NULL, (LPDWORD)&flags, NULL, 0)) return FALSE; return ((flags & FS_PERSISTENT_ACLS) == FS_PERSISTENT_ACLS); #else /* we assume some kind of security is applicable outside Windows */ return TRUE; #endif }
void ves_icall_System_Globalization_CompareInfo_assign_sortkey (MonoCompareInfo *this_obj, MonoSortKey *key, MonoString *source, gint32 options) { MonoArray *arr; gint32 keylen, i; keylen=mono_string_length (source); arr=mono_array_new (mono_domain_get (), mono_get_byte_class (), keylen); for(i=0; i<keylen; i++) { mono_array_set (arr, guint8, i, mono_string_chars (source)[i]); } MONO_OBJECT_SETREF (key, key, arr); }
static gboolean Protect (MonoString *path, gint32 file_mode, gint32 add_dir_mode) { gboolean result = FALSE; gchar *utf8_name = mono_unicode_to_external (mono_string_chars (path)); if (utf8_name) { struct stat st; if (stat (utf8_name, &st) == 0) { int mode = file_mode; if (st.st_mode & S_IFDIR) mode |= add_dir_mode; result = (chmod (utf8_name, mode) == 0); } g_free (utf8_name); } return result; }
String mono_to_utf16_string(MonoString *p_mono_string) { int len = mono_string_length(p_mono_string); String ret; if (len == 0) return ret; ret.resize(len + 1); ret.set(len, 0); CharType *src = (CharType *)mono_string_chars(p_mono_string); CharType *dst = &(ret.operator[](0)); for (int i = 0; i < len; i++) { dst[i] = src[i]; } return ret; }
static char * string_to_utf8 (MonoString *s) { char *as; GError *error = NULL; g_assert (s); if (!s->length) return g_strdup (""); as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error); if (error) { /* Happens with StringBuilders */ g_error_free (error); return g_strdup ("<INVALID UTF8>"); } else return as; }
gpointer ves_icall_System_GCHandle_GetAddrOfPinnedObject (guint32 handle) { MonoObject *obj; if (mono_gchandle_get_type (handle) != HANDLE_PINNED) return (gpointer)-2; obj = mono_gchandle_get_target (handle); if (obj) { MonoClass *klass = mono_object_class (obj); if (klass == mono_defaults.string_class) { return mono_string_chars ((MonoString*)obj); } else if (klass->rank) { return mono_array_addr ((MonoArray*)obj, char, 0); } else { /* the C# code will check and throw the exception */ /* FIXME: missing !klass->blittable test, see bug #61134 */ if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT) return (gpointer)-1; return (char*)obj + sizeof (MonoObject); } }
gpointer ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned, MonoString *name, MonoBoolean *created) { gpointer mutex; *created = TRUE; /* Need to blow away any old errors here, because code tests * for ERROR_ALREADY_EXISTS on success (!) to see if a mutex * was freshly created */ mono_w32error_set_last (ERROR_SUCCESS); if (!name) { mutex = mutex_create (owned); } else { mutex = namedmutex_create (owned, mono_string_chars (name)); if (mono_w32error_get_last () == ERROR_ALREADY_EXISTS) *created = FALSE; } return mutex; }
static MonoString *string_invariant_replace (MonoString *me, MonoString *oldValue, MonoString *newValue) { MonoString *ret; gunichar2 *src; gunichar2 *dest=NULL; /* shut gcc up */ gunichar2 *oldstr; gunichar2 *newstr=NULL; /* shut gcc up here too */ gint32 i, destpos; gint32 occurr; gint32 newsize; gint32 oldstrlen; gint32 newstrlen; gint32 srclen; occurr = 0; destpos = 0; oldstr = mono_string_chars(oldValue); oldstrlen = mono_string_length(oldValue); if (NULL != newValue) { newstr = mono_string_chars(newValue); newstrlen = mono_string_length(newValue); } else newstrlen = 0; src = mono_string_chars(me); srclen = mono_string_length(me); if (oldstrlen != newstrlen) { i = 0; while (i <= srclen - oldstrlen) { if (0 == memcmp(src + i, oldstr, oldstrlen * sizeof(gunichar2))) { occurr++; i += oldstrlen; } else i ++; } if (occurr == 0) return me; newsize = srclen + ((newstrlen - oldstrlen) * occurr); } else newsize = srclen; ret = NULL; i = 0; while (i < srclen) { if (0 == memcmp(src + i, oldstr, oldstrlen * sizeof(gunichar2))) { if (ret == NULL) { ret = mono_string_new_size( mono_domain_get (), newsize); dest = mono_string_chars(ret); memcpy (dest, src, i * sizeof(gunichar2)); } if (newstrlen > 0) { memcpy(dest + destpos, newstr, newstrlen * sizeof(gunichar2)); destpos += newstrlen; } i += oldstrlen; continue; } else if (ret != NULL) { dest[destpos] = src[i]; } destpos++; i++; } if (ret == NULL) return me; return ret; }
MonoArray * ves_icall_System_String_InternalSplit (MonoString *me, MonoArray *separator, gint32 count, gint32 options) { static MonoClass *String_array; MonoString * tmpstr; MonoArray * retarr; gunichar2 *src; gint32 arrsize, srcsize, splitsize; gint32 i, lastpos, arrpos; gint32 tmpstrsize; gint32 remempty; gint32 flag; gunichar2 *tmpstrptr; remempty = options & STRINGSPLITOPTIONS_REMOVE_EMPTY_ENTRIES; src = mono_string_chars (me); srcsize = mono_string_length (me); arrsize = mono_array_length (separator); if (!String_array) { MonoClass *klass = mono_array_class_get (mono_get_string_class (), 1); mono_memory_barrier (); String_array = klass; } splitsize = 1; /* Count the number of elements we will return. Note that this operation * guarantees that we will return exactly splitsize elements, and we will * have enough data to fill each. This allows us to skip some checks later on. */ if (remempty == 0) { for (i = 0; i != srcsize && splitsize < count; i++) { if (string_icall_is_in_array (separator, arrsize, src [i])) splitsize++; } } else if (count > 1) { /* Require pattern "Nondelim + Delim + Nondelim" to increment counter. * Lastpos != 0 means first nondelim found. * Flag = 0 means last char was delim. * Efficient, though perhaps confusing. */ lastpos = 0; flag = 0; for (i = 0; i != srcsize && splitsize < count; i++) { if (string_icall_is_in_array (separator, arrsize, src [i])) { flag = 0; } else if (flag == 0) { if (lastpos == 1) splitsize++; flag = 1; lastpos = 1; } } /* Nothing but separators */ if (lastpos == 0) { retarr = mono_array_new_specific (mono_class_vtable (mono_domain_get (), String_array), 0); return retarr; } } /* if no split chars found return the string */ if (splitsize == 1) { if (remempty == 0 || count == 1) { /* Copy the whole string */ retarr = mono_array_new_specific (mono_class_vtable (mono_domain_get (), String_array), 1); mono_array_setref (retarr, 0, me); } else { /* otherwise we have to filter out leading & trailing delims */ /* find first non-delim char */ for (; srcsize != 0; srcsize--, src++) { if (!string_icall_is_in_array (separator, arrsize, src [0])) break; } /* find last non-delim char */ for (; srcsize != 0; srcsize--) { if (!string_icall_is_in_array (separator, arrsize, src [srcsize - 1])) break; } tmpstr = mono_string_new_size (mono_domain_get (), srcsize); tmpstrptr = mono_string_chars (tmpstr); memcpy (tmpstrptr, src, srcsize * sizeof (gunichar2)); retarr = mono_array_new_specific (mono_class_vtable (mono_domain_get (), String_array), 1); mono_array_setref (retarr, 0, tmpstr); } return retarr; } lastpos = 0; arrpos = 0; retarr = mono_array_new_specific (mono_class_vtable (mono_domain_get (), String_array), splitsize); for (i = 0; i != srcsize && arrpos != splitsize; i++) { if (string_icall_is_in_array (separator, arrsize, src [i])) { if (lastpos != i || remempty == 0) { tmpstrsize = i - lastpos; tmpstr = mono_string_new_size (mono_domain_get (), tmpstrsize); tmpstrptr = mono_string_chars (tmpstr); memcpy (tmpstrptr, src + lastpos, tmpstrsize * sizeof (gunichar2)); mono_array_setref (retarr, arrpos, tmpstr); arrpos++; if (arrpos == splitsize - 1) { /* Shortcut the last array element */ lastpos = i + 1; if (remempty != 0) { /* Search for non-delim starting char (guaranteed to find one) Note that loop * condition is only there for safety. It will never actually terminate the loop. */ for (; lastpos != srcsize ; lastpos++) { if (!string_icall_is_in_array (separator, arrsize, src [lastpos])) break; } if (count > splitsize) { /* Since we have fewer results than our limit, we must remove * trailing delimiters as well. */ for (; srcsize != lastpos + 1 ; srcsize--) { if (!string_icall_is_in_array (separator, arrsize, src [srcsize - 1])) break; } } } tmpstrsize = srcsize - lastpos; tmpstr = mono_string_new_size (mono_domain_get (), tmpstrsize); tmpstrptr = mono_string_chars (tmpstr); memcpy (tmpstrptr, src + lastpos, tmpstrsize * sizeof (gunichar2)); mono_array_setref (retarr, arrpos, tmpstr); /* Loop will ALWAYS end here. Test criteria in the FOR loop is technically unnecessary. */ break; } } lastpos = i + 1; } } return retarr; }