home *** CD-ROM | disk | FTP | other *** search
/ PC Extra Super CD 1998 January / PCPLUS131.iso / DJGPP / V2 / DJLSR201.ZIP / src / libc / ansi / stdio / _rename.c next >
Encoding:
C/C++ Source or Header  |  1996-10-25  |  3.2 KB  |  139 lines

  1. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  2. #include <libc/stubs.h>
  3. #include <stdio.h>
  4. #include <errno.h>
  5. #include <fcntl.h>
  6. #include <io.h>
  7. #include <go32.h>
  8. #include <dpmi.h>
  9. #include <libc/dosio.h>
  10.  
  11. int _rename(const char *old, const char *new)
  12. {
  13.   __dpmi_regs r;
  14.   int olen    = strlen(old) + 1;
  15.   int i;
  16.   int use_lfn = _USE_LFN;
  17.   char tempfile[FILENAME_MAX];
  18.   const char *orig = old;
  19.   int lfn_fd = -1;
  20.  
  21.   r.x.dx = __tb_offset;
  22.   r.x.di = __tb_offset + olen;
  23.   r.x.ds = r.x.es = __tb_segment;
  24.  
  25.   if (use_lfn)
  26.   {
  27.     /* Windows 95 bug: for some filenames, when you rename
  28.        file -> file~ (as in Emacs, to leave a backup), the
  29.        short 8+3 alias doesn't change, which effectively
  30.        makes OLD and NEW the same file.  We must rename
  31.        through a temporary file to work around this.  */
  32.  
  33.     char *pbase = 0, *p;
  34.     static char try_char[] = "abcdefghijklmnopqrstuvwxyz012345789";
  35.     int idx = sizeof(try_char)-1;
  36.  
  37.     /* Generate a temporary name.  Can't use `tmpnam', since $TMPDIR
  38.        might point to another drive, which will fail the DOS call.  */
  39.     strcpy(tempfile, old);
  40.     for (p = tempfile; *p; p++)    /* ensure temporary is on the same drive */
  41.       if (*p == '/' || *p == '\\' || *p == ':')
  42.     pbase = p;
  43.     if (pbase)
  44.       pbase++;
  45.     else
  46.       pbase = tempfile;
  47.     strcpy(pbase, "X$$djren$$.$$temp$$");
  48.  
  49.     do
  50.     {
  51.       if (idx <= 0)
  52.     return -1;
  53.       *pbase = try_char[--idx];
  54.     } while (_chmod(tempfile, 0) != -1);
  55.  
  56.     r.x.ax = 0x7156;
  57.     _put_path2(tempfile, olen);
  58.     _put_path(old);
  59.     __dpmi_int(0x21, &r);
  60.     if (r.x.flags & 1)
  61.     {
  62.       errno = __doserr_to_errno(r.x.ax);
  63.       return -1;
  64.     }
  65.  
  66.     /* Now create a file with the original name.  This will
  67.        ensure that NEW will always have a 8+3 alias
  68.        different from that of OLD.  (Seems to be required
  69.        when NameNumericTail in the Registry is set to 0.)  */
  70.     lfn_fd = _creat(old, 0);
  71.  
  72.     olen = strlen(tempfile) + 1;
  73.     old  = tempfile;
  74.     r.x.di = __tb_offset + olen;
  75.   }
  76.  
  77.   for (i=0; i<2; i++)
  78.   {
  79.     if(use_lfn)
  80.       r.x.ax = 0x7156;
  81.     else
  82.       r.h.ah = 0x56;
  83.     _put_path2(new, olen);
  84.     _put_path(old);
  85.     __dpmi_int(0x21, &r);
  86.     if(r.x.flags & 1)
  87.     {
  88.       if (r.x.ax == 5 && i == 0) /* access denied */
  89.     remove(new);         /* and try again */
  90.       else
  91.       {
  92.     errno = __doserr_to_errno(r.x.ax);
  93.  
  94.     /* Restore to original name if we renamed it to temporary.  */
  95.     if (use_lfn)
  96.     {
  97.       if (lfn_fd != -1)
  98.       {
  99.         _close (lfn_fd);
  100.         remove (orig);
  101.       }
  102.       _put_path2(orig, olen);
  103.       _put_path(tempfile);
  104.       r.x.ax = 0x7156;
  105.       __dpmi_int(0x21, &r);
  106.     }
  107.     return -1;
  108.       }
  109.     }
  110.     else
  111.       break;
  112.   }
  113.  
  114.   /* Success.  Delete the file possibly created to work
  115.      around the Windows 95 bug.  */
  116.   if (lfn_fd != -1)
  117.     return (_close (lfn_fd) == 0) ? remove (orig) : -1;
  118.   return 0;
  119. }
  120.  
  121. #ifdef TEST
  122.  
  123. #include <string.h>
  124.  
  125. int main(int argc, char *argv[])
  126. {
  127.   if (argc > 2)
  128.     {
  129.       printf ("%s -> %s: ", argv[1], argv[2]);
  130.       if (_rename (argv[1], argv[2]))
  131.     printf ("%s\n", strerror (errno));
  132.       else
  133.     printf ("Done\n");
  134.     }
  135.   return 0;
  136. }
  137.  
  138. #endif
  139.