The 6th argument to read-file-name is a PREDICATE that filters completion candidates (file names). C-h f read-file-name says, about it:
Sixth arg PREDICATE, if non-nil, should be a function of one
argument; then a file name is considered an acceptable completion
alternative only if PREDICATE returns non-nil with the file name
as its argument.
The file name passed to the predicate is a relative name, so your predicate function may need to use expand-file-name to obtain an absolute file name. Then you will want to apply function file-directory-p to each candidate, to see if it's a directory, and apply function file-attribute-modes to each candidate, to see if it is writable.
See also (elisp) File Attributes for info about function file-attributes (search for file-attribute-modes in that manual node).