The unpac monorepo manager self-hosting as a monorepo using unpac
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #13700 from MisterDA/posix-2008-getgrnam_r-getgrgid_r

Use more POSIX thread-safe functions in libunix

authored by

David Allsopp and committed by
GitHub
29228791 f52810e1

+249 -44
+4
Changes
··· 228 228 229 229 ### Other libraries: 230 230 231 + - #13700: Use POSIX thread-safe getgrnam_r, getgrgid_r, getpwnam_r, getpwuid_r, 232 + gmtime_r, localtime_r, getlogin_r, and fix mktime error checking. 233 + (Antonin Décimo, review by David Allsopp, Stefan Muenzel, and Miod Vallat) 234 + 231 235 - #14406: Better handling of address length for unix sockets, improving Haiku 232 236 compatibility. 233 237 (Sylvain Kerjean, review by Antonin Décimo and Nicolás Ojeda Bär)
+30
configure
··· 715 715 #endif" 716 716 717 717 ac_header_c_list= 718 + ac_func_c_list= 718 719 ac_subst_vars='LTLIBOBJS 719 720 LIBOBJS 720 721 DIFF_FLAGS ··· 3168 3169 as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H" 3169 3170 as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H" 3170 3171 as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H" 3172 + as_fn_append ac_func_c_list " getlogin_r HAVE_GETLOGIN_R" 3173 + as_fn_append ac_func_c_list " getgrnam_r HAVE_GETGRNAM_R" 3174 + as_fn_append ac_func_c_list " getgrgid_r HAVE_GETGRGID_R" 3175 + as_fn_append ac_func_c_list " getpwnam_r HAVE_GETPWNAM_R" 3176 + as_fn_append ac_func_c_list " getpwuid_r HAVE_GETPWUID_R" 3177 + as_fn_append ac_func_c_list " gmtime_r HAVE_GMTIME_R" 3178 + as_fn_append ac_func_c_list " localtime_r HAVE_LOCALTIME_R" 3171 3179 3172 3180 # Auxiliary files required by this configure script. 3173 3181 ac_aux_files="install-sh ltmain.sh config.guess config.sub" ··· 20935 20943 fi 20936 20944 20937 20945 20946 + ac_func= 20947 + for ac_item in $ac_func_c_list 20948 + do 20949 + if test $ac_func; then 20950 + ac_fn_c_check_func "$LINENO" $ac_func ac_cv_func_$ac_func 20951 + if eval test \"x\$ac_cv_func_$ac_func\" = xyes; then 20952 + echo "#define $ac_item 1" >> confdefs.h 20953 + fi 20954 + ac_func= 20955 + else 20956 + ac_func=$ac_item 20957 + fi 20958 + done 20959 + 20960 + 20961 + 20962 + 20963 + 20964 + 20938 20965 ## getgroups 20939 20966 ac_fn_c_check_func "$LINENO" "getgroups" "ac_cv_func_getgroups" 20940 20967 if test "x$ac_cv_func_getgroups" = xyes ··· 21059 21086 printf "%s\n" "#define HAS_MKTIME 1" >>confdefs.h 21060 21087 21061 21088 fi 21089 + 21090 + 21091 + 21062 21092 21063 21093 21064 21094 ## setsid
+3
configure.ac
··· 2349 2349 AC_DEFINE([HAS_WAIT4], [1]) 2350 2350 ]) 2351 2351 2352 + AC_CHECK_FUNCS_ONCE([getlogin_r getgrnam_r getgrgid_r getpwnam_r getpwuid_r]) 2353 + 2352 2354 ## getgroups 2353 2355 AC_CHECK_FUNC([getgroups], [AC_DEFINE([HAS_GETGROUPS], [1])]) 2354 2356 ··· 2396 2398 ## mktime 2397 2399 2398 2400 AC_CHECK_FUNC([mktime], [AC_DEFINE([HAS_MKTIME], [1])]) 2401 + AC_CHECK_FUNCS_ONCE([gmtime_r localtime_r]) 2399 2402 2400 2403 ## setsid 2401 2404
+73 -14
otherlibs/unix/getgr.c
··· 18 18 #include <caml/alloc.h> 19 19 #include <caml/memory.h> 20 20 #include "caml/unixsupport.h" 21 + #include <unistd.h> 21 22 #include <errno.h> 22 - #include <stdio.h> 23 23 #include <grp.h> 24 24 25 - static value alloc_group_entry(struct group *entry) 25 + static value alloc_group_entry(const struct group *entry) 26 26 { 27 27 CAMLparam0(); 28 28 CAMLlocal3(name, pass, mem); ··· 41 41 CAMLreturn(res); 42 42 } 43 43 44 + /* Arbitrary limit to prevent allocating too much memory */ 45 + #define CAML_GETGR_R_SIZE_MAX (1024 * 64) 46 + 44 47 CAMLprim value caml_unix_getgrnam(value name) 45 48 { 49 + value res; 46 50 struct group * entry; 47 51 if (! caml_string_is_c_safe(name)) caml_raise_not_found(); 52 + 53 + #ifdef HAVE_GETGRNAM_R 54 + long initlen = sysconf(_SC_GETGR_R_SIZE_MAX); 55 + size_t len = initlen <= 0 ? /* default */ 1024 : (size_t) initlen; 56 + struct group result; 57 + char *buffer = caml_stat_alloc_noexc(len); 58 + if (buffer == NULL) 59 + caml_unix_error(ENOMEM, "getgrnam", Nothing); 60 + int e; 61 + while ((e = getgrnam_r(String_val(name), &result, buffer, len, &entry)) 62 + == ERANGE) { 63 + len *= 2; 64 + char *newbuffer; 65 + if (len > CAML_GETGR_R_SIZE_MAX || 66 + (newbuffer = caml_stat_resize_noexc(buffer, len)) == NULL) { 67 + caml_stat_free(buffer); 68 + caml_unix_error(ENOMEM, "getgrnam", Nothing); 69 + } 70 + buffer = newbuffer; 71 + } 72 + if (e != 0) { 73 + caml_stat_free(buffer); 74 + if (e == EINTR) 75 + #else 48 76 errno = 0; 49 77 entry = getgrnam(String_val(name)); 50 78 if (entry == NULL) { 51 - if (errno == EINTR) { 52 - caml_uerror("getgrnam", Nothing); 53 - } else { 54 - caml_raise_not_found(); 55 - } 79 + if (errno == EINTR) 80 + #endif 81 + caml_unix_error(EINTR, "getgrnam", Nothing); 82 + caml_raise_not_found(); 56 83 } 57 - return alloc_group_entry(entry); 84 + res = alloc_group_entry(entry); 85 + #if HAVE_GETGRNAM_R 86 + caml_stat_free(buffer); 87 + #endif 88 + return res; 58 89 } 59 90 60 91 CAMLprim value caml_unix_getgrgid(value gid) 61 92 { 93 + value res; 62 94 struct group * entry; 95 + 96 + #ifdef HAVE_GETGRGID_R 97 + long initlen = sysconf(_SC_GETGR_R_SIZE_MAX); 98 + size_t len = initlen <= 0 ? /* default */ 1024 : (size_t) initlen; 99 + struct group result; 100 + char *buffer = caml_stat_alloc_noexc(len); 101 + if (buffer == NULL) 102 + caml_unix_error(ENOMEM, "getgrid", Nothing); 103 + int e; 104 + while ((e = getgrgid_r(Int_val(gid), &result, buffer, len, &entry)) 105 + == ERANGE) { 106 + len *= 2; 107 + char *newbuffer; 108 + if (len > CAML_GETGR_R_SIZE_MAX || 109 + (newbuffer = caml_stat_resize_noexc(buffer, len)) == NULL) { 110 + caml_stat_free(buffer); 111 + caml_unix_error(ENOMEM, "getgrid", Nothing); 112 + } 113 + buffer = newbuffer; 114 + } 115 + if (e != 0) { 116 + caml_stat_free(buffer); 117 + if (e == EINTR) 118 + #else 63 119 errno = 0; 64 120 entry = getgrgid(Int_val(gid)); 65 121 if (entry == NULL) { 66 - if (errno == EINTR) { 67 - caml_uerror("getgrgid", Nothing); 68 - } else { 69 - caml_raise_not_found(); 70 - } 122 + if (errno == EINTR) 123 + #endif 124 + caml_unix_error(EINTR, "getgrgid", Nothing); 125 + caml_raise_not_found(); 71 126 } 72 - return alloc_group_entry(entry); 127 + res = alloc_group_entry(entry); 128 + #if HAVE_GETGRGID_R 129 + caml_stat_free(buffer); 130 + #endif 131 + return res; 73 132 }
+38 -4
otherlibs/unix/getlogin.c
··· 13 13 /* */ 14 14 /**************************************************************************/ 15 15 16 - #include <caml/mlvalues.h> 17 16 #include <caml/alloc.h> 18 17 #include "caml/unixsupport.h" 18 + #include <limits.h> 19 + #include <unistd.h> 19 20 #include <errno.h> 20 21 21 - extern char * getlogin(void); 22 + #define CAML_LOGIN_NAME_MAX (256 * 4) 22 23 23 24 CAMLprim value caml_unix_getlogin(value unit) 24 25 { 26 + value res; 25 27 char * name; 28 + #ifdef HAVE_GETLOGIN_R 29 + size_t bufsize; 30 + #ifdef LOGIN_NAME_MAX 31 + bufsize = LOGIN_NAME_MAX; 32 + #else 33 + long initlen = sysconf(_SC_LOGIN_NAME_MAX); 34 + bufsize = initlen <= 0 ? _POSIX_LOGIN_NAME_MAX : (size_t) initlen; 35 + #endif 36 + name = caml_stat_alloc_noexc(bufsize); 37 + if (name == NULL) 38 + caml_unix_error(ENOMEM, "getlogin", Nothing); 39 + int e; 40 + while ((e = getlogin_r(name, bufsize)) == ERANGE) { 41 + bufsize *= 2; 42 + char *newname; 43 + if (bufsize > CAML_LOGIN_NAME_MAX || 44 + (newname = caml_stat_realloc(name)) == NULL) { 45 + caml_stat_free(name); 46 + caml_unix_error(ENOMEM, "getlogin", Nothing); 47 + } 48 + name = newname; 49 + } 50 + if (e != 0) { 51 + caml_stat_free(name); 52 + #else 26 53 name = getlogin(); 27 - if (name == NULL) caml_unix_error(ENOENT, "getlogin", Nothing); 28 - return caml_copy_string(name); 54 + if (name == NULL) { 55 + #endif 56 + caml_unix_error(ENOENT, "getlogin", Nothing); 57 + } 58 + res = caml_copy_string(name); 59 + #ifdef HAVE_GETLOGIN_R 60 + caml_stat_free(name); 61 + #endif 62 + return res; 29 63 }
+74 -15
otherlibs/unix/getpw.c
··· 21 21 #include <errno.h> 22 22 #include <pwd.h> 23 23 24 - static value alloc_passwd_entry(struct passwd *entry) 24 + static value alloc_passwd_entry(const struct passwd *entry) 25 25 { 26 26 CAMLparam0(); 27 27 CAMLlocal5(name, passwd, gecos, dir, shell); ··· 47 47 CAMLreturn(res); 48 48 } 49 49 50 + /* Arbitrary limit to prevent allocating too much memory */ 51 + #define CAML_GETPW_R_SIZE_MAX (1024 * 64) 52 + 50 53 CAMLprim value caml_unix_getpwnam(value name) 51 54 { 55 + value res; 52 56 struct passwd * entry; 53 57 if (! caml_string_is_c_safe(name)) caml_raise_not_found(); 58 + 59 + #ifdef HAVE_GETPWNAM_R 60 + long initlen = sysconf(_SC_GETPW_R_SIZE_MAX); 61 + size_t len = initlen <= 0 ? /* default */ 1024 : (size_t) initlen; 62 + struct passwd result; 63 + char *buffer = caml_stat_alloc_noexc(len); 64 + if (buffer == NULL) 65 + caml_unix_error(ENOMEM, "getpwnam", Nothing); 66 + int e; 67 + while ((e = getpwnam_r(String_val(name), &result, buffer, len, &entry)) 68 + == ERANGE) { 69 + len *= 2; 70 + char *newbuffer; 71 + if (len > CAML_GETPW_R_SIZE_MAX || 72 + (newbuffer = caml_stat_resize_noexc(buffer, len)) == NULL) { 73 + caml_stat_free(buffer); 74 + caml_unix_error(ENOMEM, "getpwnam", Nothing); 75 + } 76 + buffer = newbuffer; 77 + } 78 + if (e != 0) { 79 + caml_stat_free(buffer); 80 + if (e == EINTR) 81 + #else 54 82 errno = 0; 55 83 entry = getpwnam(String_val(name)); 56 - if (entry == (struct passwd *) NULL) { 57 - if (errno == EINTR) { 58 - caml_uerror("getpwnam", Nothing); 59 - } else { 60 - caml_raise_not_found(); 61 - } 84 + if (entry == NULL) { 85 + if (errno == EINTR) 86 + #endif 87 + caml_unix_error(EINTR, "getpwnam", Nothing); 88 + caml_raise_not_found(); 62 89 } 63 - return alloc_passwd_entry(entry); 90 + res = alloc_passwd_entry(entry); 91 + #if HAVE_GETPWNAM_R 92 + caml_stat_free(buffer); 93 + #endif 94 + return res; 64 95 } 65 96 66 97 CAMLprim value caml_unix_getpwuid(value uid) 67 98 { 99 + value res; 68 100 struct passwd * entry; 101 + 102 + #ifdef HAVE_GETPWUID_R 103 + long initlen = sysconf(_SC_GETPW_R_SIZE_MAX); 104 + size_t len = initlen <= 0 ? /* default */ 1024 : (size_t) initlen; 105 + struct passwd result; 106 + char *buffer = caml_stat_alloc(len); 107 + if (buffer == NULL) 108 + caml_unix_error(ENOMEM, "getpwuid", Nothing); 109 + int e; 110 + while ((e = getpwuid_r(Int_val(uid), &result, buffer, len, &entry)) 111 + == ERANGE) { 112 + len *= 2; 113 + char *newbuffer; 114 + if (len > CAML_GETPW_R_SIZE_MAX || 115 + (newbuffer = caml_stat_resize_noexc(buffer, len)) == NULL) { 116 + caml_stat_free(buffer); 117 + caml_unix_error(ENOMEM, "getpwuid", Nothing); 118 + } 119 + buffer = newbuffer; 120 + } 121 + if (e != 0) { 122 + caml_stat_free(buffer); 123 + if (e == EINTR) 124 + #else 69 125 errno = 0; 70 126 entry = getpwuid(Int_val(uid)); 71 - if (entry == (struct passwd *) NULL) { 72 - if (errno == EINTR) { 73 - caml_uerror("getpwuid", Nothing); 74 - } else { 75 - caml_raise_not_found(); 76 - } 127 + if (entry == NULL) { 128 + if (errno == EINTR) 129 + #endif 130 + caml_unix_error(EINTR, "getpwuid", Nothing); 131 + caml_raise_not_found(); 77 132 } 78 - return alloc_passwd_entry(entry); 133 + res = alloc_passwd_entry(entry); 134 + #if HAVE_GETPWUID_R 135 + caml_stat_free(buffer); 136 + #endif 137 + return res; 79 138 }
+19 -11
otherlibs/unix/gmtime.c
··· 21 21 #include <time.h> 22 22 #include <errno.h> 23 23 24 - static value alloc_tm(struct tm *tm) 24 + static value alloc_tm(const struct tm *tm) 25 25 { 26 26 value res; 27 27 res = caml_alloc_small(9, 0); ··· 39 39 40 40 CAMLprim value caml_unix_gmtime(value t) 41 41 { 42 - time_t clock; 42 + time_t clock = (time_t) Double_val(t); 43 43 struct tm * tm; 44 - clock = (time_t) Double_val(t); 44 + #ifdef HAVE_GMTIME_R 45 + struct tm result; 46 + tm = gmtime_r(&clock, &result); 47 + #else 45 48 tm = gmtime(&clock); 46 - if (tm == NULL) caml_unix_error(EINVAL, "gmtime", Nothing); 49 + #endif 50 + if (tm == NULL) caml_uerror("gmtime", Nothing); 47 51 return alloc_tm(tm); 48 52 } 49 53 50 54 CAMLprim value caml_unix_localtime(value t) 51 55 { 52 - time_t clock; 56 + time_t clock = (time_t) Double_val(t); 53 57 struct tm * tm; 54 - clock = (time_t) Double_val(t); 58 + #ifdef HAVE_LOCALTIME_R 59 + struct tm result; 60 + tm = localtime_r(&clock, &result); 61 + #else 55 62 tm = localtime(&clock); 56 - if (tm == NULL) caml_unix_error(EINVAL, "localtime", Nothing); 63 + #endif 64 + if (tm == NULL) caml_uerror("localtime", Nothing); 57 65 return alloc_tm(tm); 58 66 } 59 67 ··· 73 81 tm.tm_mday = Int_val(Field(t, 3)); 74 82 tm.tm_mon = Int_val(Field(t, 4)); 75 83 tm.tm_year = Int_val(Field(t, 5)); 76 - tm.tm_wday = Int_val(Field(t, 6)); 77 - tm.tm_yday = Int_val(Field(t, 7)); 78 - tm.tm_isdst = -1; /* tm.tm_isdst = Bool_val(Field(t, 8)); */ 84 + tm.tm_isdst = -1; 85 + tm.tm_wday = -1; 79 86 clock = mktime(&tm); 80 - if (clock == (time_t) -1) caml_unix_error(ERANGE, "mktime", Nothing); 87 + if (clock == (time_t) -1 && tm.tm_wday == -1) 88 + caml_uerror("mktime", Nothing); 81 89 tmval = alloc_tm(&tm); 82 90 clkval = caml_copy_double((double) clock); 83 91 res = caml_alloc_small(2, 0);
+8
runtime/caml/s.h.in
··· 226 226 227 227 /* Define HAS_MKTIME if you have mktime(). */ 228 228 229 + #undef HAVE_GMTIME_R 230 + #undef HAVE_LOCALTIME_R 231 + 229 232 #undef HAS_SETSID 230 233 231 234 /* Define HAS_SETSID if you have setsid(). */ ··· 323 326 #undef HAS_ZSTD 324 327 325 328 #undef HAVE_MAX_ALIGN_T 329 + 330 + #undef HAVE_GETGRNAM_R 331 + #undef HAVE_GETGRGID_R 332 + #undef HAVE_GETPWNAM_R 333 + #undef HAVE_GETPWUID_R 326 334 327 335 /* 3. Language extensions. */ 328 336