...
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 func (r *ComDoc) sectorToOffset(sector SecID) int64 {
27 if sector < 0 {
28 return -1
29 }
30 return r.FirstSector + int64(sector)*int64(r.SectorSize)
31 }
32
33
34 func (r *ComDoc) readSector(sector SecID, buf []byte) error {
35 _, err := r.File.ReadAt(buf, r.sectorToOffset(sector))
36 return err
37 }
38
39
40
41 func (r *ComDoc) readSectorStruct(sector SecID, v interface{}) error {
42 if err := r.readSector(sector, r.sectorBuf); err != nil {
43 return err
44 }
45 return binary.Read(bytes.NewReader(r.sectorBuf), binary.LittleEndian, v)
46 }
47
48
49
50 func (r *ComDoc) writeSector(sector SecID, content []byte) error {
51 if len(content) > r.SectorSize {
52 panic("excessive write")
53 } else if len(content) < r.SectorSize {
54 buf := r.sectorBuf
55 copy(buf, content)
56 for i := len(content); i < r.SectorSize; i++ {
57 buf[i] = 0
58 }
59 content = buf[:r.SectorSize]
60 }
61 _, err := r.writer.WriteAt(content, r.sectorToOffset(sector))
62 return err
63 }
64
65
66 func freeSectors(sat []SecID, sector SecID) {
67 for {
68 nextSector := sat[sector]
69 sat[sector] = SecIDFree
70 if nextSector < 0 {
71 break
72 }
73 sector = nextSector
74 }
75 }
76
77
78 func (r *ComDoc) makeFreeSectors(count int, short bool) []SecID {
79 if count <= 0 {
80 return nil
81 }
82 freeList := make([]SecID, 0, count)
83 var sat []SecID
84 if short {
85 sat = r.SSAT
86 } else {
87 sat = r.SAT
88 }
89
90 for i, j := range sat {
91 if j != SecIDFree {
92 continue
93 }
94 freeList = append(freeList, SecID(i))
95 count--
96 if count == 0 {
97 return freeList
98 }
99 }
100
101 sectorsPerBlock := r.SectorSize / 4
102 needBlocks := (count + sectorsPerBlock - 1) / sectorsPerBlock
103 oldCount := len(sat)
104 newSAT := append(sat, make([]SecID, needBlocks*sectorsPerBlock)...)
105 for i := oldCount; i < len(newSAT); i++ {
106 newSAT[i] = SecIDFree
107 if count > 0 {
108 freeList = append(freeList, SecID(i))
109 count--
110 }
111 }
112 if short {
113 r.SSAT = newSAT
114 } else {
115 r.SAT = newSAT
116 }
117 return freeList
118 }
119
120
121
122
123
124
125
126 func (r *ComDoc) readSAT() error {
127 count := r.SectorSize / 4
128 sat := make([]SecID, count*int(r.Header.SATSectors))
129 position := 0
130 for _, sector := range r.MSAT {
131 if sector < 0 {
132 continue
133 }
134 if position >= len(sat) {
135 return errors.New("msat has more sectors than indicated")
136 }
137 if err := r.readSectorStruct(sector, sat[position:position+count]); err != nil {
138 return err
139 }
140 position += count
141 }
142 r.SAT = sat
143 return nil
144 }
145
146
147 func (r *ComDoc) writeSAT(freeList []SecID) error {
148 satPerSector := r.SectorSize / 4
149 buf := bytes.NewBuffer(r.sectorBuf)
150 for i, sector := range freeList {
151 j := i * satPerSector
152 buf.Reset()
153 binary.Write(buf, binary.LittleEndian, r.SAT[j:j+satPerSector])
154 if err := r.writeSector(sector, buf.Bytes()); err != nil {
155 return err
156 }
157 }
158 return nil
159 }
160
View as plain text