dir-readdir.lisp 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. (in-package :hurd)
  2. (defcfun ("dir_readdir" %dir-readdir)
  3. err
  4. (dir port)
  5. (data :pointer)
  6. (data-cnt :pointer)
  7. (entry :int)
  8. (nentries :int)
  9. (bufsiz vm-size)
  10. (amount :pointer))
  11. (defconstant +dir-readdir-start-size+ 2048
  12. "Initial block size for dirent data as libc's readdir64.c")
  13. (defun %get-entries (ptr total)
  14. (loop for i from 0 below total
  15. collect (let ((entry (read-dirent ptr)))
  16. (incf-pointer ptr (dirent-size entry))
  17. entry)))
  18. (defun dir-readdir (dir &key (entry 0) (nentries -1) (bufsiz 0))
  19. "Read directory entries from 'dir'. 'entry' indicates the starting entry. 'nentries' tells how many entries we want. 'bufsiz' limits the size of entries fetched."
  20. (declare (type fixnum dir entry nentries bufsiz))
  21. (when (or (zerop nentries)
  22. (< nentries -1))
  23. (return-from dir-readdir nil))
  24. (with-foreign-pointer (data +dir-readdir-start-size+)
  25. (with-foreign-pointer (data-cnt (foreign-type-size 'msg-type-number))
  26. (setf (mem-ref data-cnt 'msg-type-number) +dir-readdir-start-size+)
  27. (with-foreign-pointer (dataptr (foreign-type-size :pointer))
  28. (setf (mem-ref dataptr :pointer) data)
  29. (with-foreign-pointer (amount (foreign-type-size :int))
  30. (select-error
  31. (%dir-readdir dir dataptr data-cnt
  32. entry nentries bufsiz amount)
  33. (let ((ptr (mem-ref dataptr :pointer))
  34. (total (mem-ref data-cnt 'msg-type-number)))
  35. (with-cleanup (unless (pointer-eq ptr data)
  36. (munmap ptr total))
  37. (%get-entries ptr (mem-ref amount :int))))))))))