Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go-fuse
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Levin Zimmermann
go-fuse
Commits
0ec6d90d
Commit
0ec6d90d
authored
May 14, 2011
by
Han-Wen Nienhuys
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Split out tree/file management of zipfs.go into
archive agnostic MemTree and MemTreeFileSystem.
parent
4e9a1e68
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
189 additions
and
164 deletions
+189
-164
zipfs/Makefile
zipfs/Makefile
+1
-0
zipfs/memtree.go
zipfs/memtree.go
+145
-0
zipfs/multizip.go
zipfs/multizip.go
+9
-8
zipfs/zipfs.go
zipfs/zipfs.go
+32
-155
zipfs/zipfs_test.go
zipfs/zipfs_test.go
+2
-1
No files found.
zipfs/Makefile
View file @
0ec6d90d
...
@@ -6,6 +6,7 @@ DEPS=../fuse
...
@@ -6,6 +6,7 @@ DEPS=../fuse
GOFILES
=
zipfs.go
\
GOFILES
=
zipfs.go
\
multizip.go
\
multizip.go
\
memtree.go
include
$(GOROOT)/src/Make.pkg
include
$(GOROOT)/src/Make.pkg
zipfs/memtree.go
0 → 100644
View file @
0ec6d90d
package
zipfs
import
(
"fmt"
"github.com/hanwen/go-fuse/fuse"
"os"
"strings"
"path/filepath"
)
type
MemFile
interface
{
Stat
()
*
os
.
FileInfo
Data
()
[]
byte
}
type
MemTree
struct
{
subdirs
map
[
string
]
*
MemTree
files
map
[
string
]
MemFile
}
func
NewMemTree
()
*
MemTree
{
d
:=
new
(
MemTree
)
d
.
subdirs
=
make
(
map
[
string
]
*
MemTree
)
d
.
files
=
make
(
map
[
string
]
MemFile
)
return
d
}
func
(
me
*
MemTree
)
Print
(
indent
int
)
{
s
:=
""
for
i
:=
0
;
i
<
indent
;
i
++
{
s
=
s
+
" "
}
for
k
,
v
:=
range
me
.
subdirs
{
fmt
.
Println
(
s
+
k
+
":"
)
v
.
Print
(
indent
+
2
)
}
for
k
,
_
:=
range
me
.
files
{
fmt
.
Println
(
s
+
k
)
}
}
func
(
me
*
MemTree
)
Lookup
(
name
string
)
(
*
MemTree
,
MemFile
)
{
if
name
==
""
{
return
me
,
nil
}
parent
:=
me
comps
:=
strings
.
Split
(
filepath
.
Clean
(
name
),
"/"
,
-
1
)
for
_
,
c
:=
range
comps
[
:
len
(
comps
)
-
1
]
{
parent
=
parent
.
subdirs
[
c
]
if
parent
==
nil
{
return
nil
,
nil
}
}
base
:=
comps
[
len
(
comps
)
-
1
]
file
,
ok
:=
parent
.
files
[
base
]
if
ok
{
return
parent
,
file
}
return
parent
.
subdirs
[
base
],
nil
}
func
(
me
*
MemTree
)
FindDir
(
name
string
)
*
MemTree
{
s
,
ok
:=
me
.
subdirs
[
name
]
if
!
ok
{
s
=
NewMemTree
()
me
.
subdirs
[
name
]
=
s
}
return
s
}
////////////////////////////////////////////////////////////////
type
MemTreeFileSystem
struct
{
tree
*
MemTree
fuse
.
DefaultFileSystem
}
func
NewMemTreeFileSystem
(
t
*
MemTree
)
*
MemTreeFileSystem
{
return
&
MemTreeFileSystem
{
tree
:
t
,
}
}
const
mem_DIRMODE
uint32
=
fuse
.
S_IFDIR
|
0500
const
mem_FILEMODE
uint32
=
fuse
.
S_IFREG
|
0400
func
(
me
*
MemTreeFileSystem
)
GetAttr
(
name
string
)
(
*
os
.
FileInfo
,
fuse
.
Status
)
{
dir
,
file
:=
me
.
tree
.
Lookup
(
name
)
if
dir
==
nil
{
return
nil
,
fuse
.
ENOENT
}
a
:=
&
os
.
FileInfo
{}
if
file
==
nil
{
a
.
Mode
=
mem_DIRMODE
}
else
{
a
=
file
.
Stat
()
}
return
a
,
fuse
.
OK
}
func
(
me
*
MemTreeFileSystem
)
Open
(
name
string
,
flags
uint32
)
(
fuseFile
fuse
.
File
,
code
fuse
.
Status
)
{
if
flags
&
fuse
.
O_ANYWRITE
!=
0
{
return
nil
,
fuse
.
EPERM
}
// TODO - should complain if it is a directory.
_
,
file
:=
me
.
tree
.
Lookup
(
name
)
if
file
==
nil
{
return
nil
,
fuse
.
ENOENT
}
return
fuse
.
NewReadOnlyFile
(
file
.
Data
()),
fuse
.
OK
}
func
(
me
*
MemTreeFileSystem
)
OpenDir
(
name
string
)
(
stream
chan
fuse
.
DirEntry
,
code
fuse
.
Status
)
{
dir
,
file
:=
me
.
tree
.
Lookup
(
name
)
if
file
!=
nil
{
return
nil
,
fuse
.
ENOSYS
}
if
dir
==
nil
{
panic
(
"dir"
)
}
stream
=
make
(
chan
fuse
.
DirEntry
,
len
(
dir
.
files
)
+
len
(
dir
.
subdirs
))
for
k
,
_
:=
range
dir
.
files
{
stream
<-
fuse
.
DirEntry
{
Name
:
k
,
Mode
:
mem_FILEMODE
,
}
}
for
k
,
_
:=
range
dir
.
subdirs
{
stream
<-
fuse
.
DirEntry
{
Name
:
k
,
Mode
:
mem_DIRMODE
,
}
}
close
(
stream
)
return
stream
,
fuse
.
OK
}
zipfs/multizip.go
View file @
0ec6d90d
...
@@ -59,6 +59,7 @@ func (me *zipCreateFile) Write(input *fuse.WriteIn, nameBytes []byte) (uint32, f
...
@@ -59,6 +59,7 @@ func (me *zipCreateFile) Write(input *fuse.WriteIn, nameBytes []byte) (uint32, f
// TODO. locks?
// TODO. locks?
me
.
zfs
.
zips
[
me
.
Basename
]
=
fs
me
.
zfs
.
zips
[
me
.
Basename
]
=
fs
me
.
zfs
.
dirZipFileMap
[
me
.
Basename
]
=
zipFile
me
.
zfs
.
pendingZips
[
me
.
Basename
]
=
false
,
false
me
.
zfs
.
pendingZips
[
me
.
Basename
]
=
false
,
false
me
.
zfs
=
nil
me
.
zfs
=
nil
...
@@ -74,18 +75,18 @@ func (me *zipCreateFile) Write(input *fuse.WriteIn, nameBytes []byte) (uint32, f
...
@@ -74,18 +75,18 @@ func (me *zipCreateFile) Write(input *fuse.WriteIn, nameBytes []byte) (uint32, f
type
MultiZipFs
struct
{
type
MultiZipFs
struct
{
Connector
*
fuse
.
FileSystemConnector
Connector
*
fuse
.
FileSystemConnector
lock
sync
.
RWMutex
lock
sync
.
RWMutex
zips
map
[
string
]
*
ZipArchiv
eFileSystem
zips
map
[
string
]
*
MemTre
eFileSystem
pendingZips
map
[
string
]
bool
pendingZips
map
[
string
]
bool
zipFileNames
map
[
string
]
string
dirZipFileMap
map
[
string
]
string
fuse
.
DefaultFileSystem
fuse
.
DefaultFileSystem
}
}
func
NewMultiZipFs
()
*
MultiZipFs
{
func
NewMultiZipFs
()
*
MultiZipFs
{
m
:=
new
(
MultiZipFs
)
m
:=
new
(
MultiZipFs
)
m
.
zips
=
make
(
map
[
string
]
*
ZipArchiv
eFileSystem
)
m
.
zips
=
make
(
map
[
string
]
*
MemTre
eFileSystem
)
m
.
pendingZips
=
make
(
map
[
string
]
bool
)
m
.
pendingZips
=
make
(
map
[
string
]
bool
)
m
.
zipFileNames
=
make
(
map
[
string
]
string
)
m
.
dirZipFileMap
=
make
(
map
[
string
]
string
)
m
.
Connector
=
fuse
.
NewFileSystemConnector
(
m
,
nil
)
m
.
Connector
=
fuse
.
NewFileSystemConnector
(
m
,
nil
)
return
m
return
m
}
}
...
@@ -155,9 +156,8 @@ func (me *MultiZipFs) GetAttr(name string) (*os.FileInfo, fuse.Status) {
...
@@ -155,9 +156,8 @@ func (me *MultiZipFs) GetAttr(name string) (*os.FileInfo, fuse.Status) {
defer
me
.
lock
.
RUnlock
()
defer
me
.
lock
.
RUnlock
()
a
.
Mode
=
submode
a
.
Mode
=
submode
entry
,
hasDir
:=
me
.
zips
[
base
]
_
,
hasDir
:=
me
.
zips
[
base
]
if
hasDir
{
if
hasDir
{
a
.
Size
=
int64
(
len
(
entry
.
ZipFileName
))
return
a
,
fuse
.
OK
return
a
,
fuse
.
OK
}
}
_
,
hasDir
=
me
.
pendingZips
[
base
]
_
,
hasDir
=
me
.
pendingZips
[
base
]
...
@@ -177,6 +177,7 @@ func (me *MultiZipFs) Unlink(name string) (code fuse.Status) {
...
@@ -177,6 +177,7 @@ func (me *MultiZipFs) Unlink(name string) (code fuse.Status) {
_
,
ok
:=
me
.
zips
[
basename
]
_
,
ok
:=
me
.
zips
[
basename
]
if
ok
{
if
ok
{
me
.
zips
[
basename
]
=
nil
,
false
me
.
zips
[
basename
]
=
nil
,
false
me
.
dirZipFileMap
[
basename
]
=
""
,
false
return
fuse
.
OK
return
fuse
.
OK
}
else
{
}
else
{
return
fuse
.
ENOENT
return
fuse
.
ENOENT
...
@@ -195,12 +196,12 @@ func (me *MultiZipFs) Open(name string, flags uint32) (file fuse.File, code fuse
...
@@ -195,12 +196,12 @@ func (me *MultiZipFs) Open(name string, flags uint32) (file fuse.File, code fuse
me
.
lock
.
RLock
()
me
.
lock
.
RLock
()
defer
me
.
lock
.
RUnlock
()
defer
me
.
lock
.
RUnlock
()
entry
,
ok
:=
me
.
zips
[
basename
]
orig
,
ok
:=
me
.
dirZipFileMap
[
basename
]
if
!
ok
{
if
!
ok
{
return
nil
,
fuse
.
ENOENT
return
nil
,
fuse
.
ENOENT
}
}
return
fuse
.
NewReadOnlyFile
([]
byte
(
entry
.
ZipFileName
)),
fuse
.
OK
return
fuse
.
NewReadOnlyFile
([]
byte
(
orig
)),
fuse
.
OK
}
}
return
nil
,
fuse
.
ENOENT
return
nil
,
fuse
.
ENOENT
...
...
zipfs/zipfs.go
View file @
0ec6d90d
package
zipfs
package
zipfs
import
(
import
(
"github.com/hanwen/go-fuse/fuse"
"archive/zip"
"archive/zip"
"fmt"
"fmt"
"os"
"os"
"strings"
"strings"
"path/filepath"
"path/filepath"
"syscall"
"log"
"log"
)
)
var
_
=
log
.
Printf
var
_
=
log
.
Printf
type
ZipDirTree
struct
{
type
ZipFile
struct
{
subdirs
map
[
string
]
*
ZipDirTree
*
zip
.
File
files
map
[
string
]
*
zip
.
File
}
func
NewZipDirTree
()
*
ZipDirTree
{
d
:=
new
(
ZipDirTree
)
d
.
subdirs
=
make
(
map
[
string
]
*
ZipDirTree
)
d
.
files
=
make
(
map
[
string
]
*
zip
.
File
)
return
d
}
}
func
(
me
*
ZipDirTree
)
Print
(
indent
int
)
{
func
(
me
*
ZipFile
)
Stat
()
*
os
.
FileInfo
{
s
:=
""
// TODO - do something intelligent with timestamps.
for
i
:=
0
;
i
<
indent
;
i
++
{
return
&
os
.
FileInfo
{
s
=
s
+
" "
Mode
:
syscall
.
S_IFREG
|
0444
,
}
Size
:
int64
(
me
.
File
.
UncompressedSize
),
for
k
,
v
:=
range
me
.
subdirs
{
fmt
.
Println
(
s
+
k
+
":"
)
v
.
Print
(
indent
+
2
)
}
for
k
,
_
:=
range
me
.
files
{
fmt
.
Println
(
s
+
k
)
}
}
}
}
func
(
me
*
ZipDirTree
)
Lookup
(
name
string
)
(
*
ZipDirTree
,
*
zip
.
File
)
{
func
(
me
*
ZipFile
)
Data
()
[]
byte
{
if
name
==
""
{
data
:=
make
([]
byte
,
me
.
UncompressedSize
)
return
me
,
nil
zf
:=
(
*
me
)
}
rc
,
err
:=
zf
.
Open
()
parent
:=
me
if
err
!=
nil
{
comps
:=
strings
.
Split
(
filepath
.
Clean
(
name
),
"/"
,
-
1
)
panic
(
"zip open"
)
for
_
,
c
:=
range
comps
[
:
len
(
comps
)
-
1
]
{
parent
=
parent
.
subdirs
[
c
]
if
parent
==
nil
{
return
nil
,
nil
}
}
base
:=
comps
[
len
(
comps
)
-
1
]
file
,
ok
:=
parent
.
files
[
base
]
if
ok
{
return
parent
,
file
}
}
return
parent
.
subdirs
[
base
],
nil
start
:=
0
}
for
{
n
,
err
:=
rc
.
Read
(
data
[
start
:
])
func
(
me
*
ZipDirTree
)
FindDir
(
name
string
)
*
ZipDirTree
{
start
+=
n
s
,
ok
:=
me
.
subdirs
[
name
]
if
err
==
os
.
EOF
{
if
!
ok
{
break
s
=
NewZipDirTree
()
}
me
.
subdirs
[
name
]
=
s
if
err
!=
nil
&&
err
!=
os
.
EOF
{
panic
(
fmt
.
Sprintf
(
"read err: %v, n %v, sz %v"
,
err
,
n
,
len
(
data
)))
}
}
}
return
s
return
data
}
}
type
ZipArchiveFileSystem
struct
{
zipReader
*
zip
.
ReadCloser
tree
*
ZipDirTree
ZipFileName
string
fuse
.
DefaultFileSystem
func
zipFilesToTree
(
files
[]
*
zip
.
File
)
*
MemTree
{
}
t
:=
NewMemTree
()
func
zipFilesToTree
(
files
[]
*
zip
.
File
)
*
ZipDirTree
{
t
:=
NewZipDirTree
()
for
_
,
f
:=
range
files
{
for
_
,
f
:=
range
files
{
parent
:=
t
parent
:=
t
comps
:=
strings
.
Split
(
filepath
.
Clean
(
f
.
Name
),
"/"
,
-
1
)
comps
:=
strings
.
Split
(
filepath
.
Clean
(
f
.
Name
),
"/"
,
-
1
)
...
@@ -94,112 +63,20 @@ func zipFilesToTree(files []*zip.File) *ZipDirTree {
...
@@ -94,112 +63,20 @@ func zipFilesToTree(files []*zip.File) *ZipDirTree {
parent
=
parent
.
FindDir
(
c
)
parent
=
parent
.
FindDir
(
c
)
}
}
if
base
!=
""
{
if
base
!=
""
{
parent
.
files
[
base
]
=
f
parent
.
files
[
base
]
=
&
ZipFile
{
File
:
f
}
}
}
}
}
return
t
return
t
}
}
// NewZipArchiveFileSystem creates a new file-system for the
// NewZipArchiveFileSystem creates a new file-system for the
// zip file named name.
// zip file named name.
func
NewZipArchiveFileSystem
(
name
string
)
(
*
ZipArchiveFileSystem
,
os
.
Error
)
{
func
NewZipArchiveFileSystem
(
name
string
)
(
*
MemTreeFileSystem
,
os
.
Error
)
{
z
:=
new
(
ZipArchiveFileSystem
)
r
,
err
:=
zip
.
OpenReader
(
name
)
r
,
err
:=
zip
.
OpenReader
(
name
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
z
.
ZipFileName
=
name
z
:=
NewMemTreeFileSystem
(
zipFilesToTree
(
r
.
File
))
z
.
zipReader
=
r
z
.
tree
=
zipFilesToTree
(
r
.
File
)
return
z
,
nil
return
z
,
nil
}
}
const
zip_DIRMODE
uint32
=
fuse
.
S_IFDIR
|
0700
const
zip_FILEMODE
uint32
=
fuse
.
S_IFREG
|
0600
func
(
me
*
ZipArchiveFileSystem
)
GetAttr
(
name
string
)
(
*
os
.
FileInfo
,
fuse
.
Status
)
{
dir
,
file
:=
me
.
tree
.
Lookup
(
name
)
if
dir
==
nil
{
return
nil
,
fuse
.
ENOENT
}
a
:=
&
os
.
FileInfo
{}
if
file
==
nil
{
a
.
Mode
=
zip_DIRMODE
}
else
{
// TODO - do something intelligent with timestamps.
a
.
Mode
=
zip_FILEMODE
a
.
Size
=
int64
(
file
.
UncompressedSize
)
}
return
a
,
fuse
.
OK
}
func
(
me
*
ZipArchiveFileSystem
)
Open
(
name
string
,
flags
uint32
)
(
file
fuse
.
File
,
code
fuse
.
Status
)
{
if
flags
&
fuse
.
O_ANYWRITE
!=
0
{
return
nil
,
fuse
.
EPERM
}
_
,
zfile
:=
me
.
tree
.
Lookup
(
name
)
if
zfile
==
nil
{
return
nil
,
fuse
.
ENOENT
}
return
NewZipFile
(
zfile
),
fuse
.
OK
}
func
(
me
*
ZipArchiveFileSystem
)
OpenDir
(
name
string
)
(
stream
chan
fuse
.
DirEntry
,
code
fuse
.
Status
)
{
zdir
,
file
:=
me
.
tree
.
Lookup
(
name
)
if
file
!=
nil
{
return
nil
,
fuse
.
ENOSYS
}
if
zdir
==
nil
{
panic
(
"zdir"
)
}
stream
=
make
(
chan
fuse
.
DirEntry
)
go
func
()
{
for
k
,
_
:=
range
zdir
.
files
{
stream
<-
fuse
.
DirEntry
{
Name
:
k
,
Mode
:
zip_FILEMODE
,
}
}
for
k
,
_
:=
range
zdir
.
subdirs
{
stream
<-
fuse
.
DirEntry
{
Name
:
k
,
Mode
:
zip_DIRMODE
,
}
}
close
(
stream
)
}()
return
stream
,
fuse
.
OK
}
////////////////////////////////////////////////////////////////
// files & dirs
type
ZipFile
struct
{
data
[]
byte
fuse
.
DefaultFile
}
func
NewZipFile
(
f
*
zip
.
File
)
fuse
.
File
{
data
:=
make
([]
byte
,
f
.
UncompressedSize
)
rc
,
err
:=
f
.
Open
()
if
err
!=
nil
{
panic
(
"zip open"
)
}
start
:=
0
for
{
n
,
err
:=
rc
.
Read
(
data
[
start
:
])
start
+=
n
if
err
==
os
.
EOF
{
break
}
if
err
!=
nil
&&
err
!=
os
.
EOF
{
panic
(
fmt
.
Sprintf
(
"read err: %v, n %v, sz %v"
,
err
,
n
,
len
(
data
)))
}
}
return
fuse
.
NewReadOnlyFile
(
data
)
}
zipfs/zipfs_test.go
View file @
0ec6d90d
...
@@ -22,6 +22,7 @@ func TestZipFs(t *testing.T) {
...
@@ -22,6 +22,7 @@ func TestZipFs(t *testing.T) {
state
.
Mount
(
mountPoint
)
state
.
Mount
(
mountPoint
)
defer
state
.
Unmount
()
defer
state
.
Unmount
()
state
.
Debug
=
true
go
state
.
Loop
(
false
)
go
state
.
Loop
(
false
)
d
,
err
:=
os
.
Open
(
mountPoint
)
d
,
err
:=
os
.
Open
(
mountPoint
)
...
@@ -55,7 +56,7 @@ func TestZipFs(t *testing.T) {
...
@@ -55,7 +56,7 @@ func TestZipFs(t *testing.T) {
n
,
err
:=
f
.
Read
(
b
)
n
,
err
:=
f
.
Read
(
b
)
b
=
b
[
:
n
]
b
=
b
[
:
n
]
if
string
(
b
[
:
n
]
)
!=
"hello
\n
"
{
if
string
(
b
)
!=
"hello
\n
"
{
t
.
Error
(
"content fail"
,
b
[
:
n
])
t
.
Error
(
"content fail"
,
b
[
:
n
])
}
}
f
.
Close
()
f
.
Close
()
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment