Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Re^6: Read in hostfile, modify, output

by eyepopslikeamosquito (Archbishop)
on Dec 21, 2016 at 19:19 UTC ( [id://1178321]=note: print w/replies, xml ) Need Help??


in reply to Re^5: Read in hostfile, modify, output
in thread Read in hostfile, modify, output

Under Windows, this cannot happen. The rename will fail if the target file exists.
C:\Projects_Perl\testing>rename newfile.txt originalfile.txt
A duplicate file name exists, or the file cannot be found.
It can happen. Use the Windows MOVE command instead of RENAME:
MOVE /Y newfile.txt originalfile.txt
Or use Perl:
perl -e "rename('newfile.txt', 'originalfile.txt')"

Replies are listed 'Best First'.
Re^7: Read in hostfile, modify, output
by Marshall (Canon) on Dec 22, 2016 at 20:25 UTC
    Thanks for the info!

    Its been more than a decade since I worked on a serious Windows installation program for a huge 24/7 application. I am sure that my recollections are fuzzy from Perl 5.6, Win NT days! I remember spending a lot of time dealing with some of the more unusual cases, like what happens if we have a new fileA, but currently running processes are linked to an old .dll version or have open the old version of fileA or are using the info from the old version even though they have closed their filehandle to the old file version. That kind of system coordination stuff can be a mess and beyond the scope in this thread.

    The general advice in this thread:

    1. Get the new copy "ready to go" on the HD.
    2. Make a backup of the original file and have a plan to revert to that if something fails.
    3. Do the file replacement (newFile replaces oldFile) in the fewest, fastest steps possible.
    Are fundamentally sound, excellent practical advice.
Re^7: Read in hostfile, modify, output
by eyepopslikeamosquito (Archbishop) on Dec 23, 2016 at 23:04 UTC

    From the perl 5.24.0 C sources, file win32.c:

    DllExport int win32_rename(const char *oname, const char *newname) { char szOldName[MAX_PATH+1]; BOOL bResult; DWORD dwFlags = MOVEFILE_COPY_ALLOWED; dTHX; if (stricmp(newname, oname)) dwFlags |= MOVEFILE_REPLACE_EXISTING; strcpy(szOldName, PerlDir_mapA(oname)); bResult = MoveFileExA(szOldName,PerlDir_mapA(newname), dwFlags); if (!bResult) { DWORD err = GetLastError(); switch (err) { case ERROR_BAD_NET_NAME: case ERROR_BAD_NETPATH: case ERROR_BAD_PATHNAME: case ERROR_FILE_NOT_FOUND: case ERROR_FILENAME_EXCED_RANGE: case ERROR_INVALID_DRIVE: case ERROR_NO_MORE_FILES: case ERROR_PATH_NOT_FOUND: errno = ENOENT; break; case ERROR_DISK_FULL: errno = ENOSPC; break; case ERROR_NOT_ENOUGH_QUOTA: errno = EDQUOT; break; default: errno = EACCES; break; } return -1; } return 0; }
    we see that the Perl rename function on Windows is implemented using the Win32 MoveFileEx function.

    Here is a standalone C program using the Win32 MoveFileEx function:

    // movetest.cpp // compile with: CL /W3 /MD movetest.cpp // example run: movetest fromfile tofile #include <windows.h> #include <stdio.h> int main(int argc, char* argv[]) { if (argc != 3) { fprintf(stderr, "usage: movetest file1 file2\n"); return 1; } char* from = argv[1]; char* to = argv[2]; fprintf(stderr, "move '%s' to '%s'...", from, to); if (!MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING)) { fprintf(stderr, "failed: error=%lu\n", (unsigned long)GetLastErr +or()); return 2; } fprintf(stderr, "done.\n"); return 0; }
    After compiling, you can run with:
    movetest newfile.txt originalfile.txt
    which overwrites the original file even if it already exists (if you have permission to do so).

    Well, it's pleasing to see that Perl is doing the rename via a single Win32 MoveFileEx function call in preference to a DeleteFile followed by a MoveFile (which would have no chance of being atomic). However, the jury seems to be out on how truly atomic Windows rename is. After reading this stackoverflow question I'm still confused. Alternatives to MoveFileEx appear to be ReplaceFile and MoveFileTransacted.

    Via brute force search of the perl 5.24.0 source code, I further noticed that MoveFileEx is also available to Perl code via the Win32API::File module. In the latest Perl distribution, Win32API::File::MoveFileEx is called by ExtUtils::Install.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1178321]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (5)
As of 2024-04-19 10:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found