diff --git a/src/modules/_Stdio/efuns.c b/src/modules/_Stdio/efuns.c index 2438a21337ad5973fcaaa7beff4bf8e3d9782379..cf9dc5fbacb6357ac00180e25f7545b2c313f54a 100644 --- a/src/modules/_Stdio/efuns.c +++ b/src/modules/_Stdio/efuns.c @@ -1528,11 +1528,6 @@ void f_mv(INT32 args) INT32 i; struct pike_string *str1; struct pike_string *str2; -#ifdef __NT__ - int orig_errno = errno; - int err; - PIKE_STAT_T st; -#endif VALID_FILE_IO("mv","write"); @@ -1560,170 +1555,7 @@ void f_mv(INT32 args) return; } -#ifndef __NT__ - i=rename(str1->str, str2->str); -#else - - /* Emulate the behavior of unix rename(2) when the destination exists. */ - - if (movefileex) { - if (MoveFileEx (str1->str, str2->str, 0)) { - i = 0; - goto no_nt_rename_kludge; - } - if ((i = GetLastError()) != ERROR_ALREADY_EXISTS) - goto no_nt_rename_kludge; - } - else { - /* Fall back to rename() for W98 and earlier. Unlike MoveFileEx, - * it can't move directories between directories. */ - if (!rename (str1->str, str2->str)) { - i = 0; - goto no_nt_rename_kludge; - } - if ((i = errno) != EEXIST) - goto no_nt_rename_kludge; - } - -#ifdef HAVE_LSTAT - if (fd_lstat (str2->str, &st)) goto no_nt_rename_kludge; -#else - if (fd_stat (str2->str, &st)) goto no_nt_rename_kludge; -#endif - - if ((st.st_mode & S_IFMT) != S_IFDIR && movefileex) { - /* MoveFileEx can overwrite a file but not a dir. */ - if (!(st.st_mode & _S_IWRITE)) - /* Like in f_rm, we got to handle the case that NT looks on the - * permissions on the file itself before removing it. */ - if (chmod (str2->str, st.st_mode | _S_IWRITE)) - goto no_nt_rename_kludge; - if (movefileex (str1->str, str2->str, MOVEFILE_REPLACE_EXISTING)) - i = 0; /* Success. */ - else - chmod (str2->str, st.st_mode); - } - - else { - char *s = malloc (str2->len + 2), *p; - if (!s) { - i = movefileex ? ERROR_NOT_ENOUGH_MEMORY : ENOMEM; - goto no_nt_rename_kludge; - } - memcpy (s, str2->str, str2->len); - p = s + str2->len; - p[2] = 0; - - if ((st.st_mode & S_IFMT) == S_IFDIR) { - /* Check first that the target is empty if it's a directory, so - * that we won't even bother trying with the stunt below. */ - WIN32_FIND_DATA *dir = malloc (sizeof (WIN32_FIND_DATA)); - HANDLE h; - if (!dir) { - i = movefileex ? ERROR_NOT_ENOUGH_MEMORY : ENOMEM; - goto nt_rename_kludge_end; - } - p[0] = '/', p[1] = '*'; - h = FindFirstFile (s, dir); - if (h != INVALID_HANDLE_VALUE) { - do { - if (dir->cFileName[0] != '.' || - (dir->cFileName[1] && - (dir->cFileName[1] != '.' || dir->cFileName[2]))) { - /* Target dir not empty. */ - FindClose (h); - free (dir); - goto nt_rename_kludge_end; - } - } while (FindNextFile (h, dir)); - FindClose (h); - } - free (dir); - } - - /* Move away the target temporarily to do the move, then cleanup - * or undo depending on how it went. */ - for (p[0] = 'A'; p[0] != 'Z'; p[0]++) - for (p[1] = 'A'; p[1] != 'Z'; p[1]++) { - if (movefileex) { - if (!movefileex (str2->str, s, 0)) { - if (GetLastError() == ERROR_ALREADY_EXISTS) continue; - else goto nt_rename_kludge_end; - } - } - else { - if (rename (str2->str, s)) { - if (errno == EEXIST) continue; - else goto nt_rename_kludge_end; - } - } - if (movefileex ? - movefileex (str1->str, str2->str, MOVEFILE_REPLACE_EXISTING) : - !rename (str1->str, str2->str)) { - if (!(st.st_mode & _S_IWRITE)) - if (chmod (s, st.st_mode | _S_IWRITE)) - goto nt_rename_kludge_fail; - if ((st.st_mode & S_IFMT) == S_IFDIR) { - while ((err = rmdir (s)) && (errno == EINTR)) - ; - } else { - while ((err = unlink (s)) && (errno == EINTR)) - ; - } - if (!err) { /* Success. */ - i = 0; - goto nt_rename_kludge_end; - } - - nt_rename_kludge_fail: - /* Couldn't remove the old target, perhaps the directory - * grew files. */ - if (!(st.st_mode & _S_IWRITE)) - chmod (s, st.st_mode); - if (movefileex ? - !movefileex (str2->str, str1->str, MOVEFILE_REPLACE_EXISTING) : - rename (str2->str, str1->str)) { - /* Old target left behind but the rename is still - * successful, so we claim success anyway in lack of - * better error reporting capabilities. */ - i = 0; - goto nt_rename_kludge_end; - } - } - - rename (s, str2->str); - goto nt_rename_kludge_end; - } - - nt_rename_kludge_end: - free (s); - } - -no_nt_rename_kludge: - if (i) { - if (movefileex) - switch (i) { - /* Try to translate NT errors to errno codes that NT's rename() - * would return. */ - case ERROR_INVALID_NAME: - errno = EINVAL; - break; - case ERROR_NOT_ENOUGH_MEMORY: - errno = ENOMEM; - break; - case ERROR_FILE_NOT_FOUND: - case ERROR_PATH_NOT_FOUND: - errno = ENOENT; - break; - case ERROR_ALREADY_EXISTS: - errno = EEXIST; - break; - default: - errno = EACCES; - } - } - else errno = orig_errno; -#endif /* __NT__ */ + i = fd_rename(str1->str, str2->str); pop_n_elems(args); push_int(!i);