-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathindex.go
131 lines (115 loc) · 3.31 KB
/
index.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package simplecache
import (
"encoding/binary"
"fmt"
"io"
"log"
"os"
"path/filepath"
)
// URLs returns all the URLs currently stored in the cache.
//
// On linux, valid cache paths are:
// ~/.cache/chromium/Default/Cache
// ~/.cache/chromium/Default/Media Cache
//
// URLs reads the files named "path/index" and "path/index-dir/the-real-index"
// and every entry files named "path/hash(url)_0" where hash is read from the-real-index file.
//
// An error is returned if the format of the index files is unexpected.
func URLs(path string) ([]string, error) {
var urls []string
if err := checkFakeIndex(path); err != nil {
return urls, fmt.Errorf("get urls from %s: %v", path, err)
}
hashes, err := readRealIndex(path)
if err != nil {
return urls, fmt.Errorf("get urls from %s: %v", path, err)
}
urls = make([]string, 0, len(hashes))
for i := 0; i < len(hashes); i++ {
url, err := readURL(hashes[i], path)
if err != nil {
log.Printf("Unable to get %s from %s: %v\n", url, path, err)
continue
}
urls = append(urls, url)
}
return urls, nil
}
// checkFakeIndex verifies the index file format.
func checkFakeIndex(path string) error {
info, err := os.Stat(path)
if err != nil {
return fmt.Errorf("fake-index: %v", err)
}
if !info.IsDir() {
return fmt.Errorf("fake-index: not a directory")
}
file, err := os.Open(filepath.Join(path, "index"))
if err != nil {
return fmt.Errorf("open fake-index: %v", err)
}
defer close(file)
var index fakeIndex
err = binary.Read(file, binary.LittleEndian, &index)
if err != nil {
return fmt.Errorf("read fake-index: %v", err)
}
if index.Magic != initialMagicNumber {
return fmt.Errorf("fake-index magic: %x, want: %x",
index.Magic, initialMagicNumber)
}
if index.Version < indexVersion {
return fmt.Errorf("fake-index version: %d, want: >= %d",
index.Version, indexVersion)
}
return nil
}
// readRealIndex reads every index-entries in "the-real-index" file.
func readRealIndex(path string) ([]uint64, error) {
var hashes []uint64
name := filepath.Join(path, "index-dir", "the-real-index")
file, err := os.Open(name)
if err != nil {
return hashes, fmt.Errorf("open real-index: %v", err)
}
defer close(file)
var index indexHeader
err = binary.Read(file, binary.LittleEndian, &index)
if err != nil {
return hashes, fmt.Errorf("read real-index header: %v", err)
}
if err := checkRealIndex(index); err != nil {
return hashes, fmt.Errorf("check real-index header: %v", err)
}
if index.Version > indexVersion {
var reasonSize int64 = 4 // last write reason
_, err = file.Seek(reasonSize, io.SeekCurrent)
if err != nil {
return hashes, fmt.Errorf("read real-index 'last write reason': %v", err)
}
}
hashes = make([]uint64, index.EntryCount)
var entry indexEntry
for i := uint64(0); i < index.EntryCount; i++ {
err = binary.Read(file, binary.LittleEndian, &entry)
if err != nil {
return nil, fmt.Errorf("read real-index entry: %v", err)
}
hashes[i] = entry.Hash
}
return hashes, nil
}
// checkRealIndex verifies the "the-real-index" header.
func checkRealIndex(index indexHeader) error {
if index.Magic != indexMagicNumber {
return fmt.Errorf("magic: %x, want: %x",
index.Magic, indexMagicNumber)
}
if index.Version < indexVersion {
return fmt.Errorf("version: %d, want: >= %d",
index.Version, indexVersion)
}
return nil
}