PyCatFile 0.14.18__tar.gz → 0.15.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyCatFile
3
- Version: 0.14.18
3
+ Version: 0.15.0
4
4
  Summary: A tar like file format name catfile after unix cat command (concatenate files) .
5
5
  Home-page: https://github.com/GameMaker2k/PyCatFile
6
6
  Download-URL: https://github.com/GameMaker2k/PyCatFile/archive/master.tar.gz
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyCatFile
3
- Version: 0.14.18
3
+ Version: 0.15.0
4
4
  Summary: A tar like file format name catfile after unix cat command (concatenate files) .
5
5
  Home-page: https://github.com/GameMaker2k/PyCatFile
6
6
  Download-URL: https://github.com/GameMaker2k/PyCatFile/archive/master.tar.gz
@@ -14,7 +14,7 @@
14
14
  Copyright 2018-2024 Game Maker 2k - http://intdb.sourceforge.net/
15
15
  Copyright 2018-2024 Kazuki Przyborowski - https://github.com/KazukiPrzyborowski
16
16
 
17
- $FileInfo: catfile.py - Last Update: 12/4/2024 Ver. 0.14.18 RC 1 - Author: cooldude2k $
17
+ $FileInfo: catfile.py - Last Update: 12/6/2024 Ver. 0.15.0 RC 1 - Author: cooldude2k $
18
18
  '''
19
19
 
20
20
  from __future__ import absolute_import, division, print_function, unicode_literals, generators, with_statement, nested_scopes
@@ -14,7 +14,7 @@
14
14
  Copyright 2018-2024 Game Maker 2k - http://intdb.sourceforge.net/
15
15
  Copyright 2018-2024 Kazuki Przyborowski - https://github.com/KazukiPrzyborowski
16
16
 
17
- $FileInfo: neocatfile.py - Last Update: 12/4/2024 Ver. 0.14.18 RC 1 - Author: cooldude2k $
17
+ $FileInfo: neocatfile.py - Last Update: 12/6/2024 Ver. 0.15.0 RC 1 - Author: cooldude2k $
18
18
  '''
19
19
 
20
20
  from __future__ import absolute_import, division, print_function, unicode_literals, generators, with_statement, nested_scopes
@@ -14,7 +14,7 @@
14
14
  Copyright 2018-2024 Game Maker 2k - http://intdb.sourceforge.net/
15
15
  Copyright 2018-2024 Kazuki Przyborowski - https://github.com/KazukiPrzyborowski
16
16
 
17
- $FileInfo: pycatfile.py - Last Update: 12/4/2024 Ver. 0.14.18 RC 1 - Author: cooldude2k $
17
+ $FileInfo: pycatfile.py - Last Update: 12/6/2024 Ver. 0.15.0 RC 1 - Author: cooldude2k $
18
18
  '''
19
19
 
20
20
  from __future__ import absolute_import, division, print_function, unicode_literals, generators, with_statement, nested_scopes
@@ -303,12 +303,12 @@ __file_format_dict__ = {'format_name': __file_format_name__, 'format_magic': __f
303
303
  'format_delimiter': __file_format_delimiter__, 'format_ver': __file_format_ver__, 'new_style': __use_new_style__, 'use_advanced_list': __use_advanced_list__, 'use_alt_inode': __use_alt_inode__}
304
304
  __project__ = __program_name__
305
305
  __project_url__ = "https://github.com/GameMaker2k/PyCatFile"
306
- __version_info__ = (0, 14, 18, "RC 1", 1)
307
- __version_date_info__ = (2024, 12, 4, "RC 1", 1)
306
+ __version_info__ = (0, 15, 0, "RC 1", 1)
307
+ __version_date_info__ = (2024, 12, 6, "RC 1", 1)
308
308
  __version_date__ = str(__version_date_info__[0]) + "." + str(
309
309
  __version_date_info__[1]).zfill(2) + "." + str(__version_date_info__[2]).zfill(2)
310
310
  __revision__ = __version_info__[3]
311
- __revision_id__ = "$Id: c90abbff71adacac4de6eafc28f0cff10ced1e38 $"
311
+ __revision_id__ = "$Id: eb6da8da544b0f7fab37dddab5ce3751d196ab97 $"
312
312
  if(__version_info__[4] is not None):
313
313
  __version_date_plusrc__ = __version_date__ + \
314
314
  "-" + str(__version_date_info__[4])
@@ -693,10 +693,29 @@ def ListDirAdvanced(dirpath, followlink=False, duplicates=False, include_regex=N
693
693
  if ((not include_pattern or include_pattern.search(path)) and
694
694
  (not exclude_pattern or not exclude_pattern.search(path))):
695
695
  retlist.append(path)
696
-
697
696
  return retlist
698
697
 
699
698
 
699
+ def GetTotalSize(file_list):
700
+ """
701
+ Calculate the total size of all files in the provided list.
702
+
703
+ Parameters:
704
+ file_list (list): List of file paths.
705
+
706
+ Returns:
707
+ int: Total size of all files in bytes.
708
+ """
709
+ total_size = 0
710
+ for item in file_list:
711
+ if os.path.isfile(item): # Ensure it's a file
712
+ try:
713
+ total_size += os.path.getsize(item)
714
+ except OSError as e:
715
+ sys.stderr.write("Error accessing file {}: {}\n".format(item, e))
716
+ return total_size
717
+
718
+
700
719
  def create_alias_function(prefix, base_name, suffix, target_function):
701
720
  # Define a new function that wraps the target function
702
721
  def alias_function(*args, **kwargs):
@@ -1468,6 +1487,8 @@ def ValidateFileChecksum(infile, checksumtype="crc32", inchecksum="0", formatspe
1468
1487
 
1469
1488
 
1470
1489
  def ReadTillNullByteOld(fp, delimiter=__file_format_dict__['format_delimiter']):
1490
+ if(not hasattr(fp, "read")):
1491
+ return False
1471
1492
  curbyte = b""
1472
1493
  curfullbyte = b""
1473
1494
  nullbyte = delimiter.encode("UTF-8")
@@ -1484,6 +1505,8 @@ def ReadUntilNullByteOld(fp, delimiter=__file_format_dict__['format_delimiter'])
1484
1505
 
1485
1506
 
1486
1507
  def ReadTillNullByteAlt(fp, delimiter=__file_format_dict__['format_delimiter'], chunk_size=1024, max_read=1024000):
1508
+ if(not hasattr(fp, "read")):
1509
+ return False
1487
1510
  delimiter = delimiter.encode('UTF-8') # Ensure the delimiter is in bytes
1488
1511
  buffer = bytearray()
1489
1512
  total_read = 0
@@ -1529,6 +1552,8 @@ def ReadUntilNullByteAlt(fp, delimiter=__file_format_dict__['format_delimiter'],
1529
1552
 
1530
1553
 
1531
1554
  def ReadTillNullByte(fp, delimiter=__file_format_dict__['format_delimiter'], max_read=1024000):
1555
+ if(not hasattr(fp, "read")):
1556
+ return False
1532
1557
  curfullbyte = bytearray()
1533
1558
  nullbyte = delimiter.encode("UTF-8")
1534
1559
  total_read = 0 # Track the total number of bytes read
@@ -1559,6 +1584,8 @@ def ReadUntilNullByte(fp, delimiter=__file_format_dict__['format_delimiter'], ma
1559
1584
 
1560
1585
 
1561
1586
  def ReadTillNullByteByNum(fp, delimiter=__file_format_dict__['format_delimiter'], num_delimiters=1, chunk_size=1024, max_read=1024000):
1587
+ if(not hasattr(fp, "read")):
1588
+ return False
1562
1589
  delimiter = delimiter.encode('UTF-8') # Ensure the delimiter is in bytes
1563
1590
  buffer = bytearray()
1564
1591
  total_read = 0
@@ -1619,6 +1646,8 @@ def SeekToEndOfFile(fp):
1619
1646
 
1620
1647
 
1621
1648
  def ReadFileHeaderData(fp, rounds=0, delimiter=__file_format_dict__['format_delimiter']):
1649
+ if(not hasattr(fp, "read")):
1650
+ return False
1622
1651
  rocount = 0
1623
1652
  roend = int(rounds)
1624
1653
  HeaderOut = []
@@ -1629,6 +1658,8 @@ def ReadFileHeaderData(fp, rounds=0, delimiter=__file_format_dict__['format_deli
1629
1658
 
1630
1659
 
1631
1660
  def ReadFileHeaderDataBySize(fp, delimiter=__file_format_dict__['format_delimiter']):
1661
+ if(not hasattr(fp, "read")):
1662
+ return False
1632
1663
  headerpresize = ReadTillNullByte(fp, delimiter)
1633
1664
  headersize = int(headerpresize, 16)
1634
1665
  if(headersize <= 0):
@@ -1645,6 +1676,8 @@ def ReadFileHeaderDataBySize(fp, delimiter=__file_format_dict__['format_delimite
1645
1676
 
1646
1677
 
1647
1678
  def ReadFileHeaderDataWoSize(fp, delimiter=__file_format_dict__['format_delimiter']):
1679
+ if(not hasattr(fp, "read")):
1680
+ return False
1648
1681
  preheaderdata = ReadFileHeaderData(fp, 2, delimiter)
1649
1682
  headersize = int(preheaderdata[0], 16)
1650
1683
  headernumfields = int(preheaderdata[1], 16)
@@ -1657,6 +1690,8 @@ def ReadFileHeaderDataWoSize(fp, delimiter=__file_format_dict__['format_delimite
1657
1690
 
1658
1691
 
1659
1692
  def ReadFileHeaderDataBySizeWithContent(fp, listonly=False, uncompress=True, skipchecksum=False, formatspecs=__file_format_dict__):
1693
+ if(not hasattr(fp, "read")):
1694
+ return False
1660
1695
  formatspecs = FormatSpecsListToDict(formatspecs)
1661
1696
  delimiter = formatspecs['format_delimiter']
1662
1697
  fheaderstart = fp.tell()
@@ -1730,6 +1765,8 @@ def ReadFileHeaderDataBySizeWithContent(fp, listonly=False, uncompress=True, ski
1730
1765
 
1731
1766
 
1732
1767
  def ReadFileHeaderDataBySizeWithContentToArray(fp, listonly=False, contentasfile=True, uncompress=True, skipchecksum=False, formatspecs=__file_format_dict__):
1768
+ if(not hasattr(fp, "read")):
1769
+ return False
1733
1770
  formatspecs = FormatSpecsListToDict(formatspecs)
1734
1771
  delimiter = formatspecs['format_delimiter']
1735
1772
  fheaderstart = fp.tell()
@@ -1848,6 +1885,8 @@ def ReadFileHeaderDataBySizeWithContentToArray(fp, listonly=False, contentasfile
1848
1885
 
1849
1886
 
1850
1887
  def ReadFileHeaderDataBySizeWithContentToList(fp, listonly=False, uncompress=True, skipchecksum=False, formatspecs=__file_format_dict__):
1888
+ if(not hasattr(fp, "read")):
1889
+ return False
1851
1890
  formatspecs = FormatSpecsListToDict(formatspecs)
1852
1891
  delimiter = formatspecs['format_delimiter']
1853
1892
  fheaderstart = fp.tell()
@@ -1963,6 +2002,8 @@ def ReadFileHeaderDataBySizeWithContentToList(fp, listonly=False, uncompress=Tru
1963
2002
 
1964
2003
 
1965
2004
  def ReadFileDataBySizeWithContent(fp, listonly=False, uncompress=True, skipchecksum=False, formatspecs=__file_format_dict__):
2005
+ if(not hasattr(fp, "read")):
2006
+ return False
1966
2007
  formatspecs = FormatSpecsListToDict(formatspecs)
1967
2008
  delimiter = formatspecs['format_delimiter']
1968
2009
  curloc = fp.tell()
@@ -1994,6 +2035,8 @@ def ReadFileDataBySizeWithContent(fp, listonly=False, uncompress=True, skipcheck
1994
2035
 
1995
2036
 
1996
2037
  def ReadFileDataBySizeWithContentToArray(fp, seekstart=0, seekend=0, listonly=False, contentasfile=True, uncompress=True, skipchecksum=False, formatspecs=__file_format_dict__):
2038
+ if(not hasattr(fp, "read")):
2039
+ return False
1997
2040
  formatspecs = FormatSpecsListToDict(formatspecs)
1998
2041
  delimiter = formatspecs['format_delimiter']
1999
2042
  curloc = fp.tell()
@@ -2097,6 +2140,8 @@ def ReadFileDataBySizeWithContentToArray(fp, seekstart=0, seekend=0, listonly=Fa
2097
2140
 
2098
2141
 
2099
2142
  def ReadFileDataBySizeWithContentToList(fp, seekstart=0, seekend=0, listonly=False, uncompress=True, skipchecksum=False, formatspecs=__file_format_dict__):
2143
+ if(not hasattr(fp, "read")):
2144
+ return False
2100
2145
  formatspecs = FormatSpecsListToDict(formatspecs)
2101
2146
  delimiter = formatspecs['format_delimiter']
2102
2147
  curloc = fp.tell()
@@ -2343,6 +2388,8 @@ def AppendNullBytes(indata=[], delimiter=__file_format_dict__['format_delimiter'
2343
2388
 
2344
2389
 
2345
2390
  def AppendFileHeader(fp, numfiles, checksumtype="crc32", formatspecs=__file_format_dict__):
2391
+ if(not hasattr(fp, "write")):
2392
+ return False
2346
2393
  formatspecs = FormatSpecsListToDict(formatspecs)
2347
2394
  delimiter = formatspecs['format_delimiter']
2348
2395
  catver = formatspecs['format_ver']
@@ -2361,6 +2408,8 @@ def AppendFileHeader(fp, numfiles, checksumtype="crc32", formatspecs=__file_form
2361
2408
  try:
2362
2409
  fp.flush()
2363
2410
  os.fsync(fp.fileno())
2411
+ if(hasattr(os, "sync")):
2412
+ os.sync()
2364
2413
  except io.UnsupportedOperation:
2365
2414
  pass
2366
2415
  except AttributeError:
@@ -2404,6 +2453,8 @@ def MakeEmptyFile(outfile, compression="auto", compressionlevel=None, checksumty
2404
2453
  try:
2405
2454
  catfp.flush()
2406
2455
  os.fsync(catfp.fileno())
2456
+ if(hasattr(os, "sync")):
2457
+ os.sync()
2407
2458
  except io.UnsupportedOperation:
2408
2459
  pass
2409
2460
  except AttributeError:
@@ -2430,6 +2481,8 @@ def MakeEmptyFile(outfile, compression="auto", compressionlevel=None, checksumty
2430
2481
 
2431
2482
 
2432
2483
  def AppendFileHeaderWithContent(fp, filevalues=[], extradata=[], filecontent="", checksumtype="crc32", formatspecs=__file_format_dict__):
2484
+ if(not hasattr(fp, "write")):
2485
+ return False
2433
2486
  formatspecs = FormatSpecsListToDict(formatspecs)
2434
2487
  extrafields = format(len(extradata), 'x').lower()
2435
2488
  extrasizestr = AppendNullByte(extrafields, formatspecs['format_delimiter'])
@@ -2480,6 +2533,8 @@ def AppendFileHeaderWithContent(fp, filevalues=[], extradata=[], filecontent="",
2480
2533
  try:
2481
2534
  fp.flush()
2482
2535
  os.fsync(fp.fileno())
2536
+ if(hasattr(os, "sync")):
2537
+ os.sync()
2483
2538
  except io.UnsupportedOperation:
2484
2539
  pass
2485
2540
  except AttributeError:
@@ -2490,6 +2545,8 @@ def AppendFileHeaderWithContent(fp, filevalues=[], extradata=[], filecontent="",
2490
2545
 
2491
2546
 
2492
2547
  def AppendFilesWithContent(infiles, fp, dirlistfromtxt=False, filevalues=[], extradata=[], compression="auto", compresswholefile=True, compressionlevel=None, followlink=False, checksumtype="crc32", formatspecs=__file_format_dict__, verbose=False):
2548
+ if(not hasattr(fp, "write")):
2549
+ return False
2493
2550
  formatspecs = FormatSpecsListToDict(formatspecs)
2494
2551
  advancedlist = formatspecs['use_advanced_list']
2495
2552
  altinode = formatspecs['use_alt_inode']
@@ -2516,6 +2573,7 @@ def AppendFilesWithContent(infiles, fp, dirlistfromtxt=False, filevalues=[], ext
2516
2573
  GetDirList = ListDirAdvanced(infilelist, followlink, False)
2517
2574
  else:
2518
2575
  GetDirList = ListDir(infilelist, followlink, False)
2576
+ FullSizeFiles = GetTotalSize(GetDirList)
2519
2577
  if(not GetDirList):
2520
2578
  return False
2521
2579
  curinode = 0
@@ -2527,6 +2585,7 @@ def AppendFilesWithContent(infiles, fp, dirlistfromtxt=False, filevalues=[], ext
2527
2585
  numfiles = int(len(GetDirList))
2528
2586
  fnumfiles = format(numfiles, 'x').lower()
2529
2587
  AppendFileHeader(fp, fnumfiles, checksumtype, formatspecs)
2588
+ FullSizeFilesAlt = 0
2530
2589
  for curfname in GetDirList:
2531
2590
  if(re.findall("^[.|/]", curfname)):
2532
2591
  fname = curfname
@@ -2541,8 +2600,14 @@ def AppendFilesWithContent(infiles, fp, dirlistfromtxt=False, filevalues=[], ext
2541
2600
  fpremode = fstatinfo.st_mode
2542
2601
  finode = fstatinfo.st_ino
2543
2602
  flinkcount = fstatinfo.st_nlink
2603
+ try:
2604
+ FullSizeFilesAlt += fstatinfo.st_rsize
2605
+ except AttributeError:
2606
+ FullSizeFilesAlt += fstatinfo.st_size
2544
2607
  ftype = 0
2545
- if(stat.S_ISREG(fpremode)):
2608
+ if(hasattr(os.path, "isjunction") and os.path.isjunction(fname)):
2609
+ ftype = 13
2610
+ elif(stat.S_ISREG(fpremode)):
2546
2611
  ftype = 0
2547
2612
  elif(stat.S_ISLNK(fpremode)):
2548
2613
  ftype = 2
@@ -2562,36 +2627,44 @@ def AppendFilesWithContent(infiles, fp, dirlistfromtxt=False, filevalues=[], ext
2562
2627
  ftype = 10
2563
2628
  elif(hasattr(stat, "S_ISWHT") and stat.S_ISWHT(fpremode)):
2564
2629
  ftype = 11
2630
+ elif(fstatinfo.st_blocks * 512 < fstatinfo.st_size):
2631
+ ftype = 12
2565
2632
  else:
2566
2633
  ftype = 0
2567
2634
  flinkname = ""
2568
2635
  fcurfid = format(int(curfid), 'x').lower()
2569
- if(not followlink and finode != 0):
2570
- if(ftype != 1):
2571
- if(finode in inodelist):
2636
+ if not followlink and finode != 0:
2637
+ unique_id = (fstatinfo.st_dev, finode)
2638
+ if ftype != 1:
2639
+ if unique_id in inodelist:
2640
+ # Hard link detected
2572
2641
  ftype = 1
2573
- flinkname = inodetofile[finode]
2574
- if(altinode):
2575
- fcurinode = format(int(finode), 'x').lower()
2642
+ flinkname = inodetofile[unique_id]
2643
+ if altinode:
2644
+ fcurinode = format(int(unique_id[1]), 'x').lower()
2576
2645
  else:
2577
- fcurinode = format(
2578
- int(inodetocatinode[finode]), 'x').lower()
2579
- if(finode not in inodelist):
2580
- inodelist.append(finode)
2581
- inodetofile.update({finode: fname})
2582
- inodetocatinode.update({finode: curinode})
2583
- if(altinode):
2584
- fcurinode = format(int(finode), 'x').lower()
2646
+ fcurinode = format(int(inodetocatinode[unique_id]), 'x').lower()
2647
+ else:
2648
+ # New inode
2649
+ inodelist.append(unique_id)
2650
+ inodetofile[unique_id] = fname
2651
+ inodetocatinode[unique_id] = curinode
2652
+ if altinode:
2653
+ fcurinode = format(int(unique_id[1]), 'x').lower()
2585
2654
  else:
2586
2655
  fcurinode = format(int(curinode), 'x').lower()
2587
- curinode = curinode + 1
2656
+ curinode += 1
2588
2657
  else:
2658
+ # Handle cases where inodes are not supported or symlinks are followed
2589
2659
  fcurinode = format(int(curinode), 'x').lower()
2590
- curinode = curinode + 1
2660
+ curinode += 1
2591
2661
  curfid = curfid + 1
2592
2662
  if(ftype == 2):
2593
2663
  flinkname = os.readlink(fname)
2594
- fdev = fstatinfo.st_dev
2664
+ try:
2665
+ fdev = fstatinfo.st_rdev
2666
+ except AttributeError:
2667
+ fdev = 0
2595
2668
  getfdev = GetDevMajorMinor(fdev)
2596
2669
  fdev_minor = getfdev[0]
2597
2670
  fdev_major = getfdev[1]
@@ -2750,6 +2823,8 @@ def AppendFilesWithContent(infiles, fp, dirlistfromtxt=False, filevalues=[], ext
2750
2823
 
2751
2824
 
2752
2825
  def AppendListsWithContent(inlist, fp, dirlistfromtxt=False, filevalues=[], extradata=[], compression="auto", compresswholefile=True, compressionlevel=None, followlink=False, checksumtype="crc32", formatspecs=__file_format_dict__, verbose=False):
2826
+ if(not hasattr(fp, "write")):
2827
+ return False
2753
2828
  formatspecs = FormatSpecsListToDict(formatspecs)
2754
2829
  if(verbose):
2755
2830
  logging.basicConfig(format="%(message)s",
@@ -2845,6 +2920,8 @@ def AppendFilesWithContentToOutFile(infiles, outfile, dirlistfromtxt=False, comp
2845
2920
  try:
2846
2921
  catfp.flush()
2847
2922
  os.fsync(catfp.fileno())
2923
+ if(hasattr(os, "sync")):
2924
+ os.sync()
2848
2925
  except io.UnsupportedOperation:
2849
2926
  pass
2850
2927
  except AttributeError:
@@ -2899,6 +2976,8 @@ def AppendListsWithContentToOutFile(inlist, outfile, dirlistfromtxt=False, compr
2899
2976
  try:
2900
2977
  catfp.flush()
2901
2978
  os.fsync(catfp.fileno())
2979
+ if(hasattr(os, "sync")):
2980
+ os.sync()
2902
2981
  except io.UnsupportedOperation:
2903
2982
  pass
2904
2983
  except AttributeError:
@@ -3162,7 +3241,7 @@ def GetCompressionMimeType(infile, formatspecs=__file_format_dict__):
3162
3241
 
3163
3242
  def UncompressArchiveFile(fp, formatspecs=__file_format_dict__):
3164
3243
  formatspecs = FormatSpecsListToDict(formatspecs)
3165
- if(not hasattr(fp, "read") and not hasattr(fp, "write")):
3244
+ if(not hasattr(fp, "read")):
3166
3245
  return False
3167
3246
  compresscheck = CheckCompressionType(fp, formatspecs, False)
3168
3247
  if(compresscheck == "gzip" and compresscheck in compressionsupport):
@@ -3406,7 +3485,7 @@ def GZipCompress(data, compresslevel=9):
3406
3485
 
3407
3486
  def CompressArchiveFile(fp, compression="auto", compressionlevel=None, formatspecs=__file_format_dict__):
3408
3487
  formatspecs = FormatSpecsListToDict(formatspecs)
3409
- if(not hasattr(fp, "read") and not hasattr(fp, "write")):
3488
+ if(not hasattr(fp, "read")):
3410
3489
  return False
3411
3490
  fp.seek(0, 0)
3412
3491
  if(not compression or compression == "catfile" or compression == formatspecs['format_lower']):
@@ -3684,6 +3763,7 @@ def PackArchiveFile(infiles, outfile, dirlistfromtxt=False, compression="auto",
3684
3763
  GetDirList = ListDirAdvanced(infilelist, followlink, False)
3685
3764
  else:
3686
3765
  GetDirList = ListDir(infilelist, followlink, False)
3766
+ FullSizeFiles = GetTotalSize(GetDirList)
3687
3767
  if(not GetDirList):
3688
3768
  return False
3689
3769
  curinode = 0
@@ -3694,6 +3774,7 @@ def PackArchiveFile(infiles, outfile, dirlistfromtxt=False, compression="auto",
3694
3774
  inodetocatinode = {}
3695
3775
  numfiles = int(len(GetDirList))
3696
3776
  catfp = AppendFileHeader(catfp, numfiles, checksumtype, formatspecs)
3777
+ FullSizeFilesAlt = 0
3697
3778
  for curfname in GetDirList:
3698
3779
  if(re.findall("^[.|/]", curfname)):
3699
3780
  fname = curfname
@@ -3708,8 +3789,14 @@ def PackArchiveFile(infiles, outfile, dirlistfromtxt=False, compression="auto",
3708
3789
  fpremode = fstatinfo.st_mode
3709
3790
  finode = fstatinfo.st_ino
3710
3791
  flinkcount = fstatinfo.st_nlink
3792
+ try:
3793
+ FullSizeFilesAlt += fstatinfo.st_rsize
3794
+ except AttributeError:
3795
+ FullSizeFilesAlt += fstatinfo.st_size
3711
3796
  ftype = 0
3712
- if(stat.S_ISREG(fpremode)):
3797
+ if(hasattr(os.path, "isjunction") and os.path.isjunction(fname)):
3798
+ ftype = 13
3799
+ elif(stat.S_ISREG(fpremode)):
3713
3800
  ftype = 0
3714
3801
  elif(stat.S_ISLNK(fpremode)):
3715
3802
  ftype = 2
@@ -3729,36 +3816,44 @@ def PackArchiveFile(infiles, outfile, dirlistfromtxt=False, compression="auto",
3729
3816
  ftype = 10
3730
3817
  elif(hasattr(stat, "S_ISWHT") and stat.S_ISWHT(fpremode)):
3731
3818
  ftype = 11
3819
+ elif(fstatinfo.st_blocks * 512 < fstatinfo.st_size):
3820
+ ftype = 12
3732
3821
  else:
3733
3822
  ftype = 0
3734
3823
  flinkname = ""
3735
3824
  fcurfid = format(int(curfid), 'x').lower()
3736
- if(not followlink and finode != 0):
3737
- if(ftype != 1):
3738
- if(finode in inodelist):
3825
+ if not followlink and finode != 0:
3826
+ unique_id = (fstatinfo.st_dev, finode)
3827
+ if ftype != 1:
3828
+ if unique_id in inodelist:
3829
+ # Hard link detected
3739
3830
  ftype = 1
3740
- flinkname = inodetofile[finode]
3741
- if(altinode):
3742
- fcurinode = format(int(finode), 'x').lower()
3831
+ flinkname = inodetofile[unique_id]
3832
+ if altinode:
3833
+ fcurinode = format(int(unique_id[1]), 'x').lower()
3743
3834
  else:
3744
- fcurinode = format(
3745
- int(inodetocatinode[finode]), 'x').lower()
3746
- if(finode not in inodelist):
3747
- inodelist.append(finode)
3748
- inodetofile.update({finode: fname})
3749
- inodetocatinode.update({finode: curinode})
3750
- if(altinode):
3751
- fcurinode = format(int(finode), 'x').lower()
3835
+ fcurinode = format(int(inodetocatinode[unique_id]), 'x').lower()
3836
+ else:
3837
+ # New inode
3838
+ inodelist.append(unique_id)
3839
+ inodetofile[unique_id] = fname
3840
+ inodetocatinode[unique_id] = curinode
3841
+ if altinode:
3842
+ fcurinode = format(int(unique_id[1]), 'x').lower()
3752
3843
  else:
3753
3844
  fcurinode = format(int(curinode), 'x').lower()
3754
- curinode = curinode + 1
3845
+ curinode += 1
3755
3846
  else:
3847
+ # Handle cases where inodes are not supported or symlinks are followed
3756
3848
  fcurinode = format(int(curinode), 'x').lower()
3757
- curinode = curinode + 1
3849
+ curinode += 1
3758
3850
  curfid = curfid + 1
3759
3851
  if(ftype == 2):
3760
3852
  flinkname = os.readlink(fname)
3761
- fdev = fstatinfo.st_dev
3853
+ try:
3854
+ fdev = fstatinfo.st_rdev
3855
+ except AttributeError:
3856
+ fdev = 0
3762
3857
  getfdev = GetDevMajorMinor(fdev)
3763
3858
  fdev_minor = getfdev[0]
3764
3859
  fdev_major = getfdev[1]
@@ -3918,6 +4013,8 @@ def PackArchiveFile(infiles, outfile, dirlistfromtxt=False, compression="auto",
3918
4013
  try:
3919
4014
  catfp.flush()
3920
4015
  os.fsync(catfp.fileno())
4016
+ if(hasattr(os, "sync")):
4017
+ os.sync()
3921
4018
  except io.UnsupportedOperation:
3922
4019
  pass
3923
4020
  except AttributeError:
@@ -4052,9 +4149,6 @@ def PackArchiveFileFromTarFile(infile, outfile, compression="auto", compresswhol
4052
4149
  if(member.isreg()):
4053
4150
  ffullmode = member.mode + stat.S_IFREG
4054
4151
  ftype = 0
4055
- elif(member.isdev()):
4056
- ffullmode = member.mode
4057
- ftype = 7
4058
4152
  elif(member.islnk()):
4059
4153
  ffullmode = member.mode + stat.S_IFREG
4060
4154
  ftype = 1
@@ -4073,9 +4167,12 @@ def PackArchiveFileFromTarFile(infile, outfile, compression="auto", compresswhol
4073
4167
  elif(member.isfifo()):
4074
4168
  ffullmode = member.mode + stat.S_IFIFO
4075
4169
  ftype = 6
4076
- elif(member.issparse()):
4170
+ elif(hasattr(member, "issparse") and member.issparse()):
4077
4171
  ffullmode = member.mode
4078
4172
  ftype = 12
4173
+ elif(member.isdev()):
4174
+ ffullmode = member.mode
4175
+ ftype = 7
4079
4176
  else:
4080
4177
  ffullmode = member.mode
4081
4178
  ftype = 0
@@ -4174,6 +4271,8 @@ def PackArchiveFileFromTarFile(infile, outfile, compression="auto", compresswhol
4174
4271
  try:
4175
4272
  catfp.flush()
4176
4273
  os.fsync(catfp.fileno())
4274
+ if(hasattr(os, "sync")):
4275
+ os.sync()
4177
4276
  except io.UnsupportedOperation:
4178
4277
  pass
4179
4278
  except AttributeError:
@@ -4440,6 +4539,8 @@ def PackArchiveFileFromZipFile(infile, outfile, compression="auto", compresswhol
4440
4539
  try:
4441
4540
  catfp.flush()
4442
4541
  os.fsync(catfp.fileno())
4542
+ if(hasattr(os, "sync")):
4543
+ os.sync()
4443
4544
  except io.UnsupportedOperation:
4444
4545
  pass
4445
4546
  except AttributeError:
@@ -4530,6 +4631,8 @@ if(rarfile_support):
4530
4631
  try:
4531
4632
  catfp.flush()
4532
4633
  os.fsync(catfp.fileno())
4634
+ if(hasattr(os, "sync")):
4635
+ os.sync()
4533
4636
  except io.UnsupportedOperation:
4534
4637
  pass
4535
4638
  except AttributeError:
@@ -4736,6 +4839,8 @@ if(rarfile_support):
4736
4839
  try:
4737
4840
  catfp.flush()
4738
4841
  os.fsync(catfp.fileno())
4842
+ if(hasattr(os, "sync")):
4843
+ os.sync()
4739
4844
  except io.UnsupportedOperation:
4740
4845
  pass
4741
4846
  except AttributeError:
@@ -4965,6 +5070,8 @@ if(py7zr_support):
4965
5070
  try:
4966
5071
  catfp.flush()
4967
5072
  os.fsync(catfp.fileno())
5073
+ if(hasattr(os, "sync")):
5074
+ os.sync()
4968
5075
  except io.UnsupportedOperation:
4969
5076
  pass
4970
5077
  except AttributeError:
@@ -6279,6 +6386,7 @@ def ListDirToArrayAlt(infiles, dirlistfromtxt=False, followlink=False, listonly=
6279
6386
  GetDirList = ListDirAdvanced(infilelist, followlink, False)
6280
6387
  else:
6281
6388
  GetDirList = ListDir(infilelist, followlink, False)
6389
+ FullSizeFiles = GetTotalSize(GetDirList)
6282
6390
  if(not GetDirList):
6283
6391
  return False
6284
6392
  curinode = 0
@@ -6306,6 +6414,7 @@ def ListDirToArrayAlt(infiles, dirlistfromtxt=False, followlink=False, listonly=
6306
6414
  fheadtell = len(fileheader)
6307
6415
  catlist = {'fnumfiles': fnumfiles, 'fformat': catversions[0], 'fversion': catversions[1],
6308
6416
  'fformatspecs': formatspecs, 'fchecksumtype': checksumtype, 'fheaderchecksum': catfileheadercshex, 'ffilelist': []}
6417
+ FullSizeFilesAlt = 0
6309
6418
  for curfname in GetDirList:
6310
6419
  catfhstart = fheadtell
6311
6420
  if(re.findall("^[.|/]", curfname)):
@@ -6321,8 +6430,14 @@ def ListDirToArrayAlt(infiles, dirlistfromtxt=False, followlink=False, listonly=
6321
6430
  fpremode = fstatinfo.st_mode
6322
6431
  finode = fstatinfo.st_ino
6323
6432
  flinkcount = fstatinfo.st_nlink
6433
+ try:
6434
+ FullSizeFilesAlt += fstatinfo.st_rsize
6435
+ except AttributeError:
6436
+ FullSizeFilesAlt += fstatinfo.st_size
6324
6437
  ftype = 0
6325
- if(stat.S_ISREG(fpremode)):
6438
+ if(hasattr(os.path, "isjunction") and os.path.isjunction(fname)):
6439
+ ftype = 13
6440
+ elif(stat.S_ISREG(fpremode)):
6326
6441
  ftype = 0
6327
6442
  elif(stat.S_ISLNK(fpremode)):
6328
6443
  ftype = 2
@@ -6342,36 +6457,45 @@ def ListDirToArrayAlt(infiles, dirlistfromtxt=False, followlink=False, listonly=
6342
6457
  ftype = 10
6343
6458
  elif(hasattr(stat, "S_ISWHT") and stat.S_ISWHT(fpremode)):
6344
6459
  ftype = 11
6460
+ elif(fstatinfo.st_blocks * 512 < fstatinfo.st_size):
6461
+ ftype = 12
6345
6462
  else:
6346
6463
  ftype = 0
6347
6464
  flinkname = ""
6348
6465
  fbasedir = os.path.dirname(fname)
6349
6466
  fcurfid = curfid
6350
- if(not followlink and finode != 0):
6351
- if(ftype != 1):
6352
- if(finode in inodelist):
6467
+ if not followlink and finode != 0:
6468
+ unique_id = (fstatinfo.st_dev, finode)
6469
+ if ftype != 1:
6470
+ if unique_id in inodelist:
6471
+ # Hard link detected
6353
6472
  ftype = 1
6354
- flinkname = inodetofile[finode]
6355
- if(altinode):
6356
- fcurinode = finode
6473
+ flinkname = inodetofile[unique_id]
6474
+ if altinode:
6475
+ fcurinode = format(int(unique_id[1]), 'x').lower()
6357
6476
  else:
6358
- fcurinode = inodetocatinode[finode]
6359
- if(finode not in inodelist):
6360
- inodelist.append(finode)
6361
- inodetofile.update({finode: fname})
6362
- inodetocatinode.update({finode: curinode})
6363
- if(altinode):
6364
- fcurinode = finode
6477
+ fcurinode = format(int(inodetocatinode[unique_id]), 'x').lower()
6478
+ else:
6479
+ # New inode
6480
+ inodelist.append(unique_id)
6481
+ inodetofile[unique_id] = fname
6482
+ inodetocatinode[unique_id] = curinode
6483
+ if altinode:
6484
+ fcurinode = format(int(unique_id[1]), 'x').lower()
6365
6485
  else:
6366
- fcurinode = curinode
6367
- curinode = curinode + 1
6486
+ fcurinode = format(int(curinode), 'x').lower()
6487
+ curinode += 1
6368
6488
  else:
6369
- fcurinode = curinode
6370
- curinode = curinode + 1
6489
+ # Handle cases where inodes are not supported or symlinks are followed
6490
+ fcurinode = format(int(curinode), 'x').lower()
6491
+ curinode += 1
6371
6492
  curfid = curfid + 1
6372
6493
  if(ftype == 2):
6373
6494
  flinkname = os.readlink(fname)
6374
- fdev = fstatinfo.st_dev
6495
+ try:
6496
+ fdev = fstatinfo.st_rdev
6497
+ except AttributeError:
6498
+ fdev = 0
6375
6499
  getfdev = GetDevMajorMinor(fdev)
6376
6500
  fdev_minor = getfdev[0]
6377
6501
  fdev_major = getfdev[1]
@@ -6572,9 +6696,6 @@ def TarFileToArrayAlt(infile, listonly=False, contentasfile=True, checksumtype="
6572
6696
  if(member.isreg()):
6573
6697
  ffullmode = member.mode + stat.S_IFREG
6574
6698
  ftype = 0
6575
- elif(member.isdev()):
6576
- ffullmode = member.mode
6577
- ftype = 7
6578
6699
  elif(member.islnk()):
6579
6700
  ffullmode = member.mode + stat.S_IFREG
6580
6701
  ftype = 1
@@ -6593,9 +6714,12 @@ def TarFileToArrayAlt(infile, listonly=False, contentasfile=True, checksumtype="
6593
6714
  elif(member.isfifo()):
6594
6715
  ffullmode = member.mode + stat.S_IFIFO
6595
6716
  ftype = 6
6596
- elif(member.issparse()):
6717
+ elif(hasattr(member, "issparse") and member.issparse()):
6597
6718
  ffullmode = member.mode
6598
6719
  ftype = 12
6720
+ elif(member.isdev()):
6721
+ ffullmode = member.mode
6722
+ ftype = 7
6599
6723
  else:
6600
6724
  ffullmode = member.mode
6601
6725
  ftype = 0
@@ -7717,6 +7841,8 @@ def RePackArchiveFile(infile, outfile, compression="auto", compresswholefile=Tru
7717
7841
  try:
7718
7842
  catfp.flush()
7719
7843
  os.fsync(catfp.fileno())
7844
+ if(hasattr(os, "sync")):
7845
+ os.sync()
7720
7846
  except io.UnsupportedOperation:
7721
7847
  pass
7722
7848
  except AttributeError:
@@ -7832,6 +7958,8 @@ def UnPackArchiveFile(infile, outdir=None, followlink=False, seekstart=0, seeken
7832
7958
  try:
7833
7959
  fpc.flush()
7834
7960
  os.fsync(fpc.fileno())
7961
+ if(hasattr(os, "sync")):
7962
+ os.sync()
7835
7963
  except io.UnsupportedOperation:
7836
7964
  pass
7837
7965
  except AttributeError:
@@ -7882,6 +8010,8 @@ def UnPackArchiveFile(infile, outdir=None, followlink=False, seekstart=0, seeken
7882
8010
  try:
7883
8011
  fpc.flush()
7884
8012
  os.fsync(fpc.fileno())
8013
+ if(hasattr(os, "sync")):
8014
+ os.sync()
7885
8015
  except io.UnsupportedOperation:
7886
8016
  pass
7887
8017
  except AttributeError:
@@ -7960,6 +8090,8 @@ def UnPackArchiveFile(infile, outdir=None, followlink=False, seekstart=0, seeken
7960
8090
  try:
7961
8091
  fpc.flush()
7962
8092
  os.fsync(fpc.fileno())
8093
+ if(hasattr(os, "sync")):
8094
+ os.sync()
7963
8095
  except io.UnsupportedOperation:
7964
8096
  pass
7965
8097
  except AttributeError:
@@ -8184,9 +8316,15 @@ def TarFileListFiles(infile, verbose=False, returnfp=False):
8184
8316
  elif(member.isfifo()):
8185
8317
  ffullmode = member.mode + stat.S_IFIFO
8186
8318
  ftype = 6
8187
- elif(member.issparse()):
8319
+ elif(hasattr(member, "issparse") and member.issparse()):
8188
8320
  ffullmode = member.mode
8189
8321
  ftype = 12
8322
+ elif(member.isdev()):
8323
+ ffullmode = member.mode
8324
+ ftype = 7
8325
+ else:
8326
+ ffullmode = member.mode
8327
+ ftype = 0
8190
8328
  if(not verbose):
8191
8329
  VerbosePrintOut(member.name)
8192
8330
  elif(verbose):
@@ -13,7 +13,7 @@
13
13
  Copyright 2016-2024 Game Maker 2k - http://intdb.sourceforge.net/
14
14
  Copyright 2016-2024 Kazuki Przyborowski - https://github.com/KazukiPrzyborowski
15
15
 
16
- $FileInfo: setup.py - Last Update: 12/4/2024 Ver. 0.14.18 RC 1 - Author: cooldude2k $
16
+ $FileInfo: setup.py - Last Update: 12/6/2024 Ver. 0.15.0 RC 1 - Author: cooldude2k $
17
17
  '''
18
18
 
19
19
  import os
File without changes
File without changes
File without changes