Skip to content

Commit 64040f3

Browse files
committed
wip: removing fcntl API
1 parent df8f085 commit 64040f3

File tree

2 files changed

+3
-235
lines changed

2 files changed

+3
-235
lines changed

Sources/System/FileControl.swift

Lines changed: 3 additions & 215 deletions
Original file line numberDiff line numberDiff line change
@@ -5,233 +5,21 @@
55
Licensed under Apache License v2.0 with Runtime Library Exception
66

77
See https://swift.org/LICENSE.txt for license information
8-
*/
8+
*/
99

1010
// Strongly typed, Swifty interfaces to the most common and useful `fcntl`
1111
// commands.
1212

1313
extension FileDescriptor {
14-
/// Get the flags associated with this file descriptor
15-
///
16-
/// The corresponding C function is `fcntl` with the `F_GETFD` command.
17-
@_alwaysEmitIntoClient
18-
public func getFlags() throws -> Flags {
19-
try Flags(rawValue: control(.getFlags))
20-
}
21-
22-
/// Set the file descriptor flags.
23-
///
24-
/// The corresponding C function is `fcntl` with the `F_SETFD` command.
25-
@_alwaysEmitIntoClient
26-
public func setFlags(_ value: Flags) throws {
27-
_ = try control(.setFlags, value.rawValue)
28-
}
29-
30-
/// Get descriptor status flags.
31-
///
32-
/// The corresponding C function is `fcntl` with the `F_GETFL` command.
33-
@_alwaysEmitIntoClient
34-
public func getStatusFlags() throws -> StatusFlags {
35-
try StatusFlags(rawValue: control(.getStatusFlags))
36-
}
37-
38-
/// Set descriptor status flags.
39-
///
40-
/// The corresponding C function is `fcntl` with the `F_SETFL` command.
41-
@_alwaysEmitIntoClient
42-
public func setStatusFlags(_ flags: StatusFlags) throws {
43-
_ = try control(.setStatusFlags, flags.rawValue)
44-
}
45-
}
46-
47-
48-
extension FileDescriptor {
49-
// TODO: Unify this dup with the other dups which have come in since...
50-
51-
/// Duplicate this file descriptor and return the newly created copy.
52-
///
53-
/// - Parameters:
54-
/// - `minRawValue`: A lower bound on the new file descriptor's raw value.
55-
/// - `closeOnExec`: Whether the new descriptor's `closeOnExec` flag is set.
56-
/// - Returns: The lowest numbered available descriptor whose raw value is
57-
/// greater than or equal to `minRawValue`.
58-
///
59-
/// File descriptors are merely references to some underlying system resource.
60-
/// The system does not distinguish between the original and the new file
61-
/// descriptor in any way. For example, read, write and seek operations on
62-
/// one of them also affect the logical file position in the other, and
63-
/// append mode, non-blocking I/O and asynchronous I/O options are shared
64-
/// between the references. If a separate pointer into the file is desired,
65-
/// a different object reference to the file must be obtained by issuing an
66-
/// additional call to `open`.
67-
///
68-
/// However, each file descriptor maintains its own close-on-exec flag.
69-
///
70-
/// The corresponding C functions are `fcntl` with `F_DUPFD` and
71-
/// `F_DUPFD_CLOEXEC`.
72-
@_alwaysEmitIntoClient
73-
public func duplicate(
74-
minRawValue: CInt, closeOnExec: Bool
75-
) throws -> FileDescriptor {
76-
let cmd: Control.Command = closeOnExec ? .duplicateCloseOnExec : .duplicate
77-
return try FileDescriptor(rawValue: control(cmd, minRawValue))
78-
}
79-
80-
#if !os(Linux)
81-
/// Get the path of the file descriptor
82-
///
83-
/// - Parameters:
84-
/// - `noFirmLink`: Get the non firmlinked path of the file descriptor.
85-
///
86-
/// The corresponding C functions are `fcntl` with `F_GETPATH` and
87-
/// `F_GETPATH_NOFIRMLINK`.
88-
public func getPath(noFirmLink: Bool = false) throws -> FilePath {
89-
let cmd: Control.Command = noFirmLink ? .getPathNoFirmLink : .getPath
90-
// TODO: have a uninitialized init on FilePath / SystemString...
91-
let bytes = try Array<SystemChar>(unsafeUninitializedCapacity: _maxPathLen) {
92-
(bufPtr, count: inout Int) in
93-
_ = try control(cmd, UnsafeMutableRawPointer(bufPtr.baseAddress!))
94-
count = 1 + system_strlen(
95-
UnsafeRawPointer(bufPtr.baseAddress!).assumingMemoryBound(to: Int8.self))
96-
}
97-
return FilePath(SystemString(nullTerminated: bytes))
98-
}
99-
#endif
100-
}
101-
102-
// TODO: More fsync functionality using `F_BARRIERFSYNC` and `F_FULLFSYNC`,
103-
// coinciding with the sketch for fsync.
104-
105-
// MARK: - To add in the future with process support
106-
107-
extension FileDescriptor {
108-
// TODO: Flesh out PID work and see if there's a better, common formulation
109-
// of the process-or-group id concept.
110-
// TODO: @frozen
111-
// TODO: public
112-
private struct PIDOrPGID: RawRepresentable {
113-
@_alwaysEmitIntoClient
114-
public let rawValue: CInt
115-
116-
@_alwaysEmitIntoClient
117-
public init(rawValue: CInt) { self.rawValue = rawValue }
118-
119-
/// TODO: PID type
120-
@_alwaysEmitIntoClient
121-
public var asPID: CInt? { rawValue >= 0 ? rawValue : nil }
122-
123-
/// TODO: PGID type
124-
@_alwaysEmitIntoClient
125-
public var asPositiveGroupID: CInt? {
126-
rawValue >= 0 ? nil : -rawValue
127-
}
128-
129-
/// TODO: PID type
130-
@_alwaysEmitIntoClient
131-
public init(pid id: CInt) {
132-
precondition(id >= 0)
133-
self.init(rawValue: id)
134-
}
135-
136-
/// TODO: PGID type
137-
@_alwaysEmitIntoClient
138-
public init(positiveGroupID id: CInt) {
139-
precondition(id >= 0)
140-
self.init(rawValue: -id)
141-
}
142-
}
143-
144-
/// Get the process ID or process group currently receiv-
145-
/// ing SIGIO and SIGURG signals.
146-
///
147-
/// The corresponding C function is `fcntl` with the `F_GETOWN` command.
148-
// TODO: @_alwaysEmitIntoClient
149-
// TODO: public
150-
private func getOwner() throws -> PIDOrPGID {
151-
try PIDOrPGID(rawValue: control(.getOwner))
152-
}
153-
154-
/// Set the process or process group to receive SIGIO and
155-
/// SIGURG signals.
156-
///
157-
/// The corresponding C function is `fcntl` with the `F_SETOWN` command.
158-
// TODO: @_alwaysEmitIntoClient
159-
// TODO: public
160-
private func setOwner(_ id: PIDOrPGID) throws {
161-
_ = try control(.setOwner, id.rawValue)
162-
}
163-
}
164-
165-
extension FileDescriptor {
166-
/// Low-level file control.
167-
///
168-
/// Note: most common operations have Swiftier alternatives, e.g. `FileDescriptor.getFlags()`
169-
///
170-
/// The corresponding C function is `fcntl`.
171-
@_alwaysEmitIntoClient
172-
public func control(_ cmd: Control.Command) throws -> CInt {
173-
try _fcntl(cmd).get()
174-
}
175-
176-
/// Low-level file control.
177-
///
178-
/// Note: most common operations have Swiftier alternatives, e.g. `FileDescriptor.getFlags()`
179-
///
180-
/// The corresponding C function is `fcntl`.
181-
@_alwaysEmitIntoClient
182-
public func control(_ cmd: Control.Command, _ arg: CInt) throws -> CInt {
183-
try _fcntl(cmd, arg).get()
184-
}
185-
186-
/// Low-level file control.
187-
///
188-
/// Note: most common operations have Swiftier alternatives, e.g. `FileDescriptor.getFlags()`
189-
///
190-
/// The corresponding C function is `fcntl`.
191-
@_alwaysEmitIntoClient
192-
public func control(
193-
_ cmd: Control.Command, _ ptr: UnsafeMutableRawPointer
194-
) throws -> CInt {
195-
try _fcntl(cmd, ptr).get()
196-
}
197-
198-
@usableFromInline
199-
internal func _fcntl(_ cmd: Control.Command) -> Result<CInt, Errno> {
200-
valueOrErrno(retryOnInterrupt: false) {
201-
system_fcntl(self.rawValue, cmd.rawValue)
202-
}
203-
}
204-
@usableFromInline
205-
internal func _fcntl(
206-
_ cmd: Control.Command, _ arg: CInt
207-
) -> Result<CInt, Errno> {
208-
valueOrErrno(retryOnInterrupt: false) {
209-
system_fcntl(self.rawValue, cmd.rawValue, arg)
210-
}
211-
}
212-
@usableFromInline
213-
internal func _fcntl(
214-
_ cmd: Control.Command, _ ptr: UnsafeMutableRawPointer
215-
) -> Result<CInt, Errno> {
216-
valueOrErrno(retryOnInterrupt: false) {
217-
system_fcntl(self.rawValue, cmd.rawValue, ptr)
218-
}
219-
}
22014
@usableFromInline
22115
internal func _fcntl(
22216
_ cmd: Control.Command, _ lock: inout FileDescriptor.FileLock,
22317
retryOnInterrupt: Bool
22418
) -> Result<(), Errno> {
225-
print(
226-
" fcntl \(cmd.rawValue) with type \(lock.type.rawValue)",
227-
terminator: "")
228-
let result = nothingOrErrno(retryOnInterrupt: retryOnInterrupt) {
19+
nothingOrErrno(retryOnInterrupt: retryOnInterrupt) {
22920
withUnsafeMutablePointer(to: &lock) {
230-
let r = system_fcntl(self.rawValue, cmd.rawValue, $0)
231-
return r
21+
system_fcntl(self.rawValue, cmd.rawValue, $0)
23222
}
23323
}
234-
print(" -> type \(lock.type.rawValue)")
235-
return result
23624
}
23725
}

Tests/SystemTests/FileOperationsTest.swift

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -224,26 +224,6 @@ final class FileOperationsTest: XCTestCase {
224224
XCTAssertEqual(readBytesAfterTruncation, Array("ab".utf8))
225225
}
226226
}
227-
228-
func testFcntl() throws {
229-
let path = FilePath("/tmp/\(UUID().uuidString).txt")
230-
231-
// On Darwin, `/tmp` is a symlink to `/private/tmp`
232-
// TODO: Linux?
233-
// TODO: Get or query symlink status when we add those APIs
234-
let resolvedPath = FilePath("/private").pushing(path.removingRoot())
235-
236-
let fd = try FileDescriptor.open(
237-
path, .readWrite, options: [.create, .truncate], permissions: .ownerReadWrite)
238-
try fd.closeAfter {
239-
240-
#if !os(Linux)
241-
XCTAssertEqual(resolvedPath, try fd.getPath())
242-
#endif
243-
244-
// TODO: more tests
245-
}
246-
}
247227
#endif
248228
}
249229

0 commit comments

Comments
 (0)