Repository: vidstige/ar (language: python)

Issue:
Possible fix for GNU extended filenames
Looks like this line:
https://github.com/vidstige/ar/blob/e0275f79281c1cc5d9f3f4622b8de3f76cf95a42/ar/archive.py#L78

Should be:
```py
end = data.find(b"\n", start)
```

After this fix, I was able to work with my files.
@vidstige please check it out


Discussion / hints:

Fix patch:
diff --git a/ar/archive.py b/ar/archive.py
index 176c651..ac36ab5 100644
--- a/ar/archive.py
+++ b/ar/archive.py
@@ -74,9 +74,11 @@ def open(self, path: Union[str, ArPath], mode='r', encoding='utf-8'):
 
 
 def lookup(data: bytes, offset: int) -> str:
-    start = offset
-    end = data.find(b"\00", start)
-    return data[start:end - 1].decode()
+    for delim in (b"\x00", b"\x2F"):
+        pos = data.find(delim, offset)
+        if pos >= 0:
+            data = data[offset:pos]
+    return data.decode()
 
 
 ENTRY_FORMAT = '16s12s6s6s8s10sbb'


Test patch:
diff --git a/ar/tests/test_roundtrip.py b/ar/tests/test_roundtrip.py
index 5b3dc0c..91bf802 100644
--- a/ar/tests/test_roundtrip.py
+++ b/ar/tests/test_roundtrip.py
@@ -17,14 +17,16 @@ def simple_archive():
 
     (TEST_DATA / 'file0.txt').write_text('Hello')
     (TEST_DATA / 'file1.bin').write_bytes(b'\xc3\x28')  # invalid utf-8 characters
-    subprocess.check_call('ar r test.a file0.txt file1.bin'.split(), cwd=str(TEST_DATA))
+    (TEST_DATA / 'long_file_name_test0.txt').write_text('Hello2')
+    (TEST_DATA / 'long_file_name_test1.bin').write_bytes(b'\xc3\x28')
+    subprocess.check_call('ar r test.a file0.txt file1.bin long_file_name_test0.txt long_file_name_test1.bin'.split(), cwd=str(TEST_DATA))
     return TEST_DATA / 'test.a'
 
 
 def test_list(simple_archive):
     with simple_archive.open('rb') as f:
         archive = Archive(f)
-        assert ['file0.txt', 'file1.bin'] == [entry.name for entry in archive]
+        assert ['file0.txt', 'file1.bin', 'long_file_name_test0.txt', 'long_file_name_test1.bin'] == [entry.name for entry in archive]
 
 
 def test_read_content(simple_archive):
@@ -41,6 +43,20 @@ def test_read_binary(simple_archive):
         file0 = archive.open('file1.bin', 'rb')
         assert file0.read() == b'\xc3\x28'
 
+def test_read_content_ext(simple_archive):
+    with simple_archive.open('rb') as f:
+        archive = Archive(f)
+        file0 = archive.open('long_file_name_test0.txt')
+        assert file0.read(2) == 'He'
+        assert file0.read() == 'llo2'
+
+
+def test_read_binary_ext(simple_archive):
+    with simple_archive.open('rb') as f:
+        archive = Archive(f)
+        file0 = archive.open('long_file_name_test1.bin', 'rb')
+        assert file0.read() == b'\xc3\x28'
+
 
 def test_seek_basic(simple_archive):
     with simple_archive.open('rb') as f:
diff --git a/ar/tests/test_windows.py b/ar/tests/test_windows.py
index c2e1be1..04b4b40 100644
--- a/ar/tests/test_windows.py
+++ b/ar/tests/test_windows.py
@@ -13,7 +13,7 @@
 def test_list():
     with ARCHIVE.open('rb') as f:
         archive = Archive(f)
-        expected = ['x64\\Release\\pch.ob', 'x64\\Release\\MiniLib.ob']
+        expected = ['x64\\Release\\pch.obj', 'x64\\Release\\MiniLib.obj']
         actual = [entry.name for entry in archive]
         assert actual == expected
 
@@ -21,14 +21,14 @@ def test_list():
 def test_read_binary():
     with ARCHIVE.open('rb') as f:
         archive = Archive(f)
-        file0 = archive.open('x64\\Release\\MiniLib.ob', 'rb')
+        file0 = archive.open('x64\\Release\\MiniLib.obj', 'rb')
         assert file0.read(16) == b'\x00\x00\xff\xff\x01\x00d\x86tF\xaee8\xfe\xb3\x0c'
 
 
 def test_seek_basic():
     with ARCHIVE.open('rb') as f:
         archive = Archive(f)
-        file0 = archive.open('x64\\Release\\MiniLib.ob', 'rb')
+        file0 = archive.open('x64\\Release\\MiniLib.obj', 'rb')
         file0.seek(1)
         assert file0.read(3) == b'\x00\xff\xff'
 
@@ -36,7 +36,7 @@ def test_seek_basic():
 def test_tell():
     with ARCHIVE.open('rb') as f:
         archive = Archive(f)
-        file0 = archive.open('x64\\Release\\MiniLib.ob', 'rb')
+        file0 = archive.open('x64\\Release\\MiniLib.obj', 'rb')
         assert file0.tell() == 0
         file0.read(2)
         assert file0.tell() == 2