package blefs import ( "fmt" "io/fs" "strconv" "time" ) // Mkdir creates a directory at the given path func (blefs *FS) Mkdir(path string) error { // Create make directory request err := blefs.request( FSCmdMkdir, true, uint16(len(path)), padding(4), uint64(time.Now().UnixNano()), path, ) if err != nil { return err } var status int8 // Upon receiving 0x41 (FSResponseMkdir), read status byte blefs.on(FSResponseMkdir, func(data []byte) error { return decode(data, &status) }) // If status not ok, return error if status != FSStatusOk { return FSError{status} } return nil } // ReadDir returns a list of directory entries from the given path func (blefs *FS) ReadDir(path string) ([]fs.DirEntry, error) { // Create list directory request err := blefs.request( FSCmdListDir, true, uint16(len(path)), path, ) if err != nil { return nil, err } var out []fs.DirEntry for { // Create new directory entry listing := DirEntry{} // Upon receiving 0x50 (FSResponseListDir) blefs.on(FSResponseListDir, func(data []byte) error { // Read data into listing err := decode( data, &listing.status, &listing.pathLen, &listing.entryNum, &listing.entries, &listing.flags, &listing.modtime, &listing.size, &listing.path, ) if err != nil { return err } return nil }) // If status is not ok, return error if listing.status != FSStatusOk { return nil, FSError{listing.status} } // Stop once entry number equals total entries if listing.entryNum == listing.entries { break } // Append listing to slice out = append(out, listing) } return out, nil } // DirEntry represents an entry from a directory listing type DirEntry struct { status int8 pathLen uint16 entryNum uint32 entries uint32 flags uint32 modtime uint64 size uint32 path string } // Name returns the name of the file described by the entry func (de DirEntry) Name() string { return de.path } // IsDir reports whether the entry describes a directory. func (de DirEntry) IsDir() bool { return de.flags&0b1 == 1 } // Type returns the type bits for the entry. func (de DirEntry) Type() fs.FileMode { if de.IsDir() { return fs.ModeDir } else { return 0 } } // Info returns the FileInfo for the file or subdirectory described by the entry. func (de DirEntry) Info() (fs.FileInfo, error) { return FileInfo{ name: de.path, size: de.size, modtime: de.modtime, mode: de.Type(), isDir: de.IsDir(), }, nil } func (de DirEntry) String() string { var isDirChar rune if de.IsDir() { isDirChar = 'd' } else { isDirChar = '-' } // Get human-readable value for file size val, unit := bytesHuman(de.size) prec := 0 // If value is less than 10, set precision to 1 if val < 10 { prec = 1 } // Convert float to string valStr := strconv.FormatFloat(val, 'f', prec, 64) // Return string formatted like so: // - 10 kB file // or: // d 0 B . return fmt.Sprintf( "%c %3s %-2s %s", isDirChar, valStr, unit, de.path, ) }