@@ -33,6 +33,10 @@ fn C._wstat64(&char, voidptr) u64
3333
3434fn C.chown (& char, int , int ) int
3535
36+ fn C.ftruncate (voidptr , u64 ) int
37+
38+ fn C._chsize_s (voidptr , u64 ) int
39+
3640// fn C.proc_pidpath(int, byteptr, int) int
3741struct C.stat {
3842 st_size u64
@@ -130,7 +134,28 @@ pub fn read_file(path string) ?string {
130134}
131135
132136// ***************************** OS ops ************************
133- // file_size returns the size of the file located in `path`.
137+
138+ // truncate changes the size of the file located in `path` to `len`.
139+ pub fn truncate (path string , len u64 ) ? {
140+ fp := C.open (& char (path.str), o_wronly | o_trunc)
141+ defer {
142+ C.close (fp)
143+ }
144+ if fp < 0 {
145+ return error ('open file failed' )
146+ }
147+ $if windows {
148+ if C._chsize_s (fp, len) != 0 {
149+ return error_with_code (posix_get_error_msg (C.errno), C.errno)
150+ }
151+ } $else {
152+ if C.ftruncate (fp, len) != 0 {
153+ return error_with_code (posix_get_error_msg (C.errno), C.errno)
154+ }
155+ }
156+ }
157+
158+ // file_size returns the size of the file located in `path`. In case of error -1 is returned.
134159pub fn file_size (path string ) u64 {
135160 mut s := C.stat{}
136161 unsafe {
@@ -157,7 +182,7 @@ pub fn file_size(path string) u64 {
157182 }
158183 }
159184 }
160- return 0
185+ return - 1
161186}
162187
163188// mv moves files or folders from `src` to `dst`.
@@ -201,16 +226,18 @@ pub fn cp(src string, dst string) ? {
201226 return error_with_code ('cp (permission): failed to write to $dst (fp_to: $fp_to )' ,
202227 int (fp_to))
203228 }
229+ // TODO use defer{} to close files in case of error or return.
230+ // Currently there is a C-Error when building.
204231 mut buf := [1024 ]byte {}
205232 mut count := 0
206233 for {
207- // FIXME: use sizeof, bug: 'os__buf' undeclared
208- // count = C.read(fp_from, buf, sizeof(buf))
209- count = C.read (fp_from, & buf[0 ], 1024 )
234+ count = C.read (fp_from, & buf[0 ], sizeof (buf))
210235 if count == 0 {
211236 break
212237 }
213238 if C.write (fp_to, & buf[0 ], count) < 0 {
239+ C.close (fp_to)
240+ C.close (fp_from)
214241 return error_with_code ('cp: failed to write to $dst ' , int (- 1 ))
215242 }
216243 }
@@ -219,6 +246,8 @@ pub fn cp(src string, dst string) ? {
219246 C.stat (& char (src.str), & from_attr)
220247 }
221248 if C.chmod (& char (dst.str), from_attr.st_mode) < 0 {
249+ C.close (fp_to)
250+ C.close (fp_from)
222251 return error_with_code ('failed to set permissions for $dst ' , int (- 1 ))
223252 }
224253 C.close (fp_to)
@@ -830,11 +859,11 @@ pub fn flush() {
830859// Octals like `0o600` can be used.
831860pub fn chmod (path string , mode int ) {
832861 if C.chmod (& char (path.str), mode) != 0 {
833- panic (posix_get_error_msg (C.errno))
862+ panic ('chmod failed: ' + posix_get_error_msg (C.errno))
834863 }
835864}
836865
837- // chown change owner and group attributes of path to `owner` and `group`.
866+ // chown changes the owner and group attributes of ` path` to `owner` and `group`.
838867pub fn chown (path string , owner int , group int ) ? {
839868 $if windows {
840869 return error ('os.chown() not implemented for Windows' )
0 commit comments