From: k3040e4 AT c210 DOT edvz DOT uni-linz DOT ac DOT at (Oberhumer Markus) Message-Id: <199606301311.PAA09407@c210.edvz.uni-linz.ac.at> Subject: rename() problem in Win95 ? To: djgpp-workers AT delorie DOT com Date: Sun, 30 Jun 1996 15:11:50 -0200 (MET DST) Return-Read-To: markus DOT oberhumer AT jk DOT uni-linz DOT ac DOT at Content-Type: text Content-Length: 2862 =============================================================================== Markus F.X.J. Oberhumer Subject: rename() problem in Win95 ? To: djgpp-workers AT delorie DOT com =============================================================================== Some days ago I compiled Vim 4.2 (a vi clone) with djgpp v2. Everything works fine, and I've found this interresting code fragment in msdos.c. As I don't have Windows 95 I can't verify the claims herein, but maybe it proves useful as a patch for rename(). from vim-4.2/src/msdos.c: #ifdef DJGPP /* * djgpp_rename() works around a bug in rename (aka MoveFile) in * Windows 95: rename("foo.bar", "foo.bar~") will generate a * file whose shortfilename is "FOO.BAR" (its longfilename will * be correct: "foo.bar~"). Because a file can be accessed by * either its SFN or its LFN, "foo.bar" has effectively been * renamed to "foo.bar", which is not at all what was wanted. This * seems to happen only when renaming files with three-character * extensions by appending a suffix that does not include ".". * Windows NT gets it right, however, with an SFN of "FOO~1.BAR". * This works like win95rename in win32.c, but is a bit simpler. * * Like rename(), returns 0 upon success, non-zero upon failure. * Should probably set errno appropriately when errors occur. */ #undef rename int djgpp_rename(const char *OldFile, const char *NewFile) { char_u *TempFile; int retval; int fd; /* rename() works correctly without long file names, so use that */ if (!_use_lfn()) return rename(OldFile, NewFile); if ((TempFile = alloc((unsigned)(STRLEN(OldFile) + TMPNAMELEN))) == NULL) return -1; STRCPY(TempFile, OldFile); STRCPY(gettail(TempFile), TMPNAME1); if (rename(OldFile, TempFile)) retval = -1; else { /* now create an empty file called OldFile; this prevents * the operating system using OldFile as an alias (SFN) * if we're renaming within the same directory. For example, * we're editing a file called filename.asc.txt by its SFN, * filena~1.txt. If we rename filena~1.txt to filena~1.txt~ * (i.e., we're making a backup while writing it), the SFN * for filena~1.txt~ will be filena~1.txt, by default, which * will cause all sorts of problems later in buf_write. So, we * create an empty file called filena~1.txt and the system will have * to find some other SFN for filena~1.txt~, such as filena~2.txt */ if ((fd = open(OldFile, O_RDWR|O_CREAT|O_EXCL, 0444)) < 0) return -1; retval = rename(TempFile, NewFile); close(fd); vim_remove((char_u *)OldFile); } vim_free(TempFile); return retval; /* success */ } #endif