delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1996/06/30/09:17:18

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

===============================================================================
Markus F.X.J. Oberhumer <markus DOT oberhumer AT jk DOT uni-linz DOT ac DOT at>

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

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019