| ... | ... | @@ -21,10 +21,28 @@ pub fn getCwd(out_buffer: []u8) ![]u8 { |
| 21 | 21 | |
| 22 | 22 | /// Caller must free the returned memory. |
| 23 | 23 | pub fn getCwdAlloc(allocator: *Allocator) ![]u8 { |
| 24 | | // TODO(#4812): Consider looping with larger and larger buffers to handle |
| 25 | | // overlong paths. |
| 26 | | var buf: [fs.MAX_PATH_BYTES]u8 = undefined; |
| 27 | | return mem.dupe(allocator, u8, try os.getcwd(&buf)); |
| 24 | // The use of MAX_PATH_BYTES here is just a heuristic: most paths will fit |
| 25 | // in stack_buf, avoiding an extra allocation in the common case. |
| 26 | var stack_buf: [fs.MAX_PATH_BYTES]u8 = undefined; |
| 27 | var heap_buf: ?[]u8 = null; |
| 28 | defer if (heap_buf) |buf| allocator.free(buf); |
| 29 | |
| 30 | var current_buf: []u8 = &stack_buf; |
| 31 | while (true) { |
| 32 | if (os.getcwd(current_buf)) |slice| { |
| 33 | return mem.dupe(allocator, u8, slice); |
| 34 | } else |err| switch(err) { |
| 35 | error.NameTooLong => { |
| 36 | // The path is too long to fit in stack_buf. Allocate geometrically |
| 37 | // increasing buffers until we find one that works |
| 38 | const new_capacity = current_buf.len * 2; |
| 39 | if (heap_buf) |buf| allocator.free(buf); |
| 40 | current_buf = try allocator.alloc(u8, new_capacity); |
| 41 | heap_buf = current_buf; |
| 42 | }, |
| 43 | else => return err, |
| 44 | } |
| 45 | } |
| 28 | 46 | } |
| 29 | 47 | |
| 30 | 48 | test "getCwdAlloc" { |