| ... | @@ -21,10 +21,28 @@ pub fn getCwd(out_buffer: []u8) ![]u8 { | ... | @@ -21,10 +21,28 @@ pub fn getCwd(out_buffer: []u8) ![]u8 { |
| 21 | | 21 | |
| 22 | /// Caller must free the returned memory. | 22 | /// Caller must free the returned memory. |
| 23 | pub fn getCwdAlloc(allocator: *Allocator) ![]u8 { | 23 | pub fn getCwdAlloc(allocator: *Allocator) ![]u8 { |
| 24 | // TODO(#4812): Consider looping with larger and larger buffers to handle | 24 | // The use of MAX_PATH_BYTES here is just a heuristic: most paths will fit |
| 25 | // overlong paths. | 25 | // in stack_buf, avoiding an extra allocation in the common case. |
| 26 | var buf: [fs.MAX_PATH_BYTES]u8 = undefined; | 26 | var stack_buf: [fs.MAX_PATH_BYTES]u8 = undefined; |
| 27 | return mem.dupe(allocator, u8, try os.getcwd(&buf)); | 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 | test "getCwdAlloc" { | 48 | test "getCwdAlloc" { |