...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package comdoc
18
19 import (
20 "bytes"
21 "encoding/binary"
22 "errors"
23 )
24
25
26
27
28
29
30
31
32 func (r *ComDoc) readShortSAT() error {
33 count := r.SectorSize / 4
34 sat := make([]SecID, count*int(r.Header.SSATSectorCount))
35 position := 0
36 for sector := r.Header.SSATNextSector; sector >= 0; sector = r.SAT[sector] {
37 if position >= len(sat) {
38 return errors.New("ssat has more sectors than indicated")
39 }
40 if err := r.readSectorStruct(sector, sat[position:position+count]); err != nil {
41 return err
42 }
43 position += count
44 }
45 r.SSAT = sat
46 return nil
47 }
48
49
50 func (r *ComDoc) writeShortSAT() error {
51 freeSectors(r.SAT, r.Header.SSATNextSector)
52 perSector := r.SectorSize / 4
53 freeList := r.makeFreeSectors(len(r.SSAT)/perSector, false)
54 buf := bytes.NewBuffer(r.sectorBuf)
55 first := SecIDEndOfChain
56 previous := first
57 for i, sector := range freeList {
58 j := i * perSector
59 chunk := r.SSAT[j : j+perSector]
60 buf.Reset()
61 binary.Write(buf, binary.LittleEndian, chunk)
62 if err := r.writeSector(sector, buf.Bytes()); err != nil {
63 return err
64 }
65 if previous == SecIDEndOfChain {
66 first = sector
67 } else {
68 r.SAT[previous] = sector
69 }
70 previous = sector
71 }
72 r.SAT[previous] = SecIDEndOfChain
73 r.Header.SSATNextSector = first
74 r.Header.SSATSectorCount = uint32(len(freeList))
75 return nil
76 }
77
78
79
80
81
82
83
84
85 func (r *ComDoc) readShortSector(shortSector SecID, buf []byte) error {
86
87 bigSectorIndex := int(shortSector) * r.ShortSectorSize / r.SectorSize
88 bigSectorID := r.Files[r.rootStorage].NextSector
89 for i := 0; i < bigSectorIndex; i++ {
90 bigSectorID = r.SAT[bigSectorID]
91 }
92
93 n := r.sectorToOffset(bigSectorID)
94 n += int64(int(shortSector)*r.ShortSectorSize - bigSectorIndex*r.SectorSize)
95 _, err := r.File.ReadAt(buf, n)
96 return err
97 }
98
99
100
101 func (r *ComDoc) writeShortSector(shortSector SecID, content []byte) error {
102 if len(content) > r.ShortSectorSize {
103 panic("excessive write")
104 } else if len(content) < r.ShortSectorSize {
105 buf := r.sectorBuf
106 copy(buf, content)
107 for i := len(content); i < r.ShortSectorSize; i++ {
108 buf[i] = 0
109 }
110 content = buf[:r.ShortSectorSize]
111 }
112
113 bigSectorIndex := int(shortSector) * r.ShortSectorSize / r.SectorSize
114 offset := int(shortSector)*r.ShortSectorSize - bigSectorIndex*r.SectorSize
115 root := &r.Files[r.rootStorage]
116 bigSectorID := root.NextSector
117 for ; bigSectorIndex > 0; bigSectorIndex-- {
118 next := r.SAT[bigSectorID]
119 if next < 0 {
120 break
121 }
122 bigSectorID = next
123 }
124 if bigSectorIndex > 0 {
125
126 freeList := r.makeFreeSectors(bigSectorIndex, false)
127 for _, sector := range freeList {
128 r.SAT[bigSectorID] = sector
129 bigSectorID = sector
130 }
131 r.SAT[bigSectorID] = SecIDEndOfChain
132 }
133 n := r.sectorToOffset(bigSectorID) + int64(offset)
134 if _, err := r.writer.WriteAt(content, n); err != nil {
135 return err
136 }
137 streamLength := uint32(int(shortSector+1) * r.ShortSectorSize)
138 if streamLength > root.StreamSize {
139 root.StreamSize = streamLength
140 }
141 return nil
142 }
143
View as plain text