liminix

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

tufted.fnl (1495B)


      1 (local tftp (require :tftp))
      2 (local { : realpath} (require :posix.stdlib))
      3 (local { : view } (require :fennel))
      4 
      5 (local options
      6        (match arg
      7          ["-a" ip-address dir]
      8          { :allow ip-address :base-directory (realpath dir)}
      9 
     10          [dir]
     11          { :allow nil :base-directory (realpath dir)}
     12 
     13          []
     14          (error "missing command line parameters")
     15          ))
     16 
     17 (print (.. "TFTP serving from " options.base-directory))
     18 
     19 ;; this is a copy of anoia append-path
     20 (fn  merge-pathname [dirname filename]
     21   (let [base (or (string.match dirname "(.*)/$") dirname)
     22         result []]
     23     (each [component (string.gmatch filename "([^/]+)")]
     24       (if (and (= component "..") (> (# result) 0))
     25           (table.remove result)
     26           (= component "..")
     27           (error "path traversal attempt")
     28           true
     29           (table.insert result component)))
     30     (.. base "/" (table.concat result "/"))))
     31 
     32 (->
     33  (tftp:listen
     34   (fn [file host port]
     35     (if (or (not options.allow) (= host options.allow))
     36         (let [pathname (merge-pathname options.base-directory file)
     37               f (io.open pathname "rb")
     38               size (f:seek "end")]
     39           (f:seek "set" 0)
     40           (var eof? false)
     41           (values
     42            (fn handler [reqlen]
     43              (let [bytes (f:read reqlen)]
     44                (if bytes
     45                    (values true bytes)
     46                    (values false nil))))
     47            size))
     48         (error "host not allowed")))
     49   nil
     50   ["*"]
     51   69)
     52 
     53 (os.exit))