copyparty 1.13.2__py3-none-any.whl → 1.13.4__py3-none-any.whl

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.
copyparty/mtag.py CHANGED
@@ -105,7 +105,9 @@ class MParser(object):
105
105
  raise Exception()
106
106
 
107
107
 
108
- def au_unpk(log , fmt_map , abspath , vn = None) :
108
+ def au_unpk(
109
+ log , fmt_map , abspath , vn = None
110
+ ) :
109
111
  ret = ""
110
112
  try:
111
113
  ext = abspath.split(".")[-1].lower()
@@ -131,6 +133,9 @@ def au_unpk(log , fmt_map , abspath , vn = None) :
131
133
  zil = [x for x in zil if x.filename.lower().split(".")[-1] == au]
132
134
  fi = zf.open(zil[0])
133
135
 
136
+ else:
137
+ raise Exception("unknown compression %s" % (pk,))
138
+
134
139
  with os.fdopen(fd, "wb") as fo:
135
140
  while True:
136
141
  buf = fi.read(32768)
copyparty/smbd.py CHANGED
@@ -237,7 +237,7 @@ class SMB(object):
237
237
 
238
238
  xbu = vfs.flags.get("xbu")
239
239
  if xbu and not runhook(
240
- self.nlog, xbu, ap, vpath, "", "", 0, 0, "1.7.6.2", 0, ""
240
+ self.nlog, xbu, ap, vpath, "", "", "", 0, 0, "1.7.6.2", 0, ""
241
241
  ):
242
242
  yeet("blocked by xbu server config: " + vpath)
243
243
 
copyparty/ssdp.py CHANGED
@@ -137,9 +137,29 @@ class SSDPd(MCast):
137
137
  self.log("stopped", 2)
138
138
 
139
139
  def run2(self) :
140
+ try:
141
+ if self.args.no_poll:
142
+ raise Exception()
143
+ fd2sck = {}
144
+ srvpoll = select.poll()
145
+ for sck in self.srv:
146
+ fd = sck.fileno()
147
+ fd2sck[fd] = sck
148
+ srvpoll.register(fd, select.POLLIN)
149
+ except Exception as ex:
150
+ srvpoll = None
151
+ if not self.args.no_poll:
152
+ t = "WARNING: failed to poll(), will use select() instead: %r"
153
+ self.log(t % (ex,), 3)
154
+
140
155
  while self.running:
141
- rdy = select.select(self.srv, [], [], self.args.z_chk or 180)
142
- rx = rdy[0] # type: ignore
156
+ if srvpoll:
157
+ pr = srvpoll.poll((self.args.z_chk or 180) * 1000)
158
+ rx = [fd2sck[x[0]] for x in pr if x[1] & select.POLLIN]
159
+ else:
160
+ rdy = select.select(self.srv, [], [], self.args.z_chk or 180)
161
+ rx = rdy[0] # type: ignore
162
+
143
163
  self.rxc.cln()
144
164
  buf = b""
145
165
  addr = ("0", 0)
@@ -164,7 +184,7 @@ class SSDPd(MCast):
164
184
  except:
165
185
  pass
166
186
 
167
- self.srv = {}
187
+ self.srv.clear()
168
188
 
169
189
  def eat(self, buf , addr ) :
170
190
  cip = addr[0]
copyparty/star.py CHANGED
@@ -1,13 +1,13 @@
1
1
  # coding: utf-8
2
2
  from __future__ import print_function, unicode_literals
3
3
 
4
- import argparse
5
4
  import re
6
5
  import stat
7
6
  import tarfile
8
7
 
9
8
  from queue import Queue
10
9
 
10
+ from .authsrv import AuthSrv
11
11
  from .bos import bos
12
12
  from .sutil import StreamArc, errdesc
13
13
  from .util import Daemon, fsenc, min_ex
@@ -39,12 +39,12 @@ class StreamTar(StreamArc):
39
39
  def __init__(
40
40
  self,
41
41
  log ,
42
- args ,
42
+ asrv ,
43
43
  fgen ,
44
44
  cmp = "",
45
45
  **kwargs
46
46
  ):
47
- super(StreamTar, self).__init__(log, args, fgen)
47
+ super(StreamTar, self).__init__(log, asrv, fgen)
48
48
 
49
49
  self.ci = 0
50
50
  self.co = 0
@@ -142,7 +142,7 @@ class StreamTar(StreamArc):
142
142
  errors.append((f["vp"], ex))
143
143
 
144
144
  if errors:
145
- self.errf, txt = errdesc(errors)
145
+ self.errf, txt = errdesc(self.asrv.vfs, errors)
146
146
  self.log("\n".join(([repr(self.errf)] + txt[1:])))
147
147
  self.ser(self.errf)
148
148
 
copyparty/sutil.py CHANGED
@@ -1,26 +1,27 @@
1
1
  # coding: utf-8
2
2
  from __future__ import print_function, unicode_literals
3
3
 
4
- import argparse
5
4
  import os
6
5
  import tempfile
7
6
  from datetime import datetime
8
7
 
9
8
  from .__init__ import CORES
9
+ from .authsrv import AuthSrv, VFS
10
10
  from .bos import bos
11
11
  from .th_cli import ThumbCli
12
- from .util import UTC, vjoin
12
+ from .util import UTC, vjoin, vol_san
13
13
 
14
14
  class StreamArc(object):
15
15
  def __init__(
16
16
  self,
17
17
  log ,
18
- args ,
18
+ asrv ,
19
19
  fgen ,
20
20
  **kwargs
21
21
  ):
22
22
  self.log = log
23
- self.args = args
23
+ self.asrv = asrv
24
+ self.args = asrv.args
24
25
  self.fgen = fgen
25
26
  self.stopped = False
26
27
 
@@ -97,15 +98,20 @@ def enthumb(
97
98
  return f
98
99
 
99
100
 
100
- def errdesc(errors ) :
101
+ def errdesc(
102
+ vfs , errors
103
+ ) :
101
104
  report = ["copyparty failed to add the following files to the archive:", ""]
102
105
 
103
106
  for fn, err in errors:
104
107
  report.extend([" file: {}".format(fn), "error: {}".format(err), ""])
105
108
 
109
+ btxt = "\r\n".join(report).encode("utf-8", "replace")
110
+ btxt = vol_san(list(vfs.all_vols.values()), btxt)
111
+
106
112
  with tempfile.NamedTemporaryFile(prefix="copyparty-", delete=False) as tf:
107
113
  tf_path = tf.name
108
- tf.write("\r\n".join(report).encode("utf-8", "replace"))
114
+ tf.write(btxt)
109
115
 
110
116
  dt = datetime.now(UTC).strftime("%Y-%m%d-%H%M%S")
111
117
 
copyparty/svchub.py CHANGED
@@ -473,8 +473,10 @@ class SvcHub(object):
473
473
  zsl = al.th_covers.split(",")
474
474
  zsl = [x.strip() for x in zsl]
475
475
  zsl = [x for x in zsl if x]
476
- al.th_covers = set(zsl)
477
- al.th_coversd = set(zsl + ["." + x for x in zsl])
476
+ al.th_covers = zsl
477
+ al.th_coversd = zsl + ["." + x for x in zsl]
478
+ al.th_covers_set = set(al.th_covers)
479
+ al.th_coversd_set = set(al.th_coversd)
478
480
 
479
481
  for k in "c".split(" "):
480
482
  vl = getattr(al, k)
copyparty/szip.py CHANGED
@@ -1,12 +1,12 @@
1
1
  # coding: utf-8
2
2
  from __future__ import print_function, unicode_literals
3
3
 
4
- import argparse
5
4
  import calendar
6
5
  import stat
7
6
  import time
8
7
  import zlib
9
8
 
9
+ from .authsrv import AuthSrv
10
10
  from .bos import bos
11
11
  from .sutil import StreamArc, errdesc
12
12
  from .util import min_ex, sanitize_fn, spack, sunpack, yieldfile
@@ -213,13 +213,13 @@ class StreamZip(StreamArc):
213
213
  def __init__(
214
214
  self,
215
215
  log ,
216
- args ,
216
+ asrv ,
217
217
  fgen ,
218
218
  utf8 = False,
219
219
  pre_crc = False,
220
220
  **kwargs
221
221
  ) :
222
- super(StreamZip, self).__init__(log, args, fgen)
222
+ super(StreamZip, self).__init__(log, asrv, fgen)
223
223
 
224
224
  self.utf8 = utf8
225
225
  self.pre_crc = pre_crc
@@ -296,7 +296,7 @@ class StreamZip(StreamArc):
296
296
  mbuf = b""
297
297
 
298
298
  if errors:
299
- errf, txt = errdesc(errors)
299
+ errf, txt = errdesc(self.asrv.vfs, errors)
300
300
  self.log("\n".join(([repr(errf)] + txt[1:])))
301
301
  for x in self.ser(errf):
302
302
  yield x
copyparty/tcpsrv.py CHANGED
@@ -15,6 +15,7 @@ from .util import (
15
15
  E_ADDR_IN_USE,
16
16
  E_ADDR_NOT_AVAIL,
17
17
  E_UNREACH,
18
+ HAVE_IPV6,
18
19
  IP6ALL,
19
20
  Netdev,
20
21
  min_ex,
@@ -108,8 +109,10 @@ class TcpSrv(object):
108
109
 
109
110
  eps = {
110
111
  "127.0.0.1": Netdev("127.0.0.1", 0, "", "local only"),
111
- "::1": Netdev("::1", 0, "", "local only"),
112
112
  }
113
+ if HAVE_IPV6:
114
+ eps["::1"] = Netdev("::1", 0, "", "local only")
115
+
113
116
  nonlocals = [x for x in self.args.i if x not in [k.split("/")[0] for k in eps]]
114
117
  if nonlocals:
115
118
  try:
copyparty/tftpd.py CHANGED
@@ -33,7 +33,7 @@ from partftpy import (
33
33
  )
34
34
  from partftpy.TftpShared import TftpException
35
35
 
36
- from .__init__ import EXE, TYPE_CHECKING
36
+ from .__init__ import EXE, PY2, TYPE_CHECKING
37
37
  from .authsrv import VFS
38
38
  from .bos import bos
39
39
  from .util import BytesIO, Daemon, ODict, exclude_dotfiles, min_ex, runhook, undot
@@ -92,7 +92,7 @@ class Tftpd(object):
92
92
  TftpServer,
93
93
  ]
94
94
  cbak = []
95
- if not self.args.tftp_no_fast and not EXE:
95
+ if not self.args.tftp_no_fast and not EXE and not PY2:
96
96
  try:
97
97
  ptn = re.compile(r"(^\s*)log\.debug\(.*\)$")
98
98
  for C in Cs:
@@ -102,7 +102,7 @@ class Tftpd(object):
102
102
  cfn = C.__spec__.origin
103
103
  exec (compile(src2, filename=cfn, mode="exec"), C.__dict__)
104
104
  except Exception:
105
- t = "failed to optimize tftp code; run with --tftp-noopt if there are issues:\n"
105
+ t = "failed to optimize tftp code; run with --tftp-no-fast if there are issues:\n"
106
106
  self.log("tftp", t + min_ex(), 3)
107
107
  for n, zd in enumerate(cbak):
108
108
  Cs[n].__dict__ = zd
@@ -147,11 +147,6 @@ class Tftpd(object):
147
147
 
148
148
  self._disarm(fos)
149
149
 
150
- ip = next((x for x in self.args.i if ":" not in x), None)
151
- if not ip:
152
- self.log("tftp", "IPv6 not supported for tftp; listening on 0.0.0.0", 3)
153
- ip = "0.0.0.0"
154
-
155
150
  self.port = int(self.args.tftp)
156
151
  self.srv = []
157
152
  self.ips = []
@@ -165,7 +160,7 @@ class Tftpd(object):
165
160
  if "::" in ips:
166
161
  ips.append("0.0.0.0")
167
162
 
168
- if self.args.ftp4:
163
+ if self.args.tftp4:
169
164
  ips = [x for x in ips if ":" not in x]
170
165
 
171
166
  ips = list(ODict.fromkeys(ips)) # dedup
@@ -330,7 +325,7 @@ class Tftpd(object):
330
325
 
331
326
  xbu = vfs.flags.get("xbu")
332
327
  if xbu and not runhook(
333
- self.nlog, xbu, ap, vpath, "", "", 0, 0, "8.3.8.7", 0, ""
328
+ self.nlog, xbu, ap, vpath, "", "", "", 0, 0, "8.3.8.7", 0, ""
334
329
  ):
335
330
  yeet("blocked by xbu server config: " + vpath)
336
331
 
copyparty/th_cli.py CHANGED
@@ -103,7 +103,7 @@ class ThumbCli(object):
103
103
  sfmt += "3" if "3" in fmt else ""
104
104
 
105
105
  fmt = sfmt
106
-
106
+
107
107
  elif fmt[:1] == "p" and not is_au:
108
108
  t = "cannot thumbnail [%s]: png only allowed for waveforms"
109
109
  self.log(t % (rem), 6)
copyparty/th_srv.py CHANGED
@@ -596,13 +596,14 @@ class ThumbSrv(object):
596
596
  b"pngquant",
597
597
  b"--strip",
598
598
  b"--nofs",
599
- b"--output", fsenc(wtpath),
600
- fsenc(tpath)
599
+ b"--output",
600
+ fsenc(wtpath),
601
+ fsenc(tpath),
601
602
  ]
602
603
  ret = runcmd(cmd, timeout=vn.flags["convt"], nice=True, oom=400)[0]
603
604
  if ret:
604
605
  try:
605
- wunlink(self.log, wtpath, vn.flags)
606
+ wunlink(self.log, wtpath, vn.flags)
606
607
  except:
607
608
  pass
608
609
  else:
@@ -670,8 +671,8 @@ class ThumbSrv(object):
670
671
  raise Exception("disabled in server config")
671
672
 
672
673
  self.wait4ram(0.2, tpath)
673
- ret, _ = ffprobe(abspath, int(vn.flags["convt"] / 2))
674
- if "ac" not in ret:
674
+ tags, rawtags = ffprobe(abspath, int(vn.flags["convt"] / 2))
675
+ if "ac" not in tags:
675
676
  raise Exception("not audio")
676
677
 
677
678
  if quality.endswith("k"):
@@ -692,7 +693,7 @@ class ThumbSrv(object):
692
693
  b"-v", b"error",
693
694
  b"-hide_banner",
694
695
  b"-i", fsenc(abspath),
695
- b"-map_metadata", b"-1",
696
+ ] + self.big_tags(rawtags) + [
696
697
  b"-map", b"0:a:0",
697
698
  b"-ar", b"44100",
698
699
  b"-ac", b"2",
@@ -708,16 +709,16 @@ class ThumbSrv(object):
708
709
  raise Exception("disabled in server config")
709
710
 
710
711
  self.wait4ram(0.2, tpath)
711
- ret, _ = ffprobe(abspath, int(vn.flags["convt"] / 2))
712
- if "ac" not in ret:
712
+ tags, rawtags = ffprobe(abspath, int(vn.flags["convt"] / 2))
713
+ if "ac" not in tags:
713
714
  raise Exception("not audio")
714
715
 
715
716
  try:
716
- dur = ret[".dur"][1]
717
+ dur = tags[".dur"][1]
717
718
  except:
718
719
  dur = 0
719
720
 
720
- src_opus = abspath.lower().endswith(".opus") or ret["ac"][1] == "opus"
721
+ src_opus = abspath.lower().endswith(".opus") or tags["ac"][1] == "opus"
721
722
  want_caf = tpath.endswith(".caf")
722
723
  tmp_opus = tpath
723
724
  if want_caf:
@@ -738,7 +739,7 @@ class ThumbSrv(object):
738
739
  b"-v", b"error",
739
740
  b"-hide_banner",
740
741
  b"-i", fsenc(abspath),
741
- b"-map_metadata", b"-1",
742
+ ] + self.big_tags(rawtags) + [
742
743
  b"-map", b"0:a:0",
743
744
  b"-c:a", b"libopus",
744
745
  b"-b:a", bq,
@@ -795,6 +796,16 @@ class ThumbSrv(object):
795
796
  except:
796
797
  pass
797
798
 
799
+ def big_tags(self, raw_tags ) :
800
+ ret = []
801
+ for k, vs in raw_tags.items():
802
+ for v in vs:
803
+ if len(str(v)) >= 1024:
804
+ bv = k.encode("utf-8", "replace")
805
+ ret += [b"-metadata", bv + b"="]
806
+ break
807
+ return ret
808
+
798
809
  def poke(self, tdir ) :
799
810
  if not self.poke_cd.poke(tdir):
800
811
  return
copyparty/up2k.py CHANGED
@@ -651,7 +651,7 @@ class Up2k(object):
651
651
  return False, flags
652
652
 
653
653
  ret = {k: v for k, v in flags.items() if not k.startswith("e2t")}
654
- if ret.keys() == flags.keys():
654
+ if len(ret) == len(flags):
655
655
  return False, flags
656
656
 
657
657
  return True, ret
@@ -706,9 +706,9 @@ class Up2k(object):
706
706
  try:
707
707
  bos.makedirs(vol.realpath) # gonna happen at snap anyways
708
708
  dir_is_empty(self.log_func, not self.args.no_scandir, vol.realpath)
709
- except:
709
+ except Exception as ex:
710
710
  self.volstate[vol.vpath] = "OFFLINE (cannot access folder)"
711
- self.log("cannot access " + vol.realpath, c=1)
711
+ self.log("cannot access %s: %r" % (vol.realpath, ex), c=1)
712
712
  continue
713
713
 
714
714
  if scan_vols and vol.vpath not in scan_vols:
@@ -1192,6 +1192,9 @@ class Up2k(object):
1192
1192
  fat32 = True
1193
1193
  cv = ""
1194
1194
 
1195
+ th_cvd = self.args.th_coversd
1196
+ th_cvds = self.args.th_coversd_set
1197
+
1195
1198
  assert self.pp and self.mem_cur
1196
1199
  self.pp.msg = "a%d %s" % (self.pp.n, cdir)
1197
1200
 
@@ -1276,12 +1279,21 @@ class Up2k(object):
1276
1279
 
1277
1280
  files.append((sz, lmod, iname))
1278
1281
  liname = iname.lower()
1279
- if sz and (
1280
- iname in self.args.th_coversd
1281
- or (
1282
+ if (
1283
+ sz
1284
+ and (
1285
+ liname in th_cvds
1286
+ or (
1287
+ not cv
1288
+ and liname.rsplit(".", 1)[-1] in CV_EXTS
1289
+ and not iname.startswith(".")
1290
+ )
1291
+ )
1292
+ and (
1282
1293
  not cv
1283
- and liname.rsplit(".", 1)[-1] in CV_EXTS
1284
- and not iname.startswith(".")
1294
+ or liname not in th_cvds
1295
+ or cv.lower() not in th_cvds
1296
+ or th_cvd.index(iname) < th_cvd.index(cv)
1285
1297
  )
1286
1298
  ):
1287
1299
  cv = iname
@@ -2755,6 +2767,7 @@ class Up2k(object):
2755
2767
  job["vtop"],
2756
2768
  job["host"],
2757
2769
  job["user"],
2770
+ self.asrv.vfs.get_perms(job["vtop"], job["user"]),
2758
2771
  job["lmod"],
2759
2772
  job["size"],
2760
2773
  job["addr"],
@@ -3077,7 +3090,7 @@ class Up2k(object):
3077
3090
 
3078
3091
  return ret, dst
3079
3092
 
3080
- def finish_upload(self, ptop , wark , busy_aps ) :
3093
+ def finish_upload(self, ptop , wark , busy_aps ) :
3081
3094
  self.busy_aps = busy_aps
3082
3095
  with self.mutex, self.reg_mutex:
3083
3096
  self._finish_upload(ptop, wark)
@@ -3282,6 +3295,7 @@ class Up2k(object):
3282
3295
  djoin(vtop, rd, fn),
3283
3296
  host,
3284
3297
  usr,
3298
+ self.asrv.vfs.get_perms(djoin(vtop, rd, fn), usr),
3285
3299
  int(ts),
3286
3300
  sz,
3287
3301
  ip,
@@ -3316,15 +3330,29 @@ class Up2k(object):
3316
3330
  with self.rescan_cond:
3317
3331
  self.rescan_cond.notify_all()
3318
3332
 
3319
- if rd and sz and fn.lower() in self.args.th_coversd:
3333
+ if rd and sz and fn.lower() in self.args.th_coversd_set:
3320
3334
  # wasteful; db_add will re-index actual covers
3321
3335
  # but that won't catch existing files
3322
3336
  crd, cdn = rd.rsplit("/", 1) if "/" in rd else ("", rd)
3323
3337
  try:
3324
- db.execute("delete from cv where rd=? and dn=?", (crd, cdn))
3325
- db.execute("insert into cv values (?,?,?)", (crd, cdn, fn))
3338
+ q = "select fn from cv where rd=? and dn=?"
3339
+ db_cv = db.execute(q, (crd, cdn)).fetchone()[0]
3340
+ db_lcv = db_cv.lower()
3341
+ if db_lcv in self.args.th_coversd_set:
3342
+ idx_db = self.args.th_coversd.index(db_lcv)
3343
+ idx_fn = self.args.th_coversd.index(fn.lower())
3344
+ add_cv = idx_fn < idx_db
3345
+ else:
3346
+ add_cv = True
3326
3347
  except:
3327
- pass
3348
+ add_cv = True
3349
+
3350
+ if add_cv:
3351
+ try:
3352
+ db.execute("delete from cv where rd=? and dn=?", (crd, cdn))
3353
+ db.execute("insert into cv values (?,?,?)", (crd, cdn, fn))
3354
+ except:
3355
+ pass
3328
3356
 
3329
3357
  def handle_rm(
3330
3358
  self,
@@ -3467,6 +3495,7 @@ class Up2k(object):
3467
3495
  vpath,
3468
3496
  "",
3469
3497
  uname,
3498
+ self.asrv.vfs.get_perms(vpath, uname),
3470
3499
  stl.st_mtime,
3471
3500
  st.st_size,
3472
3501
  ip,
@@ -3500,6 +3529,7 @@ class Up2k(object):
3500
3529
  vpath,
3501
3530
  "",
3502
3531
  uname,
3532
+ self.asrv.vfs.get_perms(vpath, uname),
3503
3533
  stl.st_mtime,
3504
3534
  st.st_size,
3505
3535
  ip,
@@ -3632,7 +3662,18 @@ class Up2k(object):
3632
3662
  xar = dvn.flags.get("xar")
3633
3663
  if xbr:
3634
3664
  if not runhook(
3635
- self.log, xbr, sabs, svp, "", uname, stl.st_mtime, st.st_size, "", 0, ""
3665
+ self.log,
3666
+ xbr,
3667
+ sabs,
3668
+ svp,
3669
+ "",
3670
+ uname,
3671
+ self.asrv.vfs.get_perms(svp, uname),
3672
+ stl.st_mtime,
3673
+ st.st_size,
3674
+ "",
3675
+ 0,
3676
+ "",
3636
3677
  ):
3637
3678
  t = "move blocked by xbr server config: {}".format(svp)
3638
3679
  self.log(t, 1)
@@ -3657,7 +3698,20 @@ class Up2k(object):
3657
3698
  self.rescan_cond.notify_all()
3658
3699
 
3659
3700
  if xar:
3660
- runhook(self.log, xar, dabs, dvp, "", uname, 0, 0, "", 0, "")
3701
+ runhook(
3702
+ self.log,
3703
+ xar,
3704
+ dabs,
3705
+ dvp,
3706
+ "",
3707
+ uname,
3708
+ self.asrv.vfs.get_perms(dvp, uname),
3709
+ 0,
3710
+ 0,
3711
+ "",
3712
+ 0,
3713
+ "",
3714
+ )
3661
3715
 
3662
3716
  return "k"
3663
3717
 
@@ -3756,7 +3810,20 @@ class Up2k(object):
3756
3810
  wunlink(self.log, sabs, svn.flags)
3757
3811
 
3758
3812
  if xar:
3759
- runhook(self.log, xar, dabs, dvp, "", uname, 0, 0, "", 0, "")
3813
+ runhook(
3814
+ self.log,
3815
+ xar,
3816
+ dabs,
3817
+ dvp,
3818
+ "",
3819
+ uname,
3820
+ self.asrv.vfs.get_perms(dvp, uname),
3821
+ 0,
3822
+ 0,
3823
+ "",
3824
+ 0,
3825
+ "",
3826
+ )
3760
3827
 
3761
3828
  return "k"
3762
3829
 
@@ -4045,6 +4112,7 @@ class Up2k(object):
4045
4112
  vp_chk,
4046
4113
  job["host"],
4047
4114
  job["user"],
4115
+ self.asrv.vfs.get_perms(vp_chk, job["user"]),
4048
4116
  int(job["lmod"]),
4049
4117
  job["size"],
4050
4118
  job["addr"],