Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1007)

Delta Between Two Patch Sets: src/pkg/os/file_windows.go

Issue 6488044: code review 6488044: os: detect and handle console in File.Write on windows (Closed)
Left Patch Set: Created 11 years, 7 months ago
Right Patch Set: diff -r cdee8bf43694 https://go.googlecode.com/hg/ Created 11 years, 6 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | src/pkg/syscall/syscall_windows.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
(no file at all)
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 package os 5 package os
6 6
7 import ( 7 import (
8 "io" 8 "io"
9 "runtime" 9 "runtime"
10 "sync" 10 "sync"
11 "syscall" 11 "syscall"
12 "unicode/utf16" 12 "unicode/utf16"
13 "unicode/utf8"
13 ) 14 )
14 15
15 // File represents an open file descriptor. 16 // File represents an open file descriptor.
16 type File struct { 17 type File struct {
17 *file 18 *file
18 } 19 }
19 20
20 // file is the real representation of *File. 21 // file is the real representation of *File.
21 // The extra level of indirection ensures that no clients of os 22 // The extra level of indirection ensures that no clients of os
22 // can overwrite this data, which could cause the finalizer 23 // can overwrite this data, which could cause the finalizer
23 // to close the wrong file descriptor. 24 // to close the wrong file descriptor.
24 type file struct { 25 type file struct {
25 fd syscall.Handle 26 fd syscall.Handle
26 name string 27 name string
27 dirinfo *dirInfo // nil unless directory being read 28 dirinfo *dirInfo // nil unless directory being read
28 l sync.Mutex // used to implement windows pread/pwrite 29 l sync.Mutex // used to implement windows pread/pwrite
30
31 // only for console io
32 isConsole bool
33 lastbits []byte // first few bytes of the last incomplete rune in last write
29 } 34 }
30 35
31 // Fd returns the Windows handle referencing the open file. 36 // Fd returns the Windows handle referencing the open file.
32 func (file *File) Fd() uintptr { 37 func (file *File) Fd() uintptr {
33 if file == nil { 38 if file == nil {
34 return uintptr(syscall.InvalidHandle) 39 return uintptr(syscall.InvalidHandle)
35 } 40 }
36 return uintptr(file.fd) 41 return uintptr(file.fd)
37 } 42 }
38 43
39 // NewFile returns a new File with the given file descriptor and name. 44 // NewFile returns a new File with the given file descriptor and name.
40 func NewFile(fd uintptr, name string) *File { 45 func NewFile(fd uintptr, name string) *File {
41 h := syscall.Handle(fd) 46 h := syscall.Handle(fd)
42 if h == syscall.InvalidHandle { 47 if h == syscall.InvalidHandle {
43 return nil 48 return nil
44 } 49 }
45 f := &File{&file{fd: h, name: name}} 50 f := &File{&file{fd: h, name: name}}
51 var m uint32
52 if syscall.GetConsoleMode(f.fd, &m) == nil {
53 f.isConsole = true
54 }
46 runtime.SetFinalizer(f.file, (*file).close) 55 runtime.SetFinalizer(f.file, (*file).close)
47 return f 56 return f
48 } 57 }
49 58
50 // Auxiliary information if the File describes a directory 59 // Auxiliary information if the File describes a directory
51 type dirInfo struct { 60 type dirInfo struct {
52 data syscall.Win32finddata 61 data syscall.Win32finddata
53 needdata bool 62 needdata bool
54 path string 63 path string
55 } 64 }
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 Offset: uint32(off), 232 Offset: uint32(off),
224 } 233 }
225 var done uint32 234 var done uint32
226 e = syscall.ReadFile(syscall.Handle(f.fd), b, &done, &o) 235 e = syscall.ReadFile(syscall.Handle(f.fd), b, &done, &o)
227 if e != nil { 236 if e != nil {
228 return 0, e 237 return 0, e
229 } 238 }
230 return int(done), nil 239 return int(done), nil
231 } 240 }
232 241
242 // writeConsole writes len(b) bytes to the console File.
243 // It returns the number of bytes written and an error, if any.
244 func (f *File) writeConsole(b []byte) (n int, err error) {
245 n = len(b)
246 runes := make([]rune, 0, 256)
247 if len(f.lastbits) > 0 {
248 b = append(f.lastbits, b...)
249 f.lastbits = nil
250
251 }
252 for len(b) >= utf8.UTFMax || utf8.FullRune(b) {
253 r, l := utf8.DecodeRune(b)
254 runes = append(runes, r)
255 b = b[l:]
256 }
257 if len(b) > 0 {
258 f.lastbits = make([]byte, len(b))
259 copy(f.lastbits, b)
260 }
261 if len(runes) > 0 {
262 uint16s := utf16.Encode(runes)
263 for len(uint16s) > 0 {
264 var written uint32
265 err = syscall.WriteConsole(f.fd, &uint16s[0], uint32(len (uint16s)), &written, nil)
266 if err != nil {
267 return 0, nil
268 }
269 uint16s = uint16s[written:]
270 }
271 }
272 return n, nil
273 }
274
233 // write writes len(b) bytes to the File. 275 // write writes len(b) bytes to the File.
234 // It returns the number of bytes written and an error, if any. 276 // It returns the number of bytes written and an error, if any.
235 func (f *File) write(b []byte) (n int, err error) { 277 func (f *File) write(b []byte) (n int, err error) {
236 f.l.Lock() 278 f.l.Lock()
237 defer f.l.Unlock() 279 defer f.l.Unlock()
280 if f.isConsole {
281 return f.writeConsole(b)
282 }
238 return syscall.Write(f.fd, b) 283 return syscall.Write(f.fd, b)
239 } 284 }
240 285
241 // pwrite writes len(b) bytes to the File starting at byte offset off. 286 // pwrite writes len(b) bytes to the File starting at byte offset off.
242 // It returns the number of bytes written and an error, if any. 287 // It returns the number of bytes written and an error, if any.
243 func (f *File) pwrite(b []byte, off int64) (n int, err error) { 288 func (f *File) pwrite(b []byte, off int64) (n int, err error) {
244 f.l.Lock() 289 f.l.Lock()
245 defer f.l.Unlock() 290 defer f.l.Unlock()
246 curoffset, e := syscall.Seek(f.fd, 0, 1) 291 curoffset, e := syscall.Seek(f.fd, 0, 1)
247 if e != nil { 292 if e != nil {
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 n, _ = syscall.GetTempPath(uint32(len(dirw)), &dirw[0]) 392 n, _ = syscall.GetTempPath(uint32(len(dirw)), &dirw[0])
348 if n > uint32(len(dirw)) { 393 if n > uint32(len(dirw)) {
349 n = 0 394 n = 0
350 } 395 }
351 } 396 }
352 if n > 0 && dirw[n-1] == pathSep { 397 if n > 0 && dirw[n-1] == pathSep {
353 n-- 398 n--
354 } 399 }
355 return string(utf16.Decode(dirw[0:n])) 400 return string(utf16.Decode(dirw[0:n]))
356 } 401 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b