diff options
author | Gabriel Scherer <gabriel.scherer@gmail.com> | 2023-05-15 11:05:44 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-15 11:05:44 +0200 |
commit | 233efc3afda778a57520b269f2d494628d12b567 (patch) | |
tree | 0f22c4b27dfd274817f5231d4052d214dd25e00f | |
parent | 399445ff2b43ba199f79831127c45b39c5ffa6aa (diff) | |
parent | 70ff202375737794910dd292f907cb52173cfa4a (diff) | |
download | ocaml-233efc3afda778a57520b269f2d494628d12b567.tar.gz |
Merge branch 'trunk' into nick-get-copy
26 files changed, 78 insertions, 31 deletions
@@ -10,6 +10,10 @@ Working version of `caml_read_directory`. Also, check for overflows in ext table sizes. (Xavier Leroy, report by Arseniy Alekseyev, review by Gabriel Scherer) +- #12223: Constify constructors and flags tables in C code. Now these + tables will go in the readonly segment, where they belong. + (Antonin Décimo, review by Gabriel Scherer and Xavier Leroy) + ### Code generation and optimizations: ### Standard library: @@ -174,6 +178,10 @@ OCaml 5.1.0 (Alexander Skvortsov, report by Török Edwin, design by Gabriel Scherer, Xavier Leroy) +- #12131: Simplify implementation of weak hash sets, fixing a + performance regression. (Nick Barnes, review by François Bobot, + Alain Frisch and Damien Doligez). + ### Type system: - #6941, #11187: prohibit using classes through recursive modules @@ -349,9 +357,8 @@ OCaml 5.1.0 (Xavier Leroy, review by Edwin Török and Gabriel Scherer, fix by Damien Doligez) -- #12131: Simplify implementation of weak hash sets, fixing a - performance regression. (Nick Barnes, review by François Bobot, - Alain Frisch and Damien Doligez). +- #12184: Sys.rename Windows fixes on directory corner cases. + (Jan Midtgaard, review by Anil Madhavapeddy) ### Other libraries: diff --git a/manual/src/refman/extensions/privatetypes.etex b/manual/src/refman/extensions/privatetypes.etex index b6ed0d8e74..dfd1e7565e 100644 --- a/manual/src/refman/extensions/privatetypes.etex +++ b/manual/src/refman/extensions/privatetypes.etex @@ -159,7 +159,7 @@ type v = private [< t > `A] corresponds to private variant types. One cannot create a value of the private type [v], except using the constructors that are explicitly listed as present, "(`A n)" in this example; yet, when -patter-matching on a [v], one should assume that any of the +pattern-matching on a [v], one should assume that any of the constructors of [t] could be present. Similarly to abstract types, the variance of type parameters diff --git a/otherlibs/unix/access.c b/otherlibs/unix/access.c index 0f7b3b3daf..48d95f7acb 100644 --- a/otherlibs/unix/access.c +++ b/otherlibs/unix/access.c @@ -35,7 +35,7 @@ # endif #endif -static int access_permission_table[] = { +static const int access_permission_table[] = { R_OK, W_OK, #ifdef _WIN32 diff --git a/otherlibs/unix/cst2constr.c b/otherlibs/unix/cst2constr.c index eab427e0b2..7bade04709 100644 --- a/otherlibs/unix/cst2constr.c +++ b/otherlibs/unix/cst2constr.c @@ -17,7 +17,7 @@ #include <caml/fail.h> #include "cst2constr.h" -value caml_unix_cst_to_constr(int n, int *tbl, int size, int deflt) +value caml_unix_cst_to_constr(int n, const int *tbl, int size, int deflt) { int i; for (i = 0; i < size; i++) diff --git a/otherlibs/unix/cst2constr.h b/otherlibs/unix/cst2constr.h index 075b6d4d2a..324d617f50 100644 --- a/otherlibs/unix/cst2constr.h +++ b/otherlibs/unix/cst2constr.h @@ -13,4 +13,5 @@ /* */ /**************************************************************************/ -extern value caml_unix_cst_to_constr(int n, int * tbl, int size, int deflt); +extern value caml_unix_cst_to_constr(int n, const int * tbl, int size, + int deflt); diff --git a/otherlibs/unix/getnameinfo.c b/otherlibs/unix/getnameinfo.c index bc7be72463..304c2576e2 100644 --- a/otherlibs/unix/getnameinfo.c +++ b/otherlibs/unix/getnameinfo.c @@ -29,7 +29,7 @@ #include <netdb.h> #endif -static int getnameinfo_flag_table[] = { +static const int getnameinfo_flag_table[] = { NI_NOFQDN, NI_NUMERICHOST, NI_NAMEREQD, NI_NUMERICSERV, NI_DGRAM }; diff --git a/otherlibs/unix/lockf_unix.c b/otherlibs/unix/lockf_unix.c index 43796c71a2..371e26fad2 100644 --- a/otherlibs/unix/lockf_unix.c +++ b/otherlibs/unix/lockf_unix.c @@ -96,7 +96,7 @@ CAMLprim value caml_unix_lockf(value fd, value cmd, value span) #define F_TEST 3 #endif -static int lock_command_table[] = { +static const int lock_command_table[] = { F_ULOCK, F_LOCK, F_TLOCK, F_TEST, F_LOCK, F_TLOCK }; diff --git a/otherlibs/unix/lseek_unix.c b/otherlibs/unix/lseek_unix.c index 2264c3b969..99f2fccbd8 100644 --- a/otherlibs/unix/lseek_unix.c +++ b/otherlibs/unix/lseek_unix.c @@ -35,7 +35,7 @@ #define EOVERFLOW ERANGE #endif -static int seek_command_table[] = { +static const int seek_command_table[] = { SEEK_SET, SEEK_CUR, SEEK_END }; diff --git a/otherlibs/unix/open_unix.c b/otherlibs/unix/open_unix.c index b527d8907e..41a566395a 100644 --- a/otherlibs/unix/open_unix.c +++ b/otherlibs/unix/open_unix.c @@ -38,7 +38,7 @@ #define O_RSYNC 0 #endif -static int open_flag_table[15] = { +static const int open_flag_table[15] = { O_RDONLY, O_WRONLY, O_RDWR, O_NONBLOCK, O_APPEND, O_CREAT, O_TRUNC, O_EXCL, O_NOCTTY, O_DSYNC, O_SYNC, O_RSYNC, 0, /* O_SHARE_DELETE, Windows-only */ @@ -48,7 +48,7 @@ static int open_flag_table[15] = { enum { CLOEXEC = 1, KEEPEXEC = 2 }; -static int open_cloexec_table[15] = { +static const int open_cloexec_table[15] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/otherlibs/unix/open_win32.c b/otherlibs/unix/open_win32.c index b4e02aefe9..6d545769f7 100644 --- a/otherlibs/unix/open_win32.c +++ b/otherlibs/unix/open_win32.c @@ -22,22 +22,22 @@ #include "unixsupport.h" #include <fcntl.h> -static int open_access_flags[15] = { +static const int open_access_flags[15] = { GENERIC_READ, GENERIC_WRITE, GENERIC_READ|GENERIC_WRITE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static int open_create_flags[15] = { +static const int open_create_flags[15] = { 0, 0, 0, 0, 0, O_CREAT, O_TRUNC, O_EXCL, 0, 0, 0, 0, 0, 0, 0 }; -static int open_share_flags[15] = { +static const int open_share_flags[15] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FILE_SHARE_DELETE, 0, 0 }; enum { CLOEXEC = 1, KEEPEXEC = 2 }; -static int open_cloexec_flags[15] = { +static const int open_cloexec_flags[15] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CLOEXEC, KEEPEXEC }; diff --git a/otherlibs/unix/sendrecv_unix.c b/otherlibs/unix/sendrecv_unix.c index 5ed785816c..46122888aa 100644 --- a/otherlibs/unix/sendrecv_unix.c +++ b/otherlibs/unix/sendrecv_unix.c @@ -24,7 +24,7 @@ #ifdef HAS_SOCKETS #include "socketaddr.h" -static int msg_flag_table[] = { +static const int msg_flag_table[] = { MSG_OOB, MSG_DONTROUTE, MSG_PEEK }; diff --git a/otherlibs/unix/sendrecv_win32.c b/otherlibs/unix/sendrecv_win32.c index 699babd9ca..1fc41d7098 100644 --- a/otherlibs/unix/sendrecv_win32.c +++ b/otherlibs/unix/sendrecv_win32.c @@ -20,7 +20,7 @@ #include "unixsupport.h" #include "socketaddr.h" -static int msg_flag_table[] = { +static const int msg_flag_table[] = { MSG_OOB, MSG_DONTROUTE, MSG_PEEK }; diff --git a/otherlibs/unix/shutdown_unix.c b/otherlibs/unix/shutdown_unix.c index 8c750e2479..898eebbb2d 100644 --- a/otherlibs/unix/shutdown_unix.c +++ b/otherlibs/unix/shutdown_unix.c @@ -21,7 +21,7 @@ #include <sys/socket.h> -static int shutdown_command_table[] = { +static const int shutdown_command_table[] = { 0, 1, 2 }; diff --git a/otherlibs/unix/shutdown_win32.c b/otherlibs/unix/shutdown_win32.c index a5f1d8c011..9bb0b3ed6b 100644 --- a/otherlibs/unix/shutdown_win32.c +++ b/otherlibs/unix/shutdown_win32.c @@ -16,7 +16,7 @@ #include <caml/mlvalues.h> #include "unixsupport.h" -static int shutdown_command_table[] = { +static const int shutdown_command_table[] = { 0, 1, 2 }; diff --git a/otherlibs/unix/stat_unix.c b/otherlibs/unix/stat_unix.c index 31b166fc65..3b28ef8409 100644 --- a/otherlibs/unix/stat_unix.c +++ b/otherlibs/unix/stat_unix.c @@ -44,7 +44,7 @@ #define EOVERFLOW ERANGE #endif -static int file_kind_table[] = { +static const int file_kind_table[] = { S_IFREG, S_IFDIR, S_IFCHR, S_IFBLK, S_IFLNK, S_IFIFO, S_IFSOCK }; diff --git a/otherlibs/unix/stat_win32.c b/otherlibs/unix/stat_win32.c index 197e4340d6..7f7b17e708 100644 --- a/otherlibs/unix/stat_win32.c +++ b/otherlibs/unix/stat_win32.c @@ -59,7 +59,7 @@ #define S_IFBLK 0 #endif -static int file_kind_table[] = { +static const int file_kind_table[] = { S_IFREG, S_IFDIR, S_IFCHR, S_IFBLK, S_IFLNK, S_IFIFO, S_IFSOCK }; diff --git a/otherlibs/unix/termios.c b/otherlibs/unix/termios.c index f41af150c7..b92ae42661 100644 --- a/otherlibs/unix/termios.c +++ b/otherlibs/unix/termios.c @@ -307,7 +307,7 @@ CAMLprim value caml_unix_tcgetattr(value fd) return res; } -static int when_flag_table[] = { +static const int when_flag_table[] = { TCSANOW, TCSADRAIN, TCSAFLUSH }; @@ -346,7 +346,7 @@ CAMLprim value caml_unix_tcdrain(value fd) } #endif -static int queue_flag_table[] = { +static const int queue_flag_table[] = { TCIFLUSH, TCOFLUSH, TCIOFLUSH }; @@ -357,7 +357,7 @@ CAMLprim value caml_unix_tcflush(value fd, value queue) return Val_unit; } -static int action_flag_table[] = { +static const int action_flag_table[] = { TCOOFF, TCOON, TCIOFF, TCION }; diff --git a/otherlibs/unix/unixsupport_unix.c b/otherlibs/unix/unixsupport_unix.c index 449af8b5c2..0d50e246b2 100644 --- a/otherlibs/unix/unixsupport_unix.c +++ b/otherlibs/unix/unixsupport_unix.c @@ -242,7 +242,7 @@ #define EOVERFLOW (-1) #endif -static int error_table[] = { +static const int error_table[] = { E2BIG, EACCES, EAGAIN, EBADF, EBUSY, ECHILD, EDEADLK, EDOM, EEXIST, EFAULT, EFBIG, EINTR, EINVAL, EIO, EISDIR, EMFILE, EMLINK, ENAMETOOLONG, ENFILE, ENODEV, ENOENT, ENOEXEC, ENOLCK, ENOMEM, ENOSPC, diff --git a/otherlibs/unix/unixsupport_win32.c b/otherlibs/unix/unixsupport_win32.c index cb5eb35df7..509afa3ea3 100644 --- a/otherlibs/unix/unixsupport_win32.c +++ b/otherlibs/unix/unixsupport_win32.c @@ -251,7 +251,7 @@ void caml_win32_maperr(DWORD errcode) #undef EACCESS #define EACCESS EACCES -static int error_table[] = { +static const int error_table[] = { E2BIG, EACCESS, EAGAIN, EBADF, EBUSY, ECHILD, EDEADLK, EDOM, EEXIST, EFAULT, EFBIG, EINTR, EINVAL, EIO, EISDIR, EMFILE, EMLINK, ENAMETOOLONG, ENFILE, ENODEV, ENOENT, ENOEXEC, ENOLCK, ENOMEM, ENOSPC, diff --git a/otherlibs/unix/wait.c b/otherlibs/unix/wait.c index 3509c76b98..b5aa0516bd 100644 --- a/otherlibs/unix/wait.c +++ b/otherlibs/unix/wait.c @@ -83,7 +83,7 @@ CAMLprim value caml_unix_wait(value unit) #define waitpid(pid,status,opts) wait4(pid,status,opts,NULL) #endif -static int wait_flag_table[] = { +static const int wait_flag_table[] = { WNOHANG, WUNTRACED }; diff --git a/otherlibs/unix/winwait.c b/otherlibs/unix/winwait.c index 2d28117af4..69ac8dd668 100644 --- a/otherlibs/unix/winwait.c +++ b/otherlibs/unix/winwait.c @@ -36,7 +36,7 @@ static value alloc_process_status(HANDLE pid, int status) enum { CAML_WNOHANG = 1, CAML_WUNTRACED = 2 }; -static int wait_flag_table[] = { CAML_WNOHANG, CAML_WUNTRACED }; +static const int wait_flag_table[] = { CAML_WNOHANG, CAML_WUNTRACED }; CAMLprim value caml_unix_waitpid(value vflags, value vpid_req) { diff --git a/runtime/extern.c b/runtime/extern.c index 4301c3df13..7b5b81379b 100644 --- a/runtime/extern.c +++ b/runtime/extern.c @@ -991,7 +991,7 @@ oom1: #endif -static int extern_flag_values[] = { +static const int extern_flag_values[] = { NO_SHARING, CLOSURES, COMPAT_32, COMPRESSED }; diff --git a/runtime/signals.c b/runtime/signals.c index 5a21024ad4..8abdf346b1 100644 --- a/runtime/signals.c +++ b/runtime/signals.c @@ -445,7 +445,7 @@ CAMLexport void caml_process_pending_actions(void) #define SIGXFSZ -1 #endif -static int posix_signals[] = { +static const int posix_signals[] = { SIGABRT, SIGALRM, SIGFPE, SIGHUP, SIGILL, SIGINT, SIGKILL, SIGPIPE, SIGQUIT, SIGSEGV, SIGTERM, SIGUSR1, SIGUSR2, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGVTALRM, SIGPROF, SIGBUS, diff --git a/runtime/win32.c b/runtime/win32.c index 599805145f..90527f01c8 100644 --- a/runtime/win32.c +++ b/runtime/win32.c @@ -783,6 +783,28 @@ CAMLexport wchar_t *caml_win32_getenv(wchar_t const *lpName) int caml_win32_rename(const wchar_t * oldpath, const wchar_t * newpath) { + /* First handle corner-cases not handled by MoveFileEx: + - dir to empty dir - positive - should succeed + - dir to existing file - should fail */ + DWORD old_attribs = GetFileAttributes(oldpath); + if ((old_attribs != INVALID_FILE_ATTRIBUTES) && + (old_attribs & FILE_ATTRIBUTE_DIRECTORY) != 0 && + (old_attribs & FILE_ATTRIBUTE_HIDDEN) == 0 && + (old_attribs & FILE_ATTRIBUTE_SYSTEM) == 0) { + DWORD new_attribs = GetFileAttributes(newpath); + if ((new_attribs != INVALID_FILE_ATTRIBUTES) && + (new_attribs & FILE_ATTRIBUTE_HIDDEN) == 0 && + (new_attribs & FILE_ATTRIBUTE_SYSTEM) == 0) { + if ((new_attribs & FILE_ATTRIBUTE_DIRECTORY) != 0) { + /* Try to delete and fall though. + RemoveDirectoryW fails on non-empty dirs as intended. */ + RemoveDirectoryW(newpath); + } else { + errno = ENOTDIR; + return -1; + } + } + } /* MOVEFILE_REPLACE_EXISTING: to be closer to POSIX MOVEFILE_COPY_ALLOWED: MoveFile performs a copy if old and new paths are on different devices, so we do the same here for diff --git a/testsuite/tests/lib-sys/rename.ml b/testsuite/tests/lib-sys/rename.ml index 948481c3de..7c62f218e9 100644 --- a/testsuite/tests/lib-sys/rename.ml +++ b/testsuite/tests/lib-sys/rename.ml @@ -82,3 +82,18 @@ let _ = testfailure "foo" "bar"; print_newline(); safe_remove f1; safe_remove_dir "foo"; safe_remove_dir "bar"; + print_string "Rename directory to existing empty directory: "; + Sys.mkdir "foo" 0o755; + Sys.mkdir "bar" 0o755; + testrenamedir "foo" "bar"; + print_newline(); + safe_remove_dir "foo"; + safe_remove_dir "bar"; + print_string "Rename directory to existing file: "; + Sys.mkdir "foo" 0o755; + writefile f2 "xyz"; + testfailure "foo" f2; + print_newline(); + safe_remove_dir "foo"; + safe_remove f2; + safe_remove_dir f2; diff --git a/testsuite/tests/lib-sys/rename.reference b/testsuite/tests/lib-sys/rename.reference index db06aad9d3..6fe40fcf87 100644 --- a/testsuite/tests/lib-sys/rename.reference +++ b/testsuite/tests/lib-sys/rename.reference @@ -5,3 +5,5 @@ Renaming to a nonexisting directory: fails as expected Rename directory to a nonexisting directory: passed Rename a nonexisting directory: fails as expected Rename directory to a non-empty directory: fails as expected +Rename directory to existing empty directory: passed +Rename directory to existing file: fails as expected |