Skip to content

Commit

Permalink
OSX 10.15 file offset methods
Browse files Browse the repository at this point in the history
  • Loading branch information
rfm committed Nov 8, 2024
1 parent 4b33151 commit fe5efb6
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 31 deletions.
2 changes: 1 addition & 1 deletion ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Headers/Foundation/NSFileHandle.h:
* Source/GSFileHandle.m:
* Source/NSFileHandle.m:
Add -truncateAtOffset:error: method (issue 325)
Add OSX 12.15 file offset methods (issue 325, pull 446 and more)

2024-11-03 Richard Frith-Macdonald <[email protected]>

Expand Down
6 changes: 6 additions & 0 deletions Headers/Foundation/NSFileHandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ GS_EXPORT_CLASS
- (void) truncateFileAtOffset: (unsigned long long)pos;

#if OS_API_VERSION(MAC_OS_X_VERSION_10_15, GS_API_LATEST)
- (BOOL) getOffset: (out unsigned long long *)offsetInFile
error: (out NSError **)error;
- (BOOL) seekToEndReturningOffset: (out unsigned long long *)offsetInFile
error: (out NSError **)error;
- (BOOL) seekToOffset: (unsigned long long)offset
error: (out NSError **)error;
- (BOOL) truncateAtOffset: (unsigned long long)offset
error: (out NSError **)error;
#endif
Expand Down
114 changes: 84 additions & 30 deletions Source/GSFileHandle.m
Original file line number Diff line number Diff line change
Expand Up @@ -1521,7 +1521,8 @@ - (void) waitForDataInBackgroundAndNotifyForModes: (NSArray*)modes

// Seeking within a file

- (unsigned long long) offsetInFile
- (BOOL) getOffset: (out unsigned long long *)offsetInFile
error: (out NSError **)error;
{
off_t result = -1;

Expand All @@ -1544,15 +1545,48 @@ - (unsigned long long) offsetInFile
result = lseek(descriptor, 0, SEEK_CUR);
}
if (result < 0)
{
if (error)
{
*error = [NSError _last];
}
return NO;
}
if (offsetInFile)
{
*offsetInFile = (unsigned long long)result;
}
return YES;
}

- (unsigned long long) offsetInFile
{
unsigned long long result;
NSError *error;

if ([self getOffset: &result error: &error] == NO)
{
[NSException raise: NSFileHandleOperationException
format: @"failed to move to offset in file - %@",
[NSError _last]];
format: @"failed to move to offset in file - %@", error];
}
return (unsigned long long)result;
return result;
}

- (unsigned long long) seekToEndOfFile
{
unsigned long long result;
NSError *error;

if ([self seekToEndReturningOffset: &result error: &error] == NO)
{
[NSException raise: NSFileHandleOperationException
format: @"failed to move to offset in file - %@", error];
}
return result;
}

- (BOOL) seekToEndReturningOffset: (out unsigned long long *)offsetInFile
error: (out NSError **)error
{
off_t result = -1;

Expand All @@ -1576,21 +1610,39 @@ - (unsigned long long) seekToEndOfFile
}
if (result < 0)
{
[NSException raise: NSFileHandleOperationException
format: @"failed to move to offset in file - %@",
[NSError _last]];
if (error)
{
*error = [NSError _last];
}
return NO;
}
return (unsigned long long)result;
if (offsetInFile)
{
*offsetInFile = (unsigned long long)result;
}
return YES;
}

- (void) seekToFileOffset: (unsigned long long)pos
{
NSError *error;

if ([self seekToOffset: pos error: &error] == NO)
{
[NSException raise: NSFileHandleOperationException
format: @"failed to move to offset in file - %@", error];
}
}

- (BOOL) seekToOffset: (unsigned long long)offset
error: (out NSError **)error
{
off_t result = -1;

#ifdef __ANDROID__
if (asset)
{
result = AAsset_seek(asset, (off_t)pos, SEEK_SET);
result = AAsset_seek(asset, (off_t)offset, SEEK_SET);
}
else
#endif
Expand All @@ -1599,21 +1651,23 @@ - (void) seekToFileOffset: (unsigned long long)pos
#if USE_ZLIB
if (gzDescriptor != 0)
{
result = gzseek(gzDescriptor, (off_t)pos, SEEK_SET);
result = gzseek(gzDescriptor, (off_t)offset, SEEK_SET);
}
else
#endif
result = lseek(descriptor, (off_t)pos, SEEK_SET);
result = lseek(descriptor, (off_t)offset, SEEK_SET);
}
if (result < 0)
{
[NSException raise: NSFileHandleOperationException
format: @"failed to move to offset in file - %@",
[NSError _last]];
if (error)
{
*error = [NSError _last];
}
return NO;
}
return YES;
}


// Operations on file

- (void) closeFile
Expand Down Expand Up @@ -1716,21 +1770,6 @@ - (void) synchronizeFile
}
}

- (void) truncateFileAtOffset: (unsigned long long)pos
{
if (!(isStandardFile && descriptor >= 0))
{
[NSException raise: NSFileHandleOperationException
format: @"attempt to truncate invalid file"];
}
if (ftruncate(descriptor, pos) < 0)
{
[NSException raise: NSFileHandleOperationException
format: @"truncation failed"];
}
[self seekToFileOffset: pos];
}

- (BOOL) truncateAtOffset: (unsigned long long)offset
error: (out NSError **)error
{
Expand All @@ -1746,6 +1785,21 @@ - (BOOL) truncateAtOffset: (unsigned long long)offset
return YES;
}

- (void) truncateFileAtOffset: (unsigned long long)pos
{
if (!(isStandardFile && descriptor >= 0))
{
[NSException raise: NSFileHandleOperationException
format: @"attempt to truncate invalid file"];
}
if (ftruncate(descriptor, pos) < 0)
{
[NSException raise: NSFileHandleOperationException
format: @"truncation failed"];
}
[self seekToFileOffset: pos];
}

- (void) writeInBackgroundAndNotify: (NSData*)item forModes: (NSArray*)modes
{
NSMutableDictionary* info;
Expand Down
21 changes: 21 additions & 0 deletions Source/NSFileHandle.m
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,13 @@ - (void) waitForDataInBackgroundAndNotifyForModes: (NSArray*)modes

// Seeking within a file

- (BOOL) getOffset: (out unsigned long long *)offsetInFile
error: (out NSError **)error
{
[self subclassResponsibility: _cmd];
return NO;
}

/**
* Return current position in file, or raises exception if instance does
* not represent a regular file.
Expand All @@ -429,6 +436,20 @@ - (unsigned long long) seekToEndOfFile
return 0;
}

- (BOOL) seekToEndReturningOffset: (out unsigned long long *)offsetInFile
error: (out NSError **)error
{
[self subclassResponsibility: _cmd];
return NO;
}

- (BOOL) seekToOffset: (unsigned long long)offset
error: (out NSError **)error
{
[self subclassResponsibility: _cmd];
return NO;
}

/**
* Position file pointer at pos, raising exception if instance does
* not represent a regular file.
Expand Down

0 comments on commit fe5efb6

Please sign in to comment.