Index: nsinstall.c =================================================================== RCS file: /cvsroot/buildtools/windows/source/shmsdos/nsinstall.c,v retrieving revision 1.1 diff -u2 -r1.1 nsinstall.c --- nsinstall.c +++ nsinstall.c @@ -35,4 +35,8 @@ WIN32_FIND_DATA *fileData, void *arg); +typedef BOOL (*CreateHardLinkFn)( + LPCSTR, + LPCSTR, + LPSECURITY_ATTRIBUTES); static int shellCp (char **pArgv); @@ -45,5 +49,12 @@ char *dstFileName, DWORD dstFileAttributes, int force, int recursive); +char *MoveToTemp(const char * filename); +BOOL NoCreateHardLink( + LPCSTR lpFileName, + LPCSTR lpExistingFileName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes){ + return FALSE; +}; /* changes all forward slashes in token to back slashes */ void changeForwardSlashesTpBackSlashes ( char *arg ) @@ -237,4 +248,51 @@ ) { + HANDLE hSrc, hDst; + HINSTANCE hInstLib; + BY_HANDLE_FILE_INFORMATION hSrcInfo, hDstInfo; + CreateHardLinkFn CreateHardLinkA; + char *backupFileName = 0; + if (srcFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + fprintf(stderr, "nsinstall: %s is a directory\n", + srcFileName); + return FALSE; + } + hDst = CreateFile(dstFileName, 0, 0, 0, OPEN_EXISTING, 0, 0); + if (hDst != INVALID_HANDLE_VALUE) { + hSrc = CreateFile(srcFileName, 0, 0, 0, OPEN_EXISTING, 0, 0); + GetFileInformationByHandle(hSrc, &hSrcInfo); + GetFileInformationByHandle(hDst, &hDstInfo); + CloseHandle(hSrc); + CloseHandle(hDst); + if ( hSrcInfo.dwVolumeSerialNumber == hDstInfo.dwVolumeSerialNumber + && hSrcInfo.nFileIndexHigh == hDstInfo.nFileIndexHigh + && hSrcInfo.nFileIndexLow == hDstInfo.nFileIndexLow + ) { + return TRUE; + } + backupFileName = MoveToTemp(dstFileName); + } + hInstLib = LoadLibrary("kernel32"); + CreateHardLinkA = (CreateHardLinkFn)GetProcAddress(hInstLib, "CreateHardLinkA"); + if (!CreateHardLinkA) + CreateHardLinkA = NoCreateHardLink; +#if 0 + if ( + !CreateHardLinkA(dstFileName, srcFileName, NULL) + && !CopyFile(srcFileName, dstFileName, FALSE) + ) +#else + if (!CreateHardLinkA(dstFileName, srcFileName, NULL) && + !CopyFile(srcFileName, dstFileName, FALSE)) +#endif + { + if (backupFileName) { + MoveFile(dstFileName, backupFileName); + free(backupFileName); + } + fprintf(stderr, "nsinstall: cannot copy %s to %s: [%d] %s\n", + srcFileName, dstFileName, GetLastError(), sh_GetLastErrorMessage()); + return FALSE; + } if (dstFileAttributes != 0xFFFFFFFF) { if ((dstFileAttributes & FILE_ATTRIBUTE_READONLY) && force) { @@ -243,15 +301,7 @@ } } - - if (srcFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - fprintf(stderr, "nsinstall: %s is a directory\n", - srcFileName); - return FALSE; - } else { - if (!CopyFile(srcFileName, dstFileName, FALSE)) { - fprintf(stderr, "nsinstall: cannot copy %s to %s: %s\n", - srcFileName, dstFileName, sh_GetLastErrorMessage()); - return FALSE; - } + if (backupFileName) { + DeleteFile(backupFileName); + free(backupFileName); } return TRUE; @@ -695,3 +745,29 @@ FindClose(hSearch); return retVal; +} + +/*limit for backup names:*/ +#define TOL 1000 +/*length of longest backup name:*/ +#define TLG 3 +/*length for use in sprintf:*/ +#define TLS "3" +char *MoveToTemp(const char * filename) +{ + const int length = strlen(filename); + char * newFilename = malloc(length + 2 + TLG); + char * number = newFilename + length + 1; + int count = 0; + if (!newFilename) + return FALSE; + memcpy(newFilename, filename, length); + newFilename[length] = '.'; + while (++count < TOL) { + sprintf(number, "%0" TLS "d", count); + if (MoveFile(filename, newFilename)) { + return newFilename; + } + } + free(newFilename); + return 0; } Index: nsinstall.mak =================================================================== RCS file: /cvsroot/buildtools/windows/source/shmsdos/nsinstall.mak,v retrieving revision 1.1 diff -u2 -r1.1 nsinstall.mak