Skip to content

Commit d04e8a2

Browse files
authored
Add files via upload
1 parent e371028 commit d04e8a2

1 file changed

Lines changed: 161 additions & 63 deletions

File tree

pyfoxfile.py

Lines changed: 161 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,54 @@ def decode_unicode_escape(value):
408408
if(__version_info__[3] is None):
409409
__version__ = str(__version_info__[0]) + "." + str(__version_info__[1]) + "." + str(__version_info__[2])
410410

411+
# ===== Module-level type code table & helpers (reuse anywhere) =====
412+
413+
FT = {
414+
"FILE": 0,
415+
"HARDLINK": 1,
416+
"SYMLINK": 2,
417+
"CHAR": 3,
418+
"BLOCK": 4,
419+
"DIR": 5,
420+
"FIFO": 6,
421+
"FILE_ALT": 7, # treated like regular file
422+
"SOCK": 8,
423+
"DOOR": 9,
424+
"PORT": 10,
425+
"WHT": 11,
426+
"JUNCTION": 13,
427+
}
428+
429+
# Base category for each concrete ftype (no unions here).
430+
BASE_CATEGORY_BY_CODE = {
431+
0: "files",
432+
7: "files",
433+
1: "hardlinks",
434+
2: "symlinks",
435+
3: "character",
436+
4: "block",
437+
5: "directories",
438+
6: "fifo",
439+
8: "sockets",
440+
9: "doors",
441+
10: "ports",
442+
11: "whiteouts",
443+
13: "junctions",
444+
}
445+
446+
# Union categories defined by which base codes should populate them.
447+
UNION_RULES = [
448+
("links", set([FT["HARDLINK"], FT["SYMLINK"]])),
449+
("devices", set([FT["CHAR"], FT["BLOCK"]])),
450+
]
451+
452+
# Deterministic category order (handy for consistent output/printing).
453+
CATEGORY_ORDER = [
454+
"files", "hardlinks", "symlinks", "character", "block",
455+
"directories", "fifo", "sockets", "doors", "ports",
456+
"whiteouts", "junctions", "links", "devices"
457+
]
458+
411459
# Robust bitness detection
412460
# Works on Py2 & Py3, all platforms
413461

@@ -7736,72 +7784,122 @@ def ListDirToArray(infiles, dirlistfromtxt=False, fmttype=__file_format_default_
77367784
return listarrayfiles
77377785

77387786

7787+
# ===== Function (keeps inarray schema; returns entries + indexes) =====
7788+
77397789
def FoxFileArrayToArrayIndex(inarray, returnfp=False):
7740-
if(isinstance(inarray, dict)):
7741-
listarrayfiles = inarray
7742-
else:
7790+
"""
7791+
Build a bidirectional index over an archive listing while preserving the
7792+
input 'inarray' as-is. Python 2/3 compatible, no external deps.
7793+
7794+
Input (unchanged contract):
7795+
inarray: dict with at least:
7796+
- 'ffilelist': list of dicts: {'fname': <str>, 'fid': <any>, 'ftype': <int>}
7797+
- 'fnumfiles': int (expected count)
7798+
- optional 'fp': any (passed through if returnfp=True)
7799+
7800+
Output structure:
7801+
{
7802+
'list': inarray, # alias to original input (not copied)
7803+
'fp': inarray.get('fp') or None,
7804+
'entries': { fid: {'name': fname, 'type': ftype} },
7805+
'indexes': {
7806+
'by_name': { fname: fid },
7807+
'by_type': {
7808+
<category>: {
7809+
'by_name': { fname: fid },
7810+
'by_id': { fid: fname },
7811+
'count': <int>
7812+
}, ...
7813+
}
7814+
},
7815+
'counts': {
7816+
'total': <int>,
7817+
'by_type': { <category>: <int>, ... }
7818+
},
7819+
'unknown_types': { <ftype_int>: [fname, ...] }
7820+
}
7821+
"""
7822+
if not isinstance(inarray, dict):
77437823
return False
7744-
if(not listarrayfiles):
7824+
if not inarray:
77457825
return False
7746-
outarray = {'list': listarrayfiles, 'filetoid': {}, 'idtofile': {}, 'filetypes': {'directories': {'filetoid': {}, 'idtofile': {}}, 'files': {'filetoid': {}, 'idtofile': {}}, 'links': {'filetoid': {}, 'idtofile': {}}, 'symlinks': {'filetoid': {
7747-
}, 'idtofile': {}}, 'hardlinks': {'filetoid': {}, 'idtofile': {}}, 'character': {'filetoid': {}, 'idtofile': {}}, 'block': {'filetoid': {}, 'idtofile': {}}, 'fifo': {'filetoid': {}, 'idtofile': {}}, 'devices': {'filetoid': {}, 'idtofile': {}}}}
7748-
if(returnfp):
7749-
outarray.update({'fp': listarrayfiles['fp']})
7750-
else:
7751-
outarray.update({'fp': None})
7752-
lenlist = len(listarrayfiles['ffilelist'])
7753-
lcfi = 0
7754-
lcfx = int(listarrayfiles['fnumfiles'])
7755-
if(lenlist > listarrayfiles['fnumfiles'] or lenlist < listarrayfiles['fnumfiles']):
7756-
lcfx = int(lenlist)
7757-
else:
7758-
lcfx = int(listarrayfiles['fnumfiles'])
7759-
while(lcfi < lcfx):
7760-
filetoidarray = {listarrayfiles['ffilelist'][lcfi]
7761-
['fname']: listarrayfiles['ffilelist'][lcfi]['fid']}
7762-
idtofilearray = {listarrayfiles['ffilelist'][lcfi]
7763-
['fid']: listarrayfiles['ffilelist'][lcfi]['fname']}
7764-
outarray['filetoid'].update(filetoidarray)
7765-
outarray['idtofile'].update(idtofilearray)
7766-
if(listarrayfiles['ffilelist'][lcfi]['ftype'] == 0 or listarrayfiles['ffilelist'][lcfi]['ftype'] == 7):
7767-
outarray['filetypes']['files']['filetoid'].update(filetoidarray)
7768-
outarray['filetypes']['files']['idtofile'].update(idtofilearray)
7769-
if(listarrayfiles['ffilelist'][lcfi]['ftype'] == 1):
7770-
outarray['filetypes']['hardlinks']['filetoid'].update(
7771-
filetoidarray)
7772-
outarray['filetypes']['hardlinks']['idtofile'].update(
7773-
idtofilearray)
7774-
outarray['filetypes']['links']['filetoid'].update(filetoidarray)
7775-
outarray['filetypes']['links']['idtofile'].update(idtofilearray)
7776-
if(listarrayfiles['ffilelist'][lcfi]['ftype'] == 2):
7777-
outarray['filetypes']['symlinks']['filetoid'].update(filetoidarray)
7778-
outarray['filetypes']['symlinks']['idtofile'].update(idtofilearray)
7779-
outarray['filetypes']['links']['filetoid'].update(filetoidarray)
7780-
outarray['filetypes']['links']['idtofile'].update(idtofilearray)
7781-
if(listarrayfiles['ffilelist'][lcfi]['ftype'] == 3):
7782-
outarray['filetypes']['character']['filetoid'].update(
7783-
filetoidarray)
7784-
outarray['filetypes']['character']['idtofile'].update(
7785-
idtofilearray)
7786-
outarray['filetypes']['devices']['filetoid'].update(filetoidarray)
7787-
outarray['filetypes']['devices']['idtofile'].update(idtofilearray)
7788-
if(listarrayfiles['ffilelist'][lcfi]['ftype'] == 4):
7789-
outarray['filetypes']['block']['filetoid'].update(filetoidarray)
7790-
outarray['filetypes']['block']['idtofile'].update(idtofilearray)
7791-
outarray['filetypes']['devices']['filetoid'].update(filetoidarray)
7792-
outarray['filetypes']['devices']['idtofile'].update(idtofilearray)
7793-
if(listarrayfiles['ffilelist'][lcfi]['ftype'] == 5):
7794-
outarray['filetypes']['directories']['filetoid'].update(
7795-
filetoidarray)
7796-
outarray['filetypes']['directories']['idtofile'].update(
7797-
idtofilearray)
7798-
if(listarrayfiles['ffilelist'][lcfi]['ftype'] == 6):
7799-
outarray['filetypes']['symlinks']['filetoid'].update(filetoidarray)
7800-
outarray['filetypes']['symlinks']['idtofile'].update(idtofilearray)
7801-
outarray['filetypes']['devices']['filetoid'].update(filetoidarray)
7802-
outarray['filetypes']['devices']['idtofile'].update(idtofilearray)
7803-
lcfi = lcfi + 1
7804-
return outarray
7826+
7827+
# Buckets for categories
7828+
def _bucket():
7829+
return {"by_name": {}, "by_id": {}, "count": 0}
7830+
7831+
by_type = {}
7832+
for cat in CATEGORY_ORDER:
7833+
by_type[cat] = _bucket()
7834+
7835+
out = {
7836+
"list": inarray,
7837+
"fp": inarray.get("fp") if returnfp else None,
7838+
"entries": {},
7839+
"indexes": {
7840+
"by_name": {},
7841+
"by_type": by_type,
7842+
},
7843+
"counts": {"total": 0, "by_type": {}},
7844+
"unknown_types": {},
7845+
}
7846+
7847+
ffilelist = inarray.get("ffilelist") or []
7848+
try:
7849+
fnumfiles = int(inarray.get("fnumfiles", len(ffilelist)))
7850+
except Exception:
7851+
fnumfiles = len(ffilelist)
7852+
7853+
# Process only what's present
7854+
total = min(len(ffilelist), fnumfiles)
7855+
7856+
def _add(cat, name, fid):
7857+
b = by_type[cat]
7858+
b["by_name"][name] = fid
7859+
b["by_id"][fid] = name
7860+
# Count is number of unique names in this category
7861+
b["count"] = len(b["by_name"])
7862+
7863+
i = 0
7864+
while i < total:
7865+
e = ffilelist[i]
7866+
name = e.get("fname")
7867+
fid = e.get("fid")
7868+
t = e.get("ftype")
7869+
7870+
if name is None or fid is None or t is None:
7871+
i += 1
7872+
continue
7873+
7874+
# Store canonical entry once, keyed by fid
7875+
out["entries"][fid] = {"name": name, "type": t}
7876+
7877+
# Global reverse index for fast name -> id
7878+
out["indexes"]["by_name"][name] = fid
7879+
7880+
# Base category
7881+
base_cat = BASE_CATEGORY_BY_CODE.get(t)
7882+
if base_cat is not None:
7883+
_add(base_cat, name, fid)
7884+
else:
7885+
# Track unknown codes for visibility/forward-compat
7886+
lst = out["unknown_types"].setdefault(t, [])
7887+
if name not in lst:
7888+
lst.append(name)
7889+
7890+
# Union categories
7891+
for union_name, code_set in UNION_RULES:
7892+
if t in code_set:
7893+
_add(union_name, name, fid)
7894+
7895+
i += 1
7896+
7897+
# Counts
7898+
out["counts"]["total"] = total
7899+
for cat in CATEGORY_ORDER:
7900+
out["counts"]["by_type"][cat] = by_type[cat]["count"]
7901+
7902+
return out
78057903

78067904

78077905
def RePackFoxFile(infile, outfile, fmttype="auto", compression="auto", compresswholefile=True, compressionlevel=None, compressionuselist=compressionlistalt, followlink=False, filestart=0, seekstart=0, seekend=0, checksumtype=["crc32", "crc32", "crc32", "crc32"], skipchecksum=False, extradata=[], jsondata={}, formatspecs=__file_format_dict__, seektoend=False, verbose=False, returnfp=False):

0 commit comments

Comments
 (0)