sonar

Scan files at memory bandwidth speed.
Log | Files | Refs

read_other.odin (1931B)


      1 #+build !linux
      2 package walk
      3 
      4 import "core:os"
      5 import "core:strings"
      6 
      7 /*
      8 Read one directory through core:os.
      9 
     10 The reader that works anywhere. core:os describes every entry in full and this keeps
     11 the part the tree records, which is most of what it costs: not knowing the platform
     12 means not knowing which of that description was worth asking for.
     13 */
     14 @(private)
     15 read_dir :: proc(d: Dir, w: ^Worker) -> (nodes, bytes: u64, ok: bool) {
     16 	f, open_err := os.open(d.path)
     17 	if open_err != nil {
     18 		return 0, 0, false
     19 	}
     20 	defer os.close(f)
     21 
     22 	it := os.read_directory_iterator_create(f)
     23 	defer os.read_directory_iterator_destroy(&it)
     24 
     25 	for info in os.read_directory_iterator(&it) {
     26 		if _, err := os.read_directory_iterator_error(&it); err != nil {
     27 			continue
     28 		}
     29 		e := Entry {
     30 			name      = info.name,
     31 			size      = u64(max(info.size, 0)),
     32 			directory = info.type == .Directory,
     33 			symlink   = info.type == .Symlink,
     34 		}
     35 		if !e.directory && !e.symlink {
     36 			// core:os reports the logical length and nothing about allocation, so the
     37 			// on-disk figure is the best estimate available here: the size rounded up
     38 			// to a block.
     39 			e.disk = round_up(e.size, BLOCK_ESTIMATE)
     40 		}
     41 		index, descend, recorded := record(w, d.index, e)
     42 		if !recorded {
     43 			return nodes, bytes, false
     44 		}
     45 		if descend {
     46 			path, clone_err := strings.clone(info.fullpath, w.allocator)
     47 			if clone_err != nil {
     48 				w.err = .Out_Of_Memory
     49 				return nodes, bytes, false
     50 			}
     51 			append(&w.found, Dir{index = index, path = path})
     52 		}
     53 		nodes += 1
     54 		bytes += e.disk
     55 	}
     56 	return nodes, bytes, true
     57 }
     58 
     59 // Without filesystem-specific knowledge the allocation unit is a guess, and four
     60 // kilobytes is the common one. It makes small files cost something rather than
     61 // nothing, which matters more than being exactly right.
     62 @(private)
     63 BLOCK_ESTIMATE :: 4096
     64 
     65 @(private)
     66 round_up :: proc(v, unit: u64) -> u64 {
     67 	if v == 0 {
     68 		return 0
     69 	}
     70 	return (v + unit - 1) / unit * unit
     71 }