Initial import to Tizen
[profile/ivi/python-twisted.git] / twisted / internet / fdesc.py
1 # -*- test-case-name: twisted.test.test_fdesc -*-
2 # Copyright (c) Twisted Matrix Laboratories.
3 # See LICENSE for details.
4
5
6 """
7 Utility functions for dealing with POSIX file descriptors.
8 """
9
10 import os
11 import errno
12 try:
13     import fcntl
14 except ImportError:
15     fcntl = None
16
17 # twisted imports
18 from twisted.internet.main import CONNECTION_LOST, CONNECTION_DONE
19 from twisted.python.runtime import platformType
20
21 def setNonBlocking(fd):
22     """
23     Make a file descriptor non-blocking.
24     """
25     flags = fcntl.fcntl(fd, fcntl.F_GETFL)
26     flags = flags | os.O_NONBLOCK
27     fcntl.fcntl(fd, fcntl.F_SETFL, flags)
28
29
30 def setBlocking(fd):
31     """
32     Make a file descriptor blocking.
33     """
34     flags = fcntl.fcntl(fd, fcntl.F_GETFL)
35     flags = flags & ~os.O_NONBLOCK
36     fcntl.fcntl(fd, fcntl.F_SETFL, flags)
37
38
39 if fcntl is None:
40     # fcntl isn't available on Windows.  By default, handles aren't
41     # inherited on Windows, so we can do nothing here.
42     _setCloseOnExec = _unsetCloseOnExec = lambda fd: None
43 else:
44     def _setCloseOnExec(fd):
45         """
46         Make a file descriptor close-on-exec.
47         """
48         flags = fcntl.fcntl(fd, fcntl.F_GETFD)
49         flags = flags | fcntl.FD_CLOEXEC
50         fcntl.fcntl(fd, fcntl.F_SETFD, flags)
51
52
53     def _unsetCloseOnExec(fd):
54         """
55         Make a file descriptor close-on-exec.
56         """
57         flags = fcntl.fcntl(fd, fcntl.F_GETFD)
58         flags = flags & ~fcntl.FD_CLOEXEC
59         fcntl.fcntl(fd, fcntl.F_SETFD, flags)
60
61
62 def readFromFD(fd, callback):
63     """
64     Read from file descriptor, calling callback with resulting data.
65
66     If successful, call 'callback' with a single argument: the
67     resulting data.
68
69     Returns same thing FileDescriptor.doRead would: CONNECTION_LOST,
70     CONNECTION_DONE, or None.
71
72     @type fd: C{int}
73     @param fd: non-blocking file descriptor to be read from.
74     @param callback: a callable which accepts a single argument. If
75     data is read from the file descriptor it will be called with this
76     data. Handling exceptions from calling the callback is up to the
77     caller.
78
79     Note that if the descriptor is still connected but no data is read,
80     None will be returned but callback will not be called.
81
82     @return: CONNECTION_LOST on error, CONNECTION_DONE when fd is
83     closed, otherwise None.
84     """
85     try:
86         output = os.read(fd, 8192)
87     except (OSError, IOError), ioe:
88         if ioe.args[0] in (errno.EAGAIN, errno.EINTR):
89             return
90         else:
91             return CONNECTION_LOST
92     if not output:
93         return CONNECTION_DONE
94     callback(output)
95
96
97 def writeToFD(fd, data):
98     """
99     Write data to file descriptor.
100
101     Returns same thing FileDescriptor.writeSomeData would.
102
103     @type fd: C{int}
104     @param fd: non-blocking file descriptor to be written to.
105     @type data: C{str} or C{buffer}
106     @param data: bytes to write to fd.
107
108     @return: number of bytes written, or CONNECTION_LOST.
109     """
110     try:
111         return os.write(fd, data)
112     except (OSError, IOError), io:
113         if io.errno in (errno.EAGAIN, errno.EINTR):
114             return 0
115         return CONNECTION_LOST
116
117
118 __all__ = ["setNonBlocking", "setBlocking", "readFromFD", "writeToFD"]