WIM: Don't use syscall package

This allows the WIM code to build on other OSes.
This commit is contained in:
John Starks
2016-04-06 13:57:09 -07:00
parent 3cedae2e26
commit 2748a384c0
+51 -14
View File
@@ -13,10 +13,32 @@ import (
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"syscall" "time"
"unicode/utf16" "unicode/utf16"
) )
// File attribute constants from Windows.
const (
FILE_ATTRIBUTE_READONLY = 0x00000001
FILE_ATTRIBUTE_HIDDEN = 0x00000002
FILE_ATTRIBUTE_SYSTEM = 0x00000004
FILE_ATTRIBUTE_DIRECTORY = 0x00000010
FILE_ATTRIBUTE_ARCHIVE = 0x00000020
FILE_ATTRIBUTE_DEVICE = 0x00000040
FILE_ATTRIBUTE_NORMAL = 0x00000080
FILE_ATTRIBUTE_TEMPORARY = 0x00000100
FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200
FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400
FILE_ATTRIBUTE_COMPRESSED = 0x00000800
FILE_ATTRIBUTE_OFFLINE = 0x00001000
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000
FILE_ATTRIBUTE_ENCRYPTED = 0x00004000
FILE_ATTRIBUTE_INTEGRITY_STREAM = 0x00008000
FILE_ATTRIBUTE_VIRTUAL = 0x00010000
FILE_ATTRIBUTE_NO_SCRUB_DATA = 0x00020000
FILE_ATTRIBUTE_EA = 0x00040000
)
var wimImageTag = [...]byte{'M', 'S', 'W', 'I', 'M', 0, 0, 0} var wimImageTag = [...]byte{'M', 'S', 'W', 'I', 'M', 0, 0, 0}
type guid struct { type guid struct {
@@ -128,9 +150,9 @@ type direntry struct {
SecurityID uint32 SecurityID uint32
SubdirOffset int64 SubdirOffset int64
Unused1, Unused2 int64 Unused1, Unused2 int64
CreationTime syscall.Filetime CreationTime filetime
LastAccessTime syscall.Filetime LastAccessTime filetime
LastWriteTime syscall.Filetime LastWriteTime filetime
Hash SHA1Hash Hash SHA1Hash
Padding uint32 Padding uint32
ReparseHardLink int64 ReparseHardLink int64
@@ -150,6 +172,21 @@ type streamentry struct {
const streamentrySize = 38 const streamentrySize = 38
type filetime struct {
LowDateTime uint32
HighDateTime uint32
}
func (ft *filetime) Time() time.Time {
// 100-nanosecond intervals since January 1, 1601
nsec := int64(ft.HighDateTime)<<32 + int64(ft.LowDateTime)
// change starting time to the Epoch (00:00:00 UTC, January 1, 1970)
nsec -= 116444736000000000
// convert into nanoseconds
nsec *= 100
return time.Unix(0, nsec)
}
// ParseError is returned when the WIM cannot be parsed. // ParseError is returned when the WIM cannot be parsed.
type ParseError struct { type ParseError struct {
Oper string Oper string
@@ -201,9 +238,9 @@ type FileHeader struct {
ShortName string ShortName string
Attributes uint32 Attributes uint32
SecurityDescriptor []byte SecurityDescriptor []byte
CreationTime syscall.Filetime CreationTime time.Time
LastAccessTime syscall.Filetime LastAccessTime time.Time
LastWriteTime syscall.Filetime LastWriteTime time.Time
Hash SHA1Hash Hash SHA1Hash
Size int64 Size int64
LinkID int64 LinkID int64
@@ -515,9 +552,9 @@ func (img *Image) readNextEntry(r *bufio.Reader) (*File, error) {
f := &File{ f := &File{
FileHeader: FileHeader{ FileHeader: FileHeader{
Attributes: dentry.Attributes, Attributes: dentry.Attributes,
CreationTime: dentry.CreationTime, CreationTime: dentry.CreationTime.Time(),
LastAccessTime: dentry.LastAccessTime, LastAccessTime: dentry.LastAccessTime.Time(),
LastWriteTime: dentry.LastWriteTime, LastWriteTime: dentry.LastWriteTime.Time(),
Hash: dentry.Hash, Hash: dentry.Hash,
Size: offset.OriginalSize, Size: offset.OriginalSize,
Name: name, Name: name,
@@ -531,9 +568,9 @@ func (img *Image) readNextEntry(r *bufio.Reader) (*File, error) {
isDir := false isDir := false
if dentry.Attributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 { if dentry.Attributes&FILE_ATTRIBUTE_REPARSE_POINT == 0 {
f.LinkID = dentry.ReparseHardLink f.LinkID = dentry.ReparseHardLink
if dentry.Attributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 { if dentry.Attributes&FILE_ATTRIBUTE_DIRECTORY != 0 {
isDir = true isDir = true
} }
} else { } else {
@@ -575,7 +612,7 @@ func (img *Image) readNextEntry(r *bufio.Reader) (*File, error) {
f.Streams = streams f.Streams = streams
} }
if dentry.Attributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0 && f.Size == 0 { if dentry.Attributes&FILE_ATTRIBUTE_REPARSE_POINT != 0 && f.Size == 0 {
return nil, &ParseError{Oper: "directory entry", Path: name, Err: errors.New("reparse point is missing reparse stream")} return nil, &ParseError{Oper: "directory entry", Path: name, Err: errors.New("reparse point is missing reparse stream")}
} }
@@ -667,5 +704,5 @@ func (f *File) Readdir() ([]*File, error) {
// IsDir returns whether the given file is a directory. It returns false when it // IsDir returns whether the given file is a directory. It returns false when it
// is a directory reparse point. // is a directory reparse point.
func (f *FileHeader) IsDir() bool { func (f *FileHeader) IsDir() bool {
return f.Attributes&(syscall.FILE_ATTRIBUTE_DIRECTORY|syscall.FILE_ATTRIBUTE_REPARSE_POINT) == syscall.FILE_ATTRIBUTE_DIRECTORY return f.Attributes&(FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_REPARSE_POINT) == FILE_ATTRIBUTE_DIRECTORY
} }