Skip to content

Commit d759780

Browse files
authored
Add files via upload
1 parent d2a580f commit d759780

1 file changed

Lines changed: 24 additions & 5 deletions

File tree

pycatfile.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2073,7 +2073,7 @@ def MkTempFile(data=None,
20732073
Return a file-like handle with consistent behavior on Py2.7 and Py3.x.
20742074

20752075
Storage:
2076-
- inmem=True -> BytesIO (bytes) or StringIO (text)
2076+
- inmem=True -> BytesIO (bytes) or StringIO (text), or memfd for bytes if available
20772077
- inmem=False, use_spool=True -> SpooledTemporaryFile (binary), optionally TextIOWrapper for text
20782078
- inmem=False, use_spool=False -> NamedTemporaryFile (binary), optionally TextIOWrapper for text
20792079

@@ -2086,6 +2086,8 @@ def MkTempFile(data=None,
20862086
- On Windows, NamedTemporaryFile(delete=True) keeps the file open and cannot be reopened by other processes.
20872087
Use delete=False if you need to pass the path elsewhere.
20882088
- For text: in-memory StringIO ignores 'newline' (as usual).
2089+
- When available, memfd is used only for inmem=True and isbytes=True, providing an anonymous in-memory
2090+
file descriptor (Linux-only). Text in-memory still uses StringIO to preserve newline semantics.
20892091
"""
20902092

20912093
# -- sanitize simple params (avoid None surprises) --
@@ -2119,20 +2121,36 @@ def MkTempFile(data=None,
21192121

21202122
# -------- In-memory --------
21212123
if inmem:
2124+
# Use memfd only for bytes, and only where available (Linux, Python 3.8+)
2125+
if isbytes and hasattr(os, "memfd_create"):
2126+
flags = 0
2127+
# Close-on-exec is almost always what you want for temps
2128+
if hasattr(os, "MFD_CLOEXEC"):
2129+
flags |= os.MFD_CLOEXEC
2130+
2131+
fd = os.memfd_create("MkTempFile", flags)
2132+
# Binary read/write file-like object backed by RAM
2133+
f = os.fdopen(fd, "w+b")
2134+
2135+
if init is not None:
2136+
f.write(init)
2137+
f.seek(0)
2138+
return f
2139+
2140+
# Fallback: pure Python in-memory objects
21222141
if isbytes:
21232142
f = io.BytesIO(init if init is not None else b"")
21242143
else:
21252144
# newline not enforced for StringIO; matches stdlib semantics
21262145
f = io.StringIO(init if init is not None else "")
2127-
# already positioned at 0 with provided init; ensure rewind for symmetry
2146+
21282147
f.seek(0)
21292148
return f
21302149

21312150
# Helper: wrap a binary file into a text file with encoding/newline
21322151
def _wrap_text(handle):
21332152
# For both Py2 & Py3, TextIOWrapper gives consistent newline/encoding behavior
21342153
tw = io.TextIOWrapper(handle, encoding=encoding, newline=newline)
2135-
# Position at start; if we wrote initial data below, we will rewind after writing
21362154
return tw
21372155

21382156
# -------- Spooled (RAM then disk) --------
@@ -2141,6 +2159,7 @@ def _wrap_text(handle):
21412159
bin_mode = "w+b" # read/write, binary
21422160
b = tempfile.SpooledTemporaryFile(max_size=spool_max, mode=bin_mode, dir=spool_dir)
21432161
f = b if isbytes else _wrap_text(b)
2162+
21442163
if init is not None:
21452164
f.write(init)
21462165
f.seek(0)
@@ -5953,14 +5972,14 @@ def AppendFilesWithContent(infiles, fp, dirlistfromtxt=False, extradata=[], json
59535972
if(hasattr(fstatinfo, "st_flags")):
59545973
fflags = format(int(fstatinfo.st_flags), 'x').lower()
59555974
ftype = 0
5956-
if(hasattr(os.path, "isjunction") and os.path.isjunction(fname)):
5975+
if(not followlink and hasattr(os.path, "isjunction") and os.path.isjunction(fname)):
59575976
ftype = 13
59585977
elif(stat.S_ISREG(fpremode)):
59595978
if(hasattr(fstatinfo, "st_blocks") and fstatinfo.st_size > 0 and fstatinfo.st_blocks * 512 < fstatinfo.st_size):
59605979
ftype = 12
59615980
else:
59625981
ftype = 0
5963-
elif(stat.S_ISLNK(fpremode)):
5982+
elif(not followlink and stat.S_ISLNK(fpremode)):
59645983
ftype = 2
59655984
elif(stat.S_ISCHR(fpremode)):
59665985
ftype = 3

0 commit comments

Comments
 (0)