mercurial/pure/osutil.py
author Gábor Stefanik <gabor.stefanik@nng.com>
Wed, 12 Oct 2016 12:41:28 +0200
changeset 30192 509d29255c04
parent 29832 8656dcac4ce9
child 30317 ba2c04059317
permissions -rw-r--r--
tests: introduce tests for grafting through renames These cover all currently known cases of renames being grafted, or changes being grafted through renames. Right now, most of these cases are broken. Later patches in this series will make them behave correctly. The testcases heavily rely on each other, which would make it very difficult to separate them and add them one-by-one for each case fixed by a patch. Separating them should perhaps be a 4.1 task, if it doesn't slow down the tests too much. (Developed together with Pierre-Yves David)
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
8232
823f25b25dea pure/osutil: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 7704
diff changeset
     1
# osutil.py - pure Python version of osutil.c
823f25b25dea pure/osutil: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 7704
diff changeset
     2
#
823f25b25dea pure/osutil: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 7704
diff changeset
     3
#  Copyright 2009 Matt Mackall <mpm@selenic.com> and others
823f25b25dea pure/osutil: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 7704
diff changeset
     4
#
823f25b25dea pure/osutil: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 7704
diff changeset
     5
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9031
diff changeset
     6
# GNU General Public License version 2 or any later version.
8232
823f25b25dea pure/osutil: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 7704
diff changeset
     7
27338
810337ae1b76 osutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25645
diff changeset
     8
from __future__ import absolute_import
810337ae1b76 osutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25645
diff changeset
     9
27474
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
    10
import ctypes
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
    11
import ctypes.util
7704
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    12
import os
27474
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
    13
import socket
10651
5f091fc1bab7 style: use consistent variable names (*mod) with imports which would shadow
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10282
diff changeset
    14
import stat as statmod
27474
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
    15
import sys
7704
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    16
29600
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    17
from . import policy
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    18
modulepolicy = policy.policy
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    19
policynocffi = policy.policynocffi
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    20
7704
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    21
def _mode_to_kind(mode):
10651
5f091fc1bab7 style: use consistent variable names (*mod) with imports which would shadow
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10282
diff changeset
    22
    if statmod.S_ISREG(mode):
5f091fc1bab7 style: use consistent variable names (*mod) with imports which would shadow
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10282
diff changeset
    23
        return statmod.S_IFREG
5f091fc1bab7 style: use consistent variable names (*mod) with imports which would shadow
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10282
diff changeset
    24
    if statmod.S_ISDIR(mode):
5f091fc1bab7 style: use consistent variable names (*mod) with imports which would shadow
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10282
diff changeset
    25
        return statmod.S_IFDIR
5f091fc1bab7 style: use consistent variable names (*mod) with imports which would shadow
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10282
diff changeset
    26
    if statmod.S_ISLNK(mode):
5f091fc1bab7 style: use consistent variable names (*mod) with imports which would shadow
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10282
diff changeset
    27
        return statmod.S_IFLNK
5f091fc1bab7 style: use consistent variable names (*mod) with imports which would shadow
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10282
diff changeset
    28
    if statmod.S_ISBLK(mode):
5f091fc1bab7 style: use consistent variable names (*mod) with imports which would shadow
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10282
diff changeset
    29
        return statmod.S_IFBLK
5f091fc1bab7 style: use consistent variable names (*mod) with imports which would shadow
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10282
diff changeset
    30
    if statmod.S_ISCHR(mode):
5f091fc1bab7 style: use consistent variable names (*mod) with imports which would shadow
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10282
diff changeset
    31
        return statmod.S_IFCHR
5f091fc1bab7 style: use consistent variable names (*mod) with imports which would shadow
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10282
diff changeset
    32
    if statmod.S_ISFIFO(mode):
5f091fc1bab7 style: use consistent variable names (*mod) with imports which would shadow
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10282
diff changeset
    33
        return statmod.S_IFIFO
5f091fc1bab7 style: use consistent variable names (*mod) with imports which would shadow
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10282
diff changeset
    34
    if statmod.S_ISSOCK(mode):
5f091fc1bab7 style: use consistent variable names (*mod) with imports which would shadow
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10282
diff changeset
    35
        return statmod.S_IFSOCK
7704
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    36
    return mode
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    37
29600
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    38
def listdirpure(path, stat=False, skip=None):
7704
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    39
    '''listdir(path, stat=False) -> list_of_tuples
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    40
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    41
    Return a sorted list containing information about the entries
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    42
    in the directory.
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    43
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    44
    If stat is True, each element is a 3-tuple:
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    45
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    46
      (name, type, stat object)
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    47
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    48
    Otherwise, each element is a 2-tuple:
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    49
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    50
      (name, type)
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    51
    '''
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    52
    result = []
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    53
    prefix = path
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    54
    if not prefix.endswith(os.sep):
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    55
        prefix += os.sep
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    56
    names = os.listdir(path)
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    57
    names.sort()
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    58
    for fn in names:
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    59
        st = os.lstat(prefix + fn)
10651
5f091fc1bab7 style: use consistent variable names (*mod) with imports which would shadow
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10282
diff changeset
    60
        if fn == skip and statmod.S_ISDIR(st.st_mode):
7704
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    61
            return []
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    62
        if stat:
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    63
            result.append((fn, _mode_to_kind(st.st_mode), st))
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    64
        else:
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    65
            result.append((fn, _mode_to_kind(st.st_mode)))
30d1d313370b move mercurial.osutil to mercurial.pure.osutil
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
    66
    return result
8421
b6d0fa8c7685 posixfile: remove posixfile_nt and fix import bug in windows.py
Sune Foldager <cryo@cyanite.org>
parents: 8232
diff changeset
    67
29600
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    68
ffi = None
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    69
if modulepolicy not in policynocffi and sys.platform == 'darwin':
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    70
    try:
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    71
        from _osutil_cffi import ffi, lib
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    72
    except ImportError:
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    73
        if modulepolicy == 'cffi': # strict cffi import
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    74
            raise
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    75
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    76
if sys.platform == 'darwin' and ffi is not None:
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    77
    listdir_batch_size = 4096
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    78
    # tweakable number, only affects performance, which chunks
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    79
    # of bytes do we get back from getattrlistbulk
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    80
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    81
    attrkinds = [None] * 20 # we need the max no for enum VXXX, 20 is plenty
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    82
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    83
    attrkinds[lib.VREG] = statmod.S_IFREG
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    84
    attrkinds[lib.VDIR] = statmod.S_IFDIR
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    85
    attrkinds[lib.VLNK] = statmod.S_IFLNK
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    86
    attrkinds[lib.VBLK] = statmod.S_IFBLK
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    87
    attrkinds[lib.VCHR] = statmod.S_IFCHR
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    88
    attrkinds[lib.VFIFO] = statmod.S_IFIFO
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    89
    attrkinds[lib.VSOCK] = statmod.S_IFSOCK
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    90
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    91
    class stat_res(object):
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    92
        def __init__(self, st_mode, st_mtime, st_size):
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    93
            self.st_mode = st_mode
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    94
            self.st_mtime = st_mtime
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    95
            self.st_size = st_size
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    96
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    97
    tv_sec_ofs = ffi.offsetof("struct timespec", "tv_sec")
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    98
    buf = ffi.new("char[]", listdir_batch_size)
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
    99
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   100
    def listdirinternal(dfd, req, stat, skip):
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   101
        ret = []
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   102
        while True:
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   103
            r = lib.getattrlistbulk(dfd, req, buf, listdir_batch_size, 0)
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   104
            if r == 0:
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   105
                break
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   106
            if r == -1:
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   107
                raise OSError(ffi.errno, os.strerror(ffi.errno))
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   108
            cur = ffi.cast("val_attrs_t*", buf)
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   109
            for i in range(r):
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   110
                lgt = cur.length
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   111
                assert lgt == ffi.cast('uint32_t*', cur)[0]
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   112
                ofs = cur.name_info.attr_dataoffset
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   113
                str_lgt = cur.name_info.attr_length
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   114
                base_ofs = ffi.offsetof('val_attrs_t', 'name_info')
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   115
                name = str(ffi.buffer(ffi.cast("char*", cur) + base_ofs + ofs,
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   116
                           str_lgt - 1))
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   117
                tp = attrkinds[cur.obj_type]
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   118
                if name == "." or name == "..":
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   119
                    continue
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   120
                if skip == name and tp == statmod.S_ISDIR:
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   121
                    return []
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   122
                if stat:
29832
8656dcac4ce9 osutil: fix the bug on OS X when we return more in listdir
Maciej Fijalkowski <fijall@gmail.com>
parents: 29712
diff changeset
   123
                    mtime = cur.mtime.tv_sec
29600
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   124
                    mode = (cur.accessmask & ~lib.S_IFMT)| tp
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   125
                    ret.append((name, tp, stat_res(st_mode=mode, st_mtime=mtime,
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   126
                                st_size=cur.datalength)))
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   127
                else:
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   128
                    ret.append((name, tp))
29832
8656dcac4ce9 osutil: fix the bug on OS X when we return more in listdir
Maciej Fijalkowski <fijall@gmail.com>
parents: 29712
diff changeset
   129
                cur = ffi.cast("val_attrs_t*", int(ffi.cast("intptr_t", cur))
8656dcac4ce9 osutil: fix the bug on OS X when we return more in listdir
Maciej Fijalkowski <fijall@gmail.com>
parents: 29712
diff changeset
   130
                    + lgt)
29600
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   131
        return ret
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   132
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   133
    def listdir(path, stat=False, skip=None):
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   134
        req = ffi.new("struct attrlist*")
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   135
        req.bitmapcount = lib.ATTR_BIT_MAP_COUNT
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   136
        req.commonattr = (lib.ATTR_CMN_RETURNED_ATTRS |
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   137
                          lib.ATTR_CMN_NAME |
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   138
                          lib.ATTR_CMN_OBJTYPE |
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   139
                          lib.ATTR_CMN_ACCESSMASK |
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   140
                          lib.ATTR_CMN_MODTIME)
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   141
        req.fileattr = lib.ATTR_FILE_DATALENGTH
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   142
        dfd = lib.open(path, lib.O_RDONLY, 0)
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   143
        if dfd == -1:
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   144
            raise OSError(ffi.errno, os.strerror(ffi.errno))
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   145
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   146
        try:
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   147
            ret = listdirinternal(dfd, req, stat, skip)
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   148
        finally:
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   149
            try:
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   150
                lib.close(dfd)
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   151
            except BaseException:
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   152
                pass # we ignore all the errors from closing, not
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   153
                # much we can do about that
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   154
        return ret
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   155
else:
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   156
    listdir = listdirpure
7a157639b8f2 osutil: add darwin-only version of os.listdir using cffi
Maciej Fijalkowski <fijall@gmail.com>
parents: 27971
diff changeset
   157
14413
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   158
if os.name != 'nt':
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   159
    posixfile = open
27474
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   160
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   161
    _SCM_RIGHTS = 0x01
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   162
    _socklen_t = ctypes.c_uint
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   163
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   164
    if sys.platform == 'linux2':
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   165
        # socket.h says "the type should be socklen_t but the definition of
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   166
        # the kernel is incompatible with this."
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   167
        _cmsg_len_t = ctypes.c_size_t
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   168
        _msg_controllen_t = ctypes.c_size_t
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   169
        _msg_iovlen_t = ctypes.c_size_t
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   170
    else:
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   171
        _cmsg_len_t = _socklen_t
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   172
        _msg_controllen_t = _socklen_t
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   173
        _msg_iovlen_t = ctypes.c_int
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   174
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   175
    class _iovec(ctypes.Structure):
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   176
        _fields_ = [
29712
f15f31505f12 py3: use unicode literals in pure/osutil.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29600
diff changeset
   177
            (u'iov_base', ctypes.c_void_p),
f15f31505f12 py3: use unicode literals in pure/osutil.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29600
diff changeset
   178
            (u'iov_len', ctypes.c_size_t),
27474
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   179
        ]
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   180
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   181
    class _msghdr(ctypes.Structure):
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   182
        _fields_ = [
29712
f15f31505f12 py3: use unicode literals in pure/osutil.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29600
diff changeset
   183
            (u'msg_name', ctypes.c_void_p),
f15f31505f12 py3: use unicode literals in pure/osutil.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29600
diff changeset
   184
            (u'msg_namelen', _socklen_t),
f15f31505f12 py3: use unicode literals in pure/osutil.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29600
diff changeset
   185
            (u'msg_iov', ctypes.POINTER(_iovec)),
f15f31505f12 py3: use unicode literals in pure/osutil.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29600
diff changeset
   186
            (u'msg_iovlen', _msg_iovlen_t),
f15f31505f12 py3: use unicode literals in pure/osutil.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29600
diff changeset
   187
            (u'msg_control', ctypes.c_void_p),
f15f31505f12 py3: use unicode literals in pure/osutil.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29600
diff changeset
   188
            (u'msg_controllen', _msg_controllen_t),
f15f31505f12 py3: use unicode literals in pure/osutil.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29600
diff changeset
   189
            (u'msg_flags', ctypes.c_int),
27474
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   190
        ]
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   191
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   192
    class _cmsghdr(ctypes.Structure):
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   193
        _fields_ = [
29712
f15f31505f12 py3: use unicode literals in pure/osutil.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29600
diff changeset
   194
            (u'cmsg_len', _cmsg_len_t),
f15f31505f12 py3: use unicode literals in pure/osutil.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29600
diff changeset
   195
            (u'cmsg_level', ctypes.c_int),
f15f31505f12 py3: use unicode literals in pure/osutil.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29600
diff changeset
   196
            (u'cmsg_type', ctypes.c_int),
f15f31505f12 py3: use unicode literals in pure/osutil.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29600
diff changeset
   197
            (u'cmsg_data', ctypes.c_ubyte * 0),
27474
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   198
        ]
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   199
29712
f15f31505f12 py3: use unicode literals in pure/osutil.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29600
diff changeset
   200
    _libc = ctypes.CDLL(ctypes.util.find_library(u'c'), use_errno=True)
27971
f7d0c28d34b3 osutil: do not abort loading pure module just because libc has no recvmsg()
Yuya Nishihara <yuya@tcha.org>
parents: 27704
diff changeset
   201
    _recvmsg = getattr(_libc, 'recvmsg', None)
f7d0c28d34b3 osutil: do not abort loading pure module just because libc has no recvmsg()
Yuya Nishihara <yuya@tcha.org>
parents: 27704
diff changeset
   202
    if _recvmsg:
f7d0c28d34b3 osutil: do not abort loading pure module just because libc has no recvmsg()
Yuya Nishihara <yuya@tcha.org>
parents: 27704
diff changeset
   203
        _recvmsg.restype = getattr(ctypes, 'c_ssize_t', ctypes.c_long)
f7d0c28d34b3 osutil: do not abort loading pure module just because libc has no recvmsg()
Yuya Nishihara <yuya@tcha.org>
parents: 27704
diff changeset
   204
        _recvmsg.argtypes = (ctypes.c_int, ctypes.POINTER(_msghdr),
f7d0c28d34b3 osutil: do not abort loading pure module just because libc has no recvmsg()
Yuya Nishihara <yuya@tcha.org>
parents: 27704
diff changeset
   205
                             ctypes.c_int)
f7d0c28d34b3 osutil: do not abort loading pure module just because libc has no recvmsg()
Yuya Nishihara <yuya@tcha.org>
parents: 27704
diff changeset
   206
    else:
f7d0c28d34b3 osutil: do not abort loading pure module just because libc has no recvmsg()
Yuya Nishihara <yuya@tcha.org>
parents: 27704
diff changeset
   207
        # recvmsg isn't always provided by libc; such systems are unsupported
f7d0c28d34b3 osutil: do not abort loading pure module just because libc has no recvmsg()
Yuya Nishihara <yuya@tcha.org>
parents: 27704
diff changeset
   208
        def _recvmsg(sockfd, msg, flags):
f7d0c28d34b3 osutil: do not abort loading pure module just because libc has no recvmsg()
Yuya Nishihara <yuya@tcha.org>
parents: 27704
diff changeset
   209
            raise NotImplementedError('unsupported platform')
27474
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   210
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   211
    def _CMSG_FIRSTHDR(msgh):
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   212
        if msgh.msg_controllen < ctypes.sizeof(_cmsghdr):
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   213
            return
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   214
        cmsgptr = ctypes.cast(msgh.msg_control, ctypes.POINTER(_cmsghdr))
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   215
        return cmsgptr.contents
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   216
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   217
    # The pure version is less portable than the native version because the
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   218
    # handling of socket ancillary data heavily depends on C preprocessor.
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   219
    # Also, some length fields are wrongly typed in Linux kernel.
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   220
    def recvfds(sockfd):
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   221
        """receive list of file descriptors via socket"""
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   222
        dummy = (ctypes.c_ubyte * 1)()
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   223
        iov = _iovec(ctypes.cast(dummy, ctypes.c_void_p), ctypes.sizeof(dummy))
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   224
        cbuf = ctypes.create_string_buffer(256)
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   225
        msgh = _msghdr(None, 0,
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   226
                       ctypes.pointer(iov), 1,
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   227
                       ctypes.cast(cbuf, ctypes.c_void_p), ctypes.sizeof(cbuf),
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   228
                       0)
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   229
        r = _recvmsg(sockfd, ctypes.byref(msgh), 0)
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   230
        if r < 0:
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   231
            e = ctypes.get_errno()
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   232
            raise OSError(e, os.strerror(e))
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   233
        # assumes that the first cmsg has fds because it isn't easy to write
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   234
        # portable CMSG_NXTHDR() with ctypes.
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   235
        cmsg = _CMSG_FIRSTHDR(msgh)
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   236
        if not cmsg:
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   237
            return []
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   238
        if (cmsg.cmsg_level != socket.SOL_SOCKET or
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   239
            cmsg.cmsg_type != _SCM_RIGHTS):
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   240
            return []
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   241
        rfds = ctypes.cast(cmsg.cmsg_data, ctypes.POINTER(ctypes.c_int))
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   242
        rfdscount = ((cmsg.cmsg_len - _cmsghdr.cmsg_data.offset) /
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   243
                     ctypes.sizeof(ctypes.c_int))
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   244
        return [rfds[i] for i in xrange(rfdscount)]
e517a89c24e1 osutil: implement pure version of recvfds() for PyPy
Yuya Nishihara <yuya@tcha.org>
parents: 27338
diff changeset
   245
14413
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   246
else:
27338
810337ae1b76 osutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25645
diff changeset
   247
    import msvcrt
14413
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   248
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   249
    _kernel32 = ctypes.windll.kernel32
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   250
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   251
    _DWORD = ctypes.c_ulong
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   252
    _LPCSTR = _LPSTR = ctypes.c_char_p
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   253
    _HANDLE = ctypes.c_void_p
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   254
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   255
    _INVALID_HANDLE_VALUE = _HANDLE(-1).value
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   256
18959
2f6418d8a4c9 check-code: catch trailing space in comments
Mads Kiilerich <madski@unity3d.com>
parents: 17429
diff changeset
   257
    # CreateFile
14413
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   258
    _FILE_SHARE_READ = 0x00000001
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   259
    _FILE_SHARE_WRITE = 0x00000002
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   260
    _FILE_SHARE_DELETE = 0x00000004
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   261
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   262
    _CREATE_ALWAYS = 2
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   263
    _OPEN_EXISTING = 3
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   264
    _OPEN_ALWAYS = 4
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   265
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   266
    _GENERIC_READ = 0x80000000
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   267
    _GENERIC_WRITE = 0x40000000
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   268
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   269
    _FILE_ATTRIBUTE_NORMAL = 0x80
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   270
17429
72fa4ef2245f declare local constants instead of using magic values and comments
Mads Kiilerich <mads@kiilerich.com>
parents: 16686
diff changeset
   271
    # open_osfhandle flags
14413
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   272
    _O_RDONLY = 0x0000
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   273
    _O_RDWR = 0x0002
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   274
    _O_APPEND = 0x0008
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   275
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   276
    _O_TEXT = 0x4000
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   277
    _O_BINARY = 0x8000
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   278
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   279
    # types of parameters of C functions used (required by pypy)
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   280
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   281
    _kernel32.CreateFileA.argtypes = [_LPCSTR, _DWORD, _DWORD, ctypes.c_void_p,
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   282
        _DWORD, _DWORD, _HANDLE]
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   283
    _kernel32.CreateFileA.restype = _HANDLE
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   284
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   285
    def _raiseioerror(name):
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   286
        err = ctypes.WinError()
25645
977102cb12fc osutil: remove Python 2.4 errno conversion workaround
Gregory Szorc <gregory.szorc@gmail.com>
parents: 19465
diff changeset
   287
        raise IOError(err.errno, '%s: %s' % (name, err.strerror))
14413
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   288
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   289
    class posixfile(object):
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   290
        '''a file object aiming for POSIX-like semantics
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   291
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   292
        CPython's open() returns a file that was opened *without* setting the
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   293
        _FILE_SHARE_DELETE flag, which causes rename and unlink to abort.
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   294
        This even happens if any hardlinked copy of the file is in open state.
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   295
        We set _FILE_SHARE_DELETE here, so files opened with posixfile can be
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   296
        renamed and deleted while they are held open.
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   297
        Note that if a file opened with posixfile is unlinked, the file
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   298
        remains but cannot be opened again or be recreated under the same name,
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   299
        until all reading processes have closed the file.'''
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   300
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   301
        def __init__(self, name, mode='r', bufsize=-1):
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   302
            if 'b' in mode:
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   303
                flags = _O_BINARY
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   304
            else:
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   305
                flags = _O_TEXT
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   306
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   307
            m0 = mode[0]
16686
67964cda8701 cleanup: "not x in y" -> "x not in y"
Brodie Rao <brodie@sf.io>
parents: 16474
diff changeset
   308
            if m0 == 'r' and '+' not in mode:
14413
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   309
                flags |= _O_RDONLY
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   310
                access = _GENERIC_READ
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   311
            else:
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   312
                # work around http://support.microsoft.com/kb/899149 and
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   313
                # set _O_RDWR for 'w' and 'a', even if mode has no '+'
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   314
                flags |= _O_RDWR
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   315
                access = _GENERIC_READ | _GENERIC_WRITE
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   316
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   317
            if m0 == 'r':
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   318
                creation = _OPEN_EXISTING
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   319
            elif m0 == 'w':
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   320
                creation = _CREATE_ALWAYS
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   321
            elif m0 == 'a':
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   322
                creation = _OPEN_ALWAYS
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   323
                flags |= _O_APPEND
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   324
            else:
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   325
                raise ValueError("invalid mode: %s" % mode)
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   326
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   327
            fh = _kernel32.CreateFileA(name, access,
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   328
                    _FILE_SHARE_READ | _FILE_SHARE_WRITE | _FILE_SHARE_DELETE,
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   329
                    None, creation, _FILE_ATTRIBUTE_NORMAL, None)
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   330
            if fh == _INVALID_HANDLE_VALUE:
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   331
                _raiseioerror(name)
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   332
16474
ee553e6cd8c4 pure/osutil: use Python's msvcrt module (issue3380)
Adrian Buehlmann <adrian@cadifra.com>
parents: 15040
diff changeset
   333
            fd = msvcrt.open_osfhandle(fh, flags)
14413
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   334
            if fd == -1:
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   335
                _kernel32.CloseHandle(fh)
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   336
                _raiseioerror(name)
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   337
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   338
            f = os.fdopen(fd, mode, bufsize)
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   339
            # unfortunately, f.name is '<fdopen>' at this point -- so we store
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   340
            # the name on this wrapper. We cannot just assign to f.name,
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   341
            # because that attribute is read-only.
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   342
            object.__setattr__(self, 'name', name)
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   343
            object.__setattr__(self, '_file', f)
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   344
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   345
        def __iter__(self):
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   346
            return self._file
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   347
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   348
        def __getattr__(self, name):
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   349
            return getattr(self._file, name)
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   350
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   351
        def __setattr__(self, name, value):
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   352
            '''mimics the read-only attributes of Python file objects
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   353
            by raising 'TypeError: readonly attribute' if someone tries:
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   354
              f = posixfile('foo.txt')
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   355
              f.name = 'bla'  '''
5ef18e28df19 pure: provide more correct implementation of posixfile for Windows
Adrian Buehlmann <adrian@cadifra.com>
parents: 10651
diff changeset
   356
            return self._file.__setattr__(name, value)
27704
051b0dcec98b osutil: implement __enter__ and __exit__ on posixfile
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27512
diff changeset
   357
051b0dcec98b osutil: implement __enter__ and __exit__ on posixfile
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27512
diff changeset
   358
        def __enter__(self):
051b0dcec98b osutil: implement __enter__ and __exit__ on posixfile
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27512
diff changeset
   359
            return self._file.__enter__()
051b0dcec98b osutil: implement __enter__ and __exit__ on posixfile
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27512
diff changeset
   360
051b0dcec98b osutil: implement __enter__ and __exit__ on posixfile
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27512
diff changeset
   361
        def __exit__(self, exc_type, exc_value, exc_tb):
051b0dcec98b osutil: implement __enter__ and __exit__ on posixfile
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27512
diff changeset
   362
            return self._file.__exit__(exc_type, exc_value, exc_tb)