[PATCH STABLE] implement nlinks() for _WIN32 in osutil.c (issue1922)

Aaron Cohen aaron at assonance.org
Sat Jan 22 18:43:53 CST 2011


On Saturday, January 22, 2011, Adrian Buehlmann <adrian at cadifra.com>
>
> +       fh = CreateFile(name, 0,
> +                       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
> +                       NULL,
> +                       OPEN_EXISTING,
> +                       0,
> +                       NULL);

Question: Do you know if this goes through CreateFileA or CreateFileW?
Does it depend on the compilation environment or is the proper
preprocessor magic happening somewhere earlier? If it goes through
CreateFileA, what happens when you call nlinks on a file with
non-ascii chars in its name?


> +       if (fh == INVALID_HANDLE_VALUE) {
> +               PyErr_SetFromWindowsErrWithFilename(GetLastError(), name);
> +               goto bail;
> +       }
> +
> +       fi.nNumberOfLinks = 1000;
> +       if (!GetFileInformationByHandle(fh, &fi)) {
> +               PyErr_SetFromWindowsErrWithFilename(GetLastError(), name);
> +               goto bail;
> +       }
> +
> +       /*
> +       nNumberOfLinks is a DWORD, which is a 32 bit unsigned
> +       The return value is a Python int, which is signed
> +       */
> +       if (fi.nNumberOfLinks > (DWORD)PyInt_GetMax())
> +               n = PyInt_GetMax();
> +       else
> +               n = (long)fi.nNumberOfLinks;
> +       res = PyInt_FromLong(n);
> +bail:
> +       if (fh != INVALID_HANDLE_VALUE)
> +               CloseHandle(fh);
> +       PyMem_Free(name);
> +       return res;
> +}
>  #endif
>
>  static char osutil_doc[] = "Native operating system services.";
> @@ -528,6 +575,8 @@ static PyMethodDef methods[] = {
>         {"posixfile", (PyCFunction)posixfile, METH_VARARGS | METH_KEYWORDS,
>          "Open a file with POSIX-like semantics.\n"
>  "On error, this function may raise either a WindowsError or an IOError."},
> +       {"nlinks", nlinks, METH_VARARGS,
> +        "return number of hardlinks for the given file\n"},
>  #endif
>         {NULL, NULL}
>  };
> diff --git a/mercurial/posix.py b/mercurial/posix.py
> --- a/mercurial/posix.py
> +++ b/mercurial/posix.py
> @@ -23,6 +23,10 @@ def openhardlinks():
>      '''return true if it is safe to hold open file handles to hardlinks'''
>      return True
>
> +def nlinks(name):
> +    """return number of hardlinks for the given file"""
> +    return os.lstat(name).st_nlink
> +
>  def rcfiles(path):
>      rcs = [os.path.join(path, 'hgrc')]
>      rcdir = os.path.join(path, 'hgrc.d')
> diff --git a/mercurial/util.py b/mercurial/util.py
> --- a/mercurial/util.py
> +++ b/mercurial/util.py
> @@ -550,10 +550,6 @@ class path_auditor(object):
>          # want to add "foo/bar/baz" before checking if there's a "foo/.hg"
>          self.auditeddir.update(prefixes)
>
> -def nlinks(pathname):
> -    """Return number of hardlinks for the given file."""
> -    return os.lstat(pathname).st_nlink
> -
>  if hasattr(os, 'link'):
>      os_link = os.link
>  else:
> @@ -913,6 +909,8 @@ class opener(object):
>                      # shares if the file is open.
>                      fd = open(f)
>                      nlink = nlinks(f)
> +                    if nlink < 1:
> +                        nlink = 2 # force mktempcopy (issue1922)
>                      fd.close()
>              except (OSError, IOError):
>                  nlink = 0
> diff --git a/mercurial/win32.py b/mercurial/win32.py
> --- a/mercurial/win32.py
> +++ b/mercurial/win32.py
> @@ -41,10 +41,6 @@ def _getfileinfo(pathname):
>      finally:
>          fh.Close()
>
> -def nlinks(pathname):
> -    """Return number of hardlinks for the given file."""
> -    return _getfileinfo(pathname)[7]
> -
>  def samefile(fpath1, fpath2):
>      """Returns whether fpath1 and fpath2 refer to the same file. This is only
>      guaranteed to work for files, not directories."""
> diff --git a/mercurial/windows.py b/mercurial/windows.py
> --- a/mercurial/windows.py
> +++ b/mercurial/windows.py
> @@ -20,6 +20,13 @@ def posixfile(name, mode='r', buffering=
>          raise IOError(err.errno, '%s: %s' % (name, err.strerror))
>  posixfile.__doc__ = osutil.posixfile.__doc__
>
> +def nlinks(name):
> +    try:
> +        return osutil.nlinks(name)
> +    except WindowsError, err:
> +        raise OSError(err.errno, '%s: %s' % (name, err.strerror))
> +nlinks.__doc__ = osutil.nlinks.__doc__
> +
>  class winstdout(object):
>      '''stdout on windows misbehaves if sent through a pipe'''
>
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
>


More information about the Mercurial-devel mailing list