OSDN Git Service

Throughout, eliminate third argument to path_conv and use new PC_* constants
authorcgf <cgf>
Mon, 17 Jul 2000 19:18:21 +0000 (19:18 +0000)
committercgf <cgf>
Mon, 17 Jul 2000 19:18:21 +0000 (19:18 +0000)
for second argument.
* path.h: Generalize SYMLINK_* constants to PC_*.
(path_conv): Create a new method.  Fold third argument into second.
* dll_init.cc (dll_list::alloc): Try harder to find space to allocate dll
struct.
(dll_dllcrt0): Don't check sanity if we've already called dll_crt0.
* path.cc (path_conv::check): Don't check for a null or empty path unless
specifically told with a flag setting.
(check_null_empty_path): New function, adapted from macro.
* syscalls.cc (_rename): Use already-determined file attributes rather than
checking again.
* lib/cygwin/cygwin_attach.dll.c (cygwin_attach_dll): Use a static per_process
structure since this is apparently supposed to be zeroed.
* lib/cygwin_crt0.c (cygwin_crt0): Zero per_process structure sent to older
DLLs.

15 files changed:
winsup/cygwin/ChangeLog
winsup/cygwin/dcrt0.cc
winsup/cygwin/dir.cc
winsup/cygwin/dlfcn.cc
winsup/cygwin/dll_init.cc
winsup/cygwin/environ.cc
winsup/cygwin/fhandler.cc
winsup/cygwin/fhandler_raw.cc
winsup/cygwin/lib/cygwin_attach_dll.c
winsup/cygwin/lib/cygwin_crt0.c
winsup/cygwin/path.cc
winsup/cygwin/path.h
winsup/cygwin/security.cc
winsup/cygwin/spawn.cc
winsup/cygwin/syscalls.cc

index aefc514..c62e309 100644 (file)
@@ -1,3 +1,22 @@
+Mon Jul 17 14:57:53 2000  Christopher Faylor <cgf@cygnus.com>
+
+       Throughout, eliminate third argument to path_conv and use new PC_*
+       constants for second argument.
+       * path.h: Generalize SYMLINK_* constants to PC_*.
+       (path_conv): Create a new method.  Fold third argument into second.
+       * dll_init.cc (dll_list::alloc): Try harder to find space to allocate
+       dll struct.
+       (dll_dllcrt0): Don't check sanity if we've already called dll_crt0.
+       * path.cc (path_conv::check): Don't check for a null or empty path
+       unless specifically told with a flag setting.
+       (check_null_empty_path): New function, adapted from macro.
+       * syscalls.cc (_rename): Use already-determined file attributes rather
+       than checking again.
+       * lib/cygwin/cygwin_attach.dll.c (cygwin_attach_dll): Use a static
+       per_process structure since this is apparently supposed to be zeroed.
+       * lib/cygwin_crt0.c (cygwin_crt0): Zero per_process structure sent to
+       older DLLs.
+
 Mon Jul 17 19:39:00 2000  Corinna Vinschen <corinna@vinschen.de>
 
        Patch suggested by Eric Fifer <EFifer@sanwaint.com>
index 0b6c701..283c2f3 100644 (file)
@@ -735,26 +735,19 @@ dll_crt0_1 ()
 /* Initialize uid, gid. */
   uinfo_init ();
 
-  /* beyond this we only do for cygwin apps or dlls */
-  if (dynamically_loaded)
-    {
-      cygwin_finished_initializing = 1;
-      return;
-    }
-
   /* Initialize signal/subprocess handling. */
   sigproc_init ();
 
   /* Connect to tty. */
   tty_init ();
 
+  /* Set up standard fds in file descriptor table. */
+  hinfo_init ();
+
   if (user_data->premain[0])
     for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
       user_data->premain[i] (argc, argv);
 
-  /* Set up standard fds in file descriptor table. */
-  hinfo_init ();
-
   /* Scan the command line and build argv.  Expand wildcards if not
      called from another cygwin process. */
   build_argv (line, argv, argc,
@@ -772,11 +765,6 @@ dll_crt0_1 ()
   /* Set up __progname for getopt error call. */
   __progname = argv[0];
 
-  /* Flush signals and ensure that signal thread is up and running. Can't
-     do this for noncygwin case since the signal thread is blocked due to
-     LoadLibrary serialization. */
-  sig_send (NULL, __SIGFLUSH);
-
   cygwin_finished_initializing = 1;
   /* Call init of loaded dlls. */
   dlls.init ();
@@ -788,6 +776,17 @@ dll_crt0_1 ()
 
   debug_printf ("user_data->main %p", user_data->main);
 
+  if (dynamically_loaded)
+    {
+      set_errno (0);
+      return;
+    }
+
+  /* Flush signals and ensure that signal thread is up and running. Can't
+     do this for noncygwin case since the signal thread is blocked due to
+     LoadLibrary serialization. */
+  sig_send (NULL, __SIGFLUSH);
+
   set_errno (0);
 
   if (user_data->main)
index 944313c..1b40906 100644 (file)
@@ -59,7 +59,7 @@ opendir (const char *dirname)
   DIR *res = 0;
   struct stat statbuf;
 
-  path_conv real_dirname (dirname, SYMLINK_FOLLOW, 1);
+  path_conv real_dirname (dirname, PC_SYM_FOLLOW | PC_FULL);
 
   if (real_dirname.error)
     {
@@ -286,7 +286,7 @@ mkdir (const char *dir, mode_t mode)
 {
   int res = -1;
 
-  path_conv real_dir (dir, SYMLINK_NOFOLLOW);
+  path_conv real_dir (dir, PC_SYM_NOFOLLOW);
 
   if (real_dir.error)
     {
@@ -318,7 +318,7 @@ rmdir (const char *dir)
 {
   int res = -1;
 
-  path_conv real_dir (dir, SYMLINK_NOFOLLOW);
+  path_conv real_dir (dir, PC_SYM_NOFOLLOW);
 
   if (real_dir.error)
     {
index 40931f2..cb89edf 100644 (file)
@@ -145,7 +145,7 @@ get_full_path_of_dll (const char* str)
      to resolve symlinks etc so that win32 API finds the underlying file.  */
   if (ret)
     {
-      path_conv real_filename (ret, SYMLINK_FOLLOW, 1);
+      path_conv real_filename (ret, PC_SYM_FOLLOW | PC_FULL);
       if (real_filename.error)
        ret = 0;
       else
index 8f9f434..f525a10 100644 (file)
@@ -106,43 +106,46 @@ dll_list::alloc (HINSTANCE h, per_process *p, dll_type type)
       return d;                /* Return previously allocated pointer. */
     }
 
+  SYSTEM_INFO s1;
+  GetSystemInfo (&s1);
+
   int i;
   void *s = p->bss_end;
+  DWORD n;
   MEMORY_BASIC_INFORMATION m;
   /* Search for space after the DLL */
-  for (i = 0; i <= RETRIES; i++)
+  for (i = 0; i <= RETRIES; i++, s = (char *) m.BaseAddress + m.RegionSize)
     {
       if (!VirtualQuery (s, &m, sizeof (m)))
        return NULL;    /* Can't do it. */
       if (m.State == MEM_FREE)
-       break;          /* Found some free space */
-      s = (char *) m.BaseAddress + m.RegionSize;
+       {
+         /* Couldn't find any.  Uh oh.  FIXME: Issue an error? */
+         if (i == RETRIES)
+           return NULL;        /* Oh well.  Couldn't locate free space. */
+
+         /* Ensure that this is rounded to the nearest page boundary.
+            FIXME: Should this be ensured by VirtualQuery? */
+         n = (DWORD) m.BaseAddress;
+         DWORD r = n % s1.dwAllocationGranularity;
+
+         if (r)
+           n = ((n - r) + s1.dwAllocationGranularity);
+
+         /* First reserve the area of memory, then commit it. */
+         if (VirtualAlloc ((void *) n, sizeof (dll), MEM_RESERVE, PAGE_READWRITE))
+           d = (dll *) VirtualAlloc ((void *) n, sizeof (dll), MEM_COMMIT,
+                                     PAGE_READWRITE);
+         if (d)
+           break;
+       }
     }
 
-  /* Couldn't find any.  Uh oh.  FIXME: Issue an error? */
-  if (i == RETRIES)
-    return NULL;       /* Oh well.  Couldn't locate free space. */
-
-  SYSTEM_INFO s1;
-  GetSystemInfo (&s1);
-
-  /* Ensure that this is rounded to the nearest page boundary.
-     FIXME: Should this be ensured by VirtualQuery? */
-  DWORD n = (DWORD) m.BaseAddress;
-  DWORD r = n % s1.dwAllocationGranularity;
-
-  if (r)
-    n = ((n - r) + s1.dwAllocationGranularity);
-
-  /* First reserve the area of memory, then commit it. */
-  if (VirtualAlloc ((void *) n, sizeof (dll), MEM_RESERVE, PAGE_READWRITE))
-    d = (dll *) VirtualAlloc ((void *) n, sizeof (dll), MEM_COMMIT, PAGE_READWRITE);
-
   /* Did we succeed? */
   if (d == NULL)
     {                  /* Nope. */
 #ifdef DEBUGGING
-      system_printf ("VirtualAlloc failed for %p, %E", n);
+      system_printf ("VirtualAlloc failed for %E");
 #endif
       __seterrno ();
       return NULL;
@@ -330,8 +333,7 @@ dll_dllcrt0 (HMODULE h, per_process *p)
   /* Partially initialize Cygwin guts for non-cygwin apps. */
   if (dynamically_loaded && user_data->magic_biscuit == 0)
     dll_crt0 (p);
-
-  if (p)
+  else
     check_sanity_and_sync (p);
 
   dll_type type;
index b536007..7c236df 100644 (file)
@@ -259,12 +259,13 @@ setenv (const char *name, const char *value, int rewrite)
 extern "C" void
 unsetenv (const char *name)
 {
-  register char **P;
+  register char **e;
   int offset;
 
   while (my_findenv (name, &offset))   /* if set multiple times */
-    for (P = &environ[offset];; ++P)
-      if (!(*P = *(P + 1)))
+    /* Move up the rest of the array */
+    for (e = environ + offset; ; e++)
+      if (!(*e = *(e + 1)))
        break;
 }
 
index 04b4fb3..35da0d8 100644 (file)
@@ -1179,7 +1179,8 @@ fhandler_disk_file::open (const char *path, int flags, mode_t mode)
   syscall_printf ("(%s, %p)", path, flags);
 
   /* O_NOSYMLINK is an internal flag for implementing lstat, nothing more. */
-  path_conv real_path (path, (flags & O_NOSYMLINK) ? SYMLINK_NOFOLLOW:SYMLINK_FOLLOW);
+  path_conv real_path (path, (flags & O_NOSYMLINK) ?
+                            PC_SYM_NOFOLLOW : PC_SYM_FOLLOW);
 
   if (real_path.error &&
       (flags & O_NOSYMLINK || real_path.error != ENOENT || !(flags & O_CREAT)))
index e34151b..e2703c1 100644 (file)
@@ -132,7 +132,7 @@ fhandler_dev_raw::de_linearize (const char *buf, const char *unix_name,
 int
 fhandler_dev_raw::open (const char *path, int flags, mode_t)
 {
-  path_conv real_path (path, SYMLINK_IGNORE);
+  path_conv real_path (path, PC_SYM_IGNORE);
   int ret;
 
   set_name (path, real_path.get_win32 ());
index 440cace..1791a4b 100644 (file)
@@ -17,7 +17,7 @@ details. */
 int
 cygwin_attach_dll (HMODULE h, MainFunc f)
 {
-  struct per_process u;
+  static struct per_process u;
   (void) _cygwin_crt0_common (f, &u);
 
   /* jump into the dll. */
index 785d9f1..0d96178 100644 (file)
@@ -25,6 +25,7 @@ cygwin_crt0 (MainFunc f)
   else                 /* Older DLL.  Provide a per_process */
     {
       u = (struct per_process *) alloca (sizeof (*u));
+      memset (u, 0, sizeof (u));
       (void) _cygwin_crt0_common (f, u);
     }
   dll_crt0__FP11per_process (u);       /* Jump into the dll, never to return */
index 3150ebf..fb50a45 100644 (file)
@@ -182,8 +182,8 @@ path_prefix_p_ (const char *path1, const char *path2, int len1)
 */
 
 void
-path_conv::check (const char *src, symlink_follow follow_mode,
-                 int use_full_path, const suffix_info *suffixes)
+path_conv::check (const char *src, unsigned opt,
+                 const suffix_info *suffixes)
 {
   /* This array is used when expanding symlinks.  It is MAX_PATH * 2
      in length so that we can hold the expanded symlink plus a
@@ -195,10 +195,12 @@ path_conv::check (const char *src, symlink_follow follow_mode,
 
   char *rel_path, *full_path;
 
-  if ((error = check_null_empty_path (src)))
+  if (!(opt & PC_NULLEMPTY))
+    error = 0;
+  else if ((error = check_null_empty_path (src)))
     return;
 
-  if (use_full_path)
+  if (opt & PC_FULL)
     rel_path = path_buf, full_path = this->path;
   else
     rel_path = this->path, full_path = path_buf;
@@ -235,7 +237,7 @@ path_conv::check (const char *src, symlink_follow follow_mode,
       if (full_path[0] && full_path[1] == ':' && full_path[2] == '\0')
        strcat (full_path, "\\");
 
-      if (follow_mode == SYMLINK_IGNORE)
+      if (opt & PC_SYM_IGNORE)
        {
          fileattr = GetFileAttributesA (path);
          goto out;
@@ -297,11 +299,11 @@ path_conv::check (const char *src, symlink_follow follow_mode,
             these operations again on the newly derived path. */
          else if (len > 0)
            {
-             if (component == 0 && follow_mode != SYMLINK_FOLLOW)
+             if (component == 0 && !(opt & PC_SYM_FOLLOW))
                {
                  set_symlink (); // last component of path is a symlink.
                  fileattr = sym.fileattr;
-                 if (follow_mode == SYMLINK_CONTENTS)
+                 if (opt & PC_SYM_CONTENTS)
                      strcpy (path, sym.contents);
                  goto fillin;
                }
@@ -370,7 +372,7 @@ path_conv::check (const char *src, symlink_follow follow_mode,
 fillin:
   if (sym.known_suffix)
     known_suffix = this->path + (sym.known_suffix - path_copy);
-  else if (sym.ext_here && follow_mode != SYMLINK_CONTENTS)
+  else if (sym.ext_here && !(opt & PC_SYM_CONTENTS))
     {
       known_suffix = strchr (this->path, '\0');
       strcpy (known_suffix, sym.ext_here);
@@ -510,7 +512,7 @@ get_device_number (const char *name, int &unit, BOOL from_conv)
       else if (! from_conv)
        devn = get_raw_device_number (name - 5,
                                      path_conv (name - 5,
-                                                SYMLINK_IGNORE).get_win32 (),
+                                                PC_SYM_IGNORE).get_win32 (),
                                      unit);
     }
   else if (deveqn ("com", 3) && (unit = digits (name + 3)) >= 0)
@@ -1975,7 +1977,7 @@ symlink (const char *topath, const char *frompath)
   HANDLE h;
   int res = -1;
 
-  path_conv win32_path (frompath, SYMLINK_NOFOLLOW);
+  path_conv win32_path (frompath, PC_SYM_NOFOLLOW);
   if (win32_path.error)
     {
       set_errno (win32_path.error);
@@ -2221,7 +2223,7 @@ int
 readlink (const char *path, char *buf, int buflen)
 {
   extern suffix_info stat_suffixes[];
-  path_conv pathbuf (path, SYMLINK_CONTENTS, 0, stat_suffixes);
+  path_conv pathbuf (path, PC_SYM_CONTENTS, stat_suffixes);
 
   if (pathbuf.error)
     {
@@ -2492,7 +2494,7 @@ extern "C"
 int
 cygwin_conv_to_win32_path (const char *path, char *win32_path)
 {
-  path_conv p (path, SYMLINK_FOLLOW, 0);
+  path_conv p (path, PC_SYM_FOLLOW);
   if (p.error)
     {
       set_errno (p.error);
@@ -2507,7 +2509,7 @@ extern "C"
 int
 cygwin_conv_to_full_win32_path (const char *path, char *win32_path)
 {
-  path_conv p (path, SYMLINK_FOLLOW, 1);
+  path_conv p (path, PC_SYM_FOLLOW | PC_FULL);
   if (p.error)
     {
       set_errno (p.error);
@@ -2548,7 +2550,7 @@ realpath (const char *path, char *resolved)
 {
   int err;
 
-  path_conv real_path (path, SYMLINK_FOLLOW, 1);
+  path_conv real_path (path, PC_SYM_FOLLOW | PC_FULL);
 
   if (real_path.error)
     err = real_path.error;
@@ -2807,3 +2809,16 @@ strcasestr (const char *searchee, const char *lookfor)
 
   return NULL;
 }
+
+int __stdcall
+check_null_empty_path (const char *name)
+{
+  MEMORY_BASIC_INFORMATION m;
+  if (!name || !VirtualQuery (name, &m, sizeof (m)) || (m.State != MEM_COMMIT))
+    return EFAULT;
+
+  if (!*name)
+    return ENOENT;
+
+  return 0;
+}
index 76ab208..a2b647b 100644 (file)
@@ -15,17 +15,21 @@ struct suffix_info
   suffix_info (const char *s, int addit = 0) {name = s, addon = addit;}
 };
 
-enum symlink_follow
+enum pathconv_arg
 {
-  SYMLINK_FOLLOW,
-  SYMLINK_NOFOLLOW,
-  SYMLINK_IGNORE,
-  SYMLINK_CONTENTS
+  PC_SYM_FOLLOW                = 0x0001,
+  PC_SYM_NOFOLLOW      = 0x0002,
+  PC_SYM_IGNORE                = 0x0004,
+  PC_SYM_CONTENTS      = 0x0008,
+  PC_FULL              = 0x0010,
+  PC_NULLEMPTY         = 0x0020
 };
 
+#define PC_NONULLEMPTY -1
+
 #include <sys/mount.h>
 
-enum
+enum path_types
 {
   PATH_NOTHING = 0,
   PATH_SYMLINK = MOUNT_SYMLINK,
@@ -36,7 +40,6 @@ enum
   PATH_HASACLS = 0x80000000
 };
 
-
 class path_conv
 {
   char path[MAX_PATH];
@@ -65,12 +68,19 @@ class path_conv
 
   DWORD fileattr;
 
-  void check (const char *src, symlink_follow follow_mode = SYMLINK_FOLLOW,
-             int use_full_path = 0, const suffix_info *suffixes = NULL);
-  path_conv (const char *src, symlink_follow follow_mode = SYMLINK_FOLLOW,
-            int use_full_path = 0, const suffix_info *suffixes = NULL)
+  void check (const char *src, unsigned opt = PC_SYM_FOLLOW,
+             const suffix_info *suffixes = NULL);
+
+  path_conv (int, const char *src, unsigned opt = PC_SYM_FOLLOW,
+            const suffix_info *suffixes = NULL)
+  {
+    check (src, opt, suffixes);
+  }
+
+  path_conv (const char *src, unsigned opt = PC_SYM_FOLLOW,
+            const suffix_info *suffixes = NULL)
   {
-    check (src, follow_mode, use_full_path, suffixes);
+    check (src, opt | PC_NULLEMPTY, suffixes);
   }
 
   path_conv (): path_flags (0), known_suffix (NULL), error (0), devn (0), unit (0), fileattr (0xffffffff) {path[0] = '\0';}
@@ -96,10 +106,9 @@ extern suffix_info std_suffixes[];
 
 int __stdcall get_device_number (const char *name, int &unit, BOOL from_conv = FALSE);
 int __stdcall slash_unc_prefix_p (const char *path);
+int __stdcall check_null_empty_path (const char *name);
 
 /* Common macros for checking for invalid path names */
-#define check_null_empty_path(src) \
-  (!(src) ? EFAULT : *(src) ? 0 : ENOENT)
 
 #define check_null_empty_path_errno(src) \
 ({ \
index 26fc2d1..29012bf 100644 (file)
@@ -1570,7 +1570,7 @@ int
 acl_worker (const char *path, int cmd, int nentries, aclent_t *aclbufp,
             int nofollow)
 {
-  path_conv real_path (path, nofollow ? SYMLINK_NOFOLLOW : SYMLINK_FOLLOW, 1);
+  path_conv real_path (path, (nofollow ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW) | PC_FULL);
   if (real_path.error)
     {
       set_errno (real_path.error);
index ca22436..063e99f 100644 (file)
@@ -43,7 +43,7 @@ perhaps_suffix (const char *prog, path_conv &buf)
   char *ext;
 
   debug_printf ("prog '%s'", prog);
-  buf.check (prog, SYMLINK_FOLLOW, 1, std_suffixes);
+  buf.check (prog, PC_SYM_FOLLOW | PC_FULL, std_suffixes);
 
   if (buf.file_attributes () & FILE_ATTRIBUTE_DIRECTORY)
     ext = NULL;
index 61479aa..b237f82 100644 (file)
@@ -47,7 +47,7 @@ _unlink (const char *ourname)
 {
   int res = -1;
 
-  path_conv win32_name (ourname, SYMLINK_NOFOLLOW, 1);
+  path_conv win32_name (ourname, PC_SYM_NOFOLLOW | PC_FULL);
 
   if (win32_name.error)
     {
@@ -494,8 +494,8 @@ int
 _link (const char *a, const char *b)
 {
   int res = -1;
-  path_conv real_a (a, SYMLINK_NOFOLLOW);
-  path_conv real_b (b, SYMLINK_NOFOLLOW);
+  path_conv real_a (a, PC_SYM_NOFOLLOW);
+  path_conv real_b (b, PC_SYM_NOFOLLOW);
 
   if (real_a.error)
     {
@@ -658,18 +658,21 @@ rel2abssd (PSECURITY_DESCRIPTOR psd_rel, PSECURITY_DESCRIPTOR psd_abs,
  * systems, it is only a stub that always returns zero.
  */
 static int
-chown_worker (const char *name, symlink_follow fmode, uid_t uid, gid_t gid)
+chown_worker (const char *name, unsigned fmode, uid_t uid, gid_t gid)
 {
   int res;
   uid_t old_uid;
   gid_t old_gid;
 
+  if (check_null_empty_path_errno(name))
+    return -1;
+
   if (os_being_run != winNT)    // real chown only works on NT
     res = 0;                   // return zero (and do nothing) under Windows 9x
   else
     {
       /* we need Win32 path names because of usage of Win32 API functions */
-      path_conv win32_path (name, fmode);
+      path_conv win32_path (PC_NONULLEMPTY, name, fmode);
 
       if (win32_path.error)
        {
@@ -717,7 +720,7 @@ chown_worker (const char *name, symlink_follow fmode, uid_t uid, gid_t gid)
 
 done:
   syscall_printf ("%d = %schown (%s,...)",
-                  res, fmode == SYMLINK_IGNORE ? "l" : "", name);
+                  res, (fmode & PC_SYM_IGNORE) ? "l" : "", name);
   return res;
 }
 
@@ -725,14 +728,14 @@ extern "C"
 int
 chown (const char * name, uid_t uid, gid_t gid)
 {
-  return chown_worker (name, SYMLINK_FOLLOW, uid, gid);
+  return chown_worker (name, PC_SYM_FOLLOW, uid, gid);
 }
 
 extern "C"
 int
 lchown (const char * name, uid_t uid, gid_t gid)
 {
-  return chown_worker (name, SYMLINK_IGNORE, uid, gid);
+  return chown_worker (name, PC_SYM_IGNORE, uid, gid);
 }
 
 extern "C"
@@ -757,7 +760,7 @@ fchown (int fd, uid_t uid, gid_t gid)
 
   syscall_printf ("fchown (%d,...): calling chown_worker (%s,FOLLOW,...)",
                   fd, path);
-  return chown_worker (path, SYMLINK_FOLLOW, uid, gid);
+  return chown_worker (path, PC_SYM_FOLLOW, uid, gid);
 }
 
 /* umask: POSIX 5.3.3.1 */
@@ -1005,7 +1008,7 @@ stat_worker (const char *caller, const char *name, struct stat *buf,
 
   debug_printf ("%s (%s, %p)", caller, name, buf);
 
-  path_conv real_path (name, nofollow ? SYMLINK_NOFOLLOW : SYMLINK_FOLLOW, 1,
+  path_conv real_path (name, (nofollow ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW) | PC_FULL,
                       stat_suffixes);
 
   if (real_path.error)
@@ -1193,7 +1196,7 @@ _rename (const char *oldpath, const char *newpath)
 {
   int res = 0;
 
-  path_conv real_old (oldpath, SYMLINK_NOFOLLOW);
+  path_conv real_old (oldpath, PC_SYM_NOFOLLOW);
 
   if (real_old.error)
     {
@@ -1202,7 +1205,7 @@ _rename (const char *oldpath, const char *newpath)
       return -1;
     }
 
-  path_conv real_new (newpath, SYMLINK_NOFOLLOW);
+  path_conv real_new (newpath, PC_SYM_NOFOLLOW);
 
   if (real_new.error)
     {
@@ -1218,20 +1221,18 @@ _rename (const char *oldpath, const char *newpath)
       return -1;
     }
 
-  int oldatts = GetFileAttributesA (real_old.get_win32 ());
-  int newatts = GetFileAttributesA (real_new.get_win32 ());
-
-  if (oldatts == -1) /* file to move doesn't exist */
+  if (real_old.file_attributes () == (DWORD) -1) /* file to move doesn't exist */
     {
        syscall_printf ("file to move doesn't exist");
        return (-1);
     }
 
-  if (newatts != -1 && newatts & FILE_ATTRIBUTE_READONLY)
+  if (real_new.file_attributes () != (DWORD) -1 &&
+      real_new.file_attributes () & FILE_ATTRIBUTE_READONLY)
     {
       /* Destination file exists and is read only, change that or else
         the rename won't work. */
-      SetFileAttributesA (real_new.get_win32 (), newatts & ~ FILE_ATTRIBUTE_READONLY);
+      SetFileAttributesA (real_new.get_win32 (), real_new.file_attributes () & ~ FILE_ATTRIBUTE_READONLY);
     }
 
   if (!MoveFile (real_old.get_win32 (), real_new.get_win32 ()))
@@ -1277,7 +1278,7 @@ done:
   if (res == 0)
     {
       /* make the new file have the permissions of the old one */
-      SetFileAttributesA (real_new.get_win32 (), oldatts);
+      SetFileAttributesA (real_new.get_win32 (), real_old.file_attributes ());
     }
 
   syscall_printf ("%d = rename (%s, %s)", res, real_old.get_win32 (),