|
1 | 1 | /*
|
2 | 2 | This source file is part of the Swift.org open source project
|
3 | 3 |
|
4 |
| - Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors |
| 4 | + Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors |
5 | 5 | Licensed under Apache License v2.0 with Runtime Library Exception
|
6 | 6 |
|
7 | 7 | See http://swift.org/LICENSE.txt for license information
|
@@ -178,12 +178,33 @@ public final class FileLock {
|
178 | 178 | throw FileSystemError(.notDirectory, lockFilesDirectory)
|
179 | 179 | }
|
180 | 180 | // use the parent path to generate unique filename in temp
|
181 |
| - var lockFileName = (resolveSymlinks(fileToLock.parentDirectory).appending(component: fileToLock.basename)).components.joined(separator: "_") |
| 181 | + var lockFileName = (resolveSymlinks(fileToLock.parentDirectory) |
| 182 | + .appending(component: fileToLock.basename)) |
| 183 | + .components.joined(separator: "_") |
| 184 | + .replacingOccurrences(of: ":", with: "_") + ".lock" |
| 185 | +#if os(Windows) |
| 186 | + // NTFS has an ARC limit of 255 codepoints |
| 187 | + var lockFileUTF16 = lockFileName.utf16.suffix(255) |
| 188 | + while String(lockFileUTF16) == nil { |
| 189 | + lockFileUTF16 = lockFileUTF16.dropFirst() |
| 190 | + } |
| 191 | + lockFileName = String(lockFileUTF16) ?? lockFileName |
| 192 | +#else |
182 | 193 | if lockFileName.hasPrefix(AbsolutePath.root.pathString) {
|
183 | 194 | lockFileName = String(lockFileName.dropFirst(AbsolutePath.root.pathString.count))
|
184 | 195 | }
|
185 |
| - let lockFilePath = lockFilesDirectory.appending(component: lockFileName + ".lock") |
186 |
| - |
| 196 | + // back off until it occupies at most `NAME_MAX` UTF-8 bytes but without splitting scalars |
| 197 | + // (we might split clusters but it's not worth the effort to keep them together as long as we get a valid file name) |
| 198 | + var lockFileUTF8 = lockFileName.utf8.suffix(Int(NAME_MAX)) |
| 199 | + while String(lockFileUTF8) == nil { |
| 200 | + // in practice this will only be a few iterations |
| 201 | + lockFileUTF8 = lockFileUTF8.dropFirst() |
| 202 | + } |
| 203 | + // we will never end up with nil since we have ASCII characters at the end |
| 204 | + lockFileName = String(lockFileUTF8) ?? lockFileName |
| 205 | +#endif |
| 206 | + let lockFilePath = lockFilesDirectory.appending(component: lockFileName) |
| 207 | + |
187 | 208 | let lock = FileLock(at: lockFilePath)
|
188 | 209 | return try lock.withLock(type: type, body)
|
189 | 210 | }
|
|
0 commit comments