server/data.rkt
#lang racket
(require
 "../enum.rkt"
 "../data.rkt")

(define-enum touch-mode
  ([name   name   "name"]
   [length length "length"]
   [mode   mode   "type and permissions"]
   [mtime  mtime  "modification time"]
   [gid    gid    "group identifier"]))

(define server-context%
  (class object%
    
    (super-new)
    
    (init-field user)
    
    (define/public-final (->user)
      user)
    
    (define/public (in-group? group)
      (string=? group user))
    
    (define/public (can-access? file mode)
      (let ([stat (send file read-stat this)]
            [mask (foldl
                   bitwise-ior 0
                   (enum-case open-direction (open-mode-direction mode)
                     [(r)   (access-flag e r)]
                     [(w)   (access-flag e w)]
                     [(r/w) (access-flag e r w)]
                     [(x)   (access-flag e x)]))])
        (= (bitwise-and
            ((cond
               [(string=? (stat-uid stat) (->user))
                file-mode-user]
               [(in-group? (stat-gid stat))
                file-mode-group]
               [else
                file-mode-others])
             (stat-mode stat))
            mask)
           mask)))
    
    (define/public (can-touch? file mode)
      (for/and ([mode (if (list? mode) (in-list mode) (in-value mode))])
        (enum-case touch-mode mode
          [(name)
           (can-access? (send file parent) (open-mode w))]
          [(length)
           (can-access? file (open-mode w))]
          [(mode)
           (and (string=? (stat-uid (send file read-stat this)) (->user))
                (can-access? (send file parent) (open-mode w)))]
          [(mtime)
           (and (string=? (stat-uid (send file read-stat this)) (->user))
                (can-access? file (open-mode w)))]
          [else
           #f])))
    
    (define/public (can-remove? file)
      (and (can-access? file (open-mode w))
           (can-access? (send file parent) (open-mode w))))
    
    ))

(provide
 touch-mode server-context%)