Skip to content

Commit 63e4416

Browse files
committed
add file.Truncate
Signed-off-by: leongross <[email protected]>
1 parent 1fd75ff commit 63e4416

File tree

4 files changed

+92
-10
lines changed

4 files changed

+92
-10
lines changed

src/os/file.go

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -290,16 +290,6 @@ func (f *File) Sync() (err error) {
290290
return
291291
}
292292

293-
// Truncate is a stub, not yet implemented
294-
func (f *File) Truncate(size int64) (err error) {
295-
if f.handle == nil {
296-
err = ErrClosed
297-
} else {
298-
err = ErrNotImplemented
299-
}
300-
return &PathError{Op: "truncate", Path: f.name, Err: err}
301-
}
302-
303293
// LinkError records an error during a link or symlink or rename system call and
304294
// the paths that caused it.
305295
type LinkError struct {

src/os/file_unix.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,26 @@ func Readlink(name string) (string, error) {
125125
}
126126
}
127127

128+
// Truncate changes the size of the file.
129+
// It does not change the I/O offset.
130+
// If there is an error, it will be of type *PathError.
131+
132+
// Alternatively just use 'raw' syscall by file name
133+
func (f *File) Truncate(size int64) (err error) {
134+
if f.handle == nil {
135+
return ErrClosed
136+
}
137+
138+
e := ignoringEINTR(func() error {
139+
return syscall.Truncate(f.name, size)
140+
})
141+
142+
if e != nil {
143+
return &PathError{Op: "truncate", Path: f.name, Err: e}
144+
}
145+
return
146+
}
147+
128148
// ReadAt reads up to len(b) bytes from the File starting at the given absolute offset.
129149
// It returns the number of bytes read and any error encountered, possibly io.EOF.
130150
// At end of file, Pread returns 0, io.EOF.

src/os/truncate_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//go:build darwin || (linux && !baremetal && !js && !wasi)
2+
3+
// Copyright 2024 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
package os_test
8+
9+
import (
10+
. "os"
11+
"path/filepath"
12+
"testing"
13+
)
14+
15+
func TestTruncate(t *testing.T) {
16+
tmpDir := t.TempDir()
17+
file := filepath.Join(tmpDir, "truncate_0x100")
18+
19+
fd, err := Create(file)
20+
if err != nil {
21+
t.Fatalf("create %q: %s", file, err)
22+
}
23+
24+
// truncate up to 0x100
25+
if err := fd.Truncate(0x100); err != nil {
26+
t.Fatalf("truncate %q: %s", file, err)
27+
}
28+
29+
// check if size is 0x100
30+
fi, err := Stat(file)
31+
if err != nil {
32+
t.Fatalf("stat %q: %s", file, err)
33+
}
34+
35+
if fi.Size() != 0x100 {
36+
t.Fatalf("size of %q is %d; want 0x100", file, fi.Size())
37+
}
38+
39+
// truncate down to 0x80
40+
if err := fd.Truncate(0x80); err != nil {
41+
t.Fatalf("truncate %q: %s", file, err)
42+
}
43+
44+
// check if size is 0x80
45+
fi, err = Stat(file)
46+
if err != nil {
47+
t.Fatalf("stat %q: %s", file, err)
48+
}
49+
50+
if fi.Size() != 0x80 {
51+
t.Fatalf("size of %q is %d; want 0x80", file, fi.Size())
52+
}
53+
}

src/syscall/syscall_libc.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,15 @@ func Execve(pathname string, argv []string, envv []string) (err error) {
203203
return
204204
}
205205

206+
func Truncate(path string, length int64) (err error) {
207+
data := cstring(path)
208+
fail := int(libc_truncate(&data[0], length))
209+
if fail < 0 {
210+
err = getErrno()
211+
}
212+
return
213+
}
214+
206215
func Faccessat(dirfd int, path string, mode uint32, flags int) (err error)
207216

208217
func Kill(pid int, sig Signal) (err error) {
@@ -442,6 +451,7 @@ func libc_readlink(path *byte, buf *byte, count uint) int
442451
//export unlink
443452
func libc_unlink(pathname *byte) int32
444453

454+
<<<<<<< HEAD
445455
// pid_t fork(void);
446456
//
447457
//export fork
@@ -451,3 +461,12 @@ func libc_fork() int32
451461
//
452462
//export execve
453463
func libc_execve(filename *byte, argv **byte, envp **byte) int
464+
=======
465+
// int truncate(const char *path, off_t length);
466+
//
467+
//export truncate
468+
func libc_truncate(path *byte, length int64) int32
469+
470+
//go:extern environ
471+
var libc_environ *unsafe.Pointer
472+
>>>>>>> 2bb9c18a (add file.Truncate)

0 commit comments

Comments
 (0)