// // Copyright Amazon.com Inc. or its affiliates. // All Rights Reserved. // // SPDX-License-Identifier: Apache-2.0 // import Foundation /// Represents an individual log file on disk used as part of a /// LogRotation final class LogFile { let fileURL: URL let sizeLimitInBytes: UInt64 private let handle: FileHandle private var count: UInt64 /// Creates a new file with the given URL and sets its attributes accordingly. init(forWritingTo fileURL: URL, sizeLimitInBytes: UInt64) throws { self.fileURL = fileURL self.sizeLimitInBytes = sizeLimitInBytes self.handle = try FileHandle(forWritingTo: fileURL) self.count = 0 } /// Opens a file for updating with the given URL and sets its attributes accordingly. init(forAppending fileURL: URL, sizeLimitInBytes: UInt64) throws { self.fileURL = fileURL self.sizeLimitInBytes = sizeLimitInBytes self.handle = try FileHandle(forUpdating: fileURL) if #available(macOS 10.15.4, iOS 13.4, watchOS 6.2, tvOS 13.4, *) { self.count = try self.handle.offset() } else { self.count = self.handle.offsetInFile } } deinit { try? self.handle.close() } /// Returns the number of bytes available in the underlying file. var available: UInt64 { if sizeLimitInBytes > count { return sizeLimitInBytes - count } else { return 0 } } /// Attempts to close the underlying log file. func close() throws { try self.handle.close() } /// Atempts to flush the receivers contents to disk. func synchronize() throws { try self.handle.synchronize() } /// - Returns: true if writing to the underlying log file will keep its size below the limit. func hasSpace(for data: Data) -> Bool { return UInt64(data.count) <= self.available } /// Writes the given **single line of text** represented as a /// Data to the underlying log file. func write(data: Data) throws { if #available(macOS 10.15.4, iOS 13.4, watchOS 6.2, tvOS 13.4, *) { try self.handle.write(contentsOf: data) } else { self.handle.write(data) } try self.handle.synchronize() count = count + UInt64(data.count) } }