Skip to content

Commit 904aebc

Browse files
committed
Add more fs methods to Filesystem interface
Interface is extended as a part of ext4 improvements effort #9 (comment) Also, Remove method is introduced for all supported filesystems.
1 parent f66ea89 commit 904aebc

File tree

10 files changed

+234
-17
lines changed

10 files changed

+234
-17
lines changed

Diff for: disk/disk.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ func (d *Disk) CreateFilesystem(spec FilesystemSpec) (filesystem.FileSystem, err
189189
case filesystem.TypeExt4:
190190
return ext4.Create(d.File, size, start, d.LogicalBlocksize, nil)
191191
case filesystem.TypeSquashfs:
192-
return nil, errors.New("squashfs is a read-only filesystem")
192+
return nil, filesystem.ErrReadonlyFilesystem
193193
default:
194194
return nil, errors.New("unknown filesystem type requested")
195195
}

Diff for: filesystem/ext4/ext4.go

+43-2
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,9 @@ func Read(file util.File, size, start, sectorsize int64) (*FileSystem, error) {
684684
}, nil
685685
}
686686

687+
// interface guard
688+
var _ filesystem.FileSystem = (*FileSystem)(nil)
689+
687690
// Type returns the type code for the filesystem. Always returns filesystem.TypeExt4
688691
func (fs *FileSystem) Type() filesystem.Type {
689692
return filesystem.TypeExt4
@@ -699,6 +702,34 @@ func (fs *FileSystem) Mkdir(p string) error {
699702
return err
700703
}
701704

705+
// creates a filesystem node (file, device special file, or named pipe) named pathname,
706+
// with attributes specified by mode and dev
707+
func (fs *FileSystem) Mknod(path string, mode uint32, dev int) error {
708+
return filesystem.ErrNotImplemented
709+
}
710+
711+
// creates a new link (also known as a hard link) to an existing file.
712+
func (fs *FileSystem) Link(oldpath string, newpath string) error {
713+
return filesystem.ErrNotImplemented
714+
}
715+
716+
// creates a symbolic link named linkpath which contains the string target.
717+
func (fs *FileSystem) Symlink(oldpath string, newpath string) error {
718+
return filesystem.ErrNotImplemented
719+
}
720+
721+
// Chmod changes the mode of the named file to mode. If the file is a symbolic link,
722+
// it changes the mode of the link's target.
723+
func (fs *FileSystem) Chmod(name string, mode os.FileMode) error {
724+
return filesystem.ErrNotImplemented
725+
}
726+
727+
// Chown changes the numeric uid and gid of the named file. If the file is a symbolic link,
728+
// it changes the uid and gid of the link's target. A uid or gid of -1 means to not change that value
729+
func (fs *FileSystem) Chown(name string, uid, gid int) error {
730+
return filesystem.ErrNotImplemented
731+
}
732+
702733
// ReadDir return the contents of a given directory in a given filesystem.
703734
//
704735
// Returns a slice of os.FileInfo with all of the entries in the directory.
@@ -808,12 +839,22 @@ func (fs *FileSystem) Label() string {
808839
return fs.superblock.volumeLabel
809840
}
810841

811-
// Rm remove file or directory at path.
842+
// Rename renames (moves) oldpath to newpath. If newpath already exists and is not a directory, Rename replaces it.
843+
func (fs *FileSystem) Rename(oldpath, newpath string) error {
844+
return filesystem.ErrNotImplemented
845+
}
846+
847+
// Deprecated: use filesystem.Remove(p string) instead
848+
func (fs *FileSystem) Rm(p string) error {
849+
return fs.Remove(p)
850+
}
851+
852+
// Removes file or directory at path.
812853
// If path is directory, it only will remove if it is empty.
813854
// If path is a file, it will remove the file.
814855
// Will not remove any parents.
815856
// Error if the file does not exist or is not an empty directory
816-
func (fs *FileSystem) Rm(p string) error {
857+
func (fs *FileSystem) Remove(p string) error {
817858
parentDir, entry, err := fs.getEntryAndParent(p)
818859
if err != nil {
819860
return err

Diff for: filesystem/fat32/fat32.go

+40
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,9 @@ func (fs *FileSystem) writeFat() error {
470470
return nil
471471
}
472472

473+
// interface guard
474+
var _ filesystem.FileSystem = (*FileSystem)(nil)
475+
473476
// Type returns the type code for the filesystem. Always returns filesystem.TypeFat32
474477
func (fs *FileSystem) Type() filesystem.Type {
475478
return filesystem.TypeFat32
@@ -485,6 +488,34 @@ func (fs *FileSystem) Mkdir(p string) error {
485488
return err
486489
}
487490

491+
// creates a filesystem node (file, device special file, or named pipe) named pathname,
492+
// with attributes specified by mode and dev
493+
func (fs *FileSystem) Mknod(path string, mode uint32, dev int) error {
494+
return filesystem.ErrNotSupported
495+
}
496+
497+
// creates a new link (also known as a hard link) to an existing file.
498+
func (fs *FileSystem) Link(oldpath string, newpath string) error {
499+
return filesystem.ErrNotSupported
500+
}
501+
502+
// creates a symbolic link named linkpath which contains the string target.
503+
func (fs *FileSystem) Symlink(oldpath string, newpath string) error {
504+
return filesystem.ErrNotSupported
505+
}
506+
507+
// Chmod changes the mode of the named file to mode. If the file is a symbolic link,
508+
// it changes the mode of the link's target.
509+
func (fs *FileSystem) Chmod(name string, mode os.FileMode) error {
510+
return filesystem.ErrNotSupported
511+
}
512+
513+
// Chown changes the numeric uid and gid of the named file. If the file is a symbolic link,
514+
// it changes the uid and gid of the link's target. A uid or gid of -1 means to not change that value
515+
func (fs *FileSystem) Chown(name string, uid, gid int) error {
516+
return filesystem.ErrNotSupported
517+
}
518+
488519
// ReadDir return the contents of a given directory in a given filesystem.
489520
//
490521
// Returns a slice of os.FileInfo with all of the entries in the directory.
@@ -606,6 +637,15 @@ func (fs *FileSystem) OpenFile(p string, flag int) (filesystem.File, error) {
606637
}, nil
607638
}
608639

640+
// Rename renames (moves) oldpath to newpath. If newpath already exists and is not a directory, Rename replaces it.
641+
func (fs *FileSystem) Rename(oldpath, newpath string) error {
642+
return filesystem.ErrNotImplemented
643+
}
644+
645+
func (fs *FileSystem) Remove(p string) error {
646+
return filesystem.ErrNotImplemented
647+
}
648+
609649
// Label get the label of the filesystem from the secial file in the root directory.
610650
// The label stored in the boot sector is ignored to mimic Windows behavior which
611651
// only stores and reads the label from the special file in the root directory.

Diff for: filesystem/fat32/fat32_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -455,9 +455,9 @@ func TestFat32OpenFile(t *testing.T) {
455455
{"/CORTO1.TXT", os.O_RDWR, false, "This is a very long replacement string", "Tenemos un archivo corto\nThis is a very long replacement string", nil},
456456
{"/CORTO1.TXT", os.O_RDWR, false, "Two", "Tenemos un archivo corto\nTwo", nil},
457457
// - open for append file that does exist (write contents, check that appended)
458-
{"/CORTO1.TXT", os.O_APPEND, false, "More", "", fmt.Errorf("cannot write to file opened read-only")},
458+
{"/CORTO1.TXT", os.O_APPEND, false, "More", "", filesystem.ErrReadonlyFilesystem},
459459
{"/CORTO1.TXT", os.O_APPEND | os.O_RDWR, false, "More", "Tenemos un archivo corto\nMore", nil},
460-
{"/CORTO1.TXT", os.O_APPEND, true, "More", "", fmt.Errorf("cannot write to file opened read-only")},
460+
{"/CORTO1.TXT", os.O_APPEND, true, "More", "", filesystem.ErrReadonlyFilesystem},
461461
{"/CORTO1.TXT", os.O_APPEND | os.O_RDWR, true, "More", "Moremos un archivo corto\n", nil},
462462
}
463463
for _, t2 := range tests {

Diff for: filesystem/fat32/file.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"fmt"
55
"io"
66
"os"
7+
8+
"github.com/diskfs/go-diskfs/filesystem"
79
)
810

911
// File represents a single file in a FAT32 filesystem
@@ -108,7 +110,7 @@ func (fl *File) Write(p []byte) (int, error) {
108110
fs := fl.filesystem
109111
// if the file was not opened RDWR, nothing we can do
110112
if !fl.isReadWrite {
111-
return totalWritten, fmt.Errorf("cannot write to file opened read-only")
113+
return totalWritten, filesystem.ErrReadonlyFilesystem
112114
}
113115
// what is the new file size?
114116
writeSize := len(p)

Diff for: filesystem/filesystem.go

+28-4
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,49 @@
33
package filesystem
44

55
import (
6+
"errors"
67
"os"
78
)
89

10+
var (
11+
ErrNotSupported = errors.New("method not supported by this filesystem")
12+
ErrNotImplemented = errors.New("method not implemented (patches are welcome)")
13+
ErrReadonlyFilesystem = errors.New("read-only filesystem")
14+
)
15+
916
// FileSystem is a reference to a single filesystem on a disk
1017
type FileSystem interface {
1118
// Type return the type of filesystem
1219
Type() Type
1320
// Mkdir make a directory
14-
Mkdir(string) error
21+
Mkdir(path string) error
22+
// creates a filesystem node (file, device special file, or named pipe) named pathname,
23+
// with attributes specified by mode and dev
24+
Mknod(path string, mode uint32, dev int) error
25+
// creates a new link (also known as a hard link) to an existing file.
26+
Link(oldpath string, newpath string) error
27+
// creates a symbolic link named linkpath which contains the string target.
28+
Symlink(oldpath string, newpath string) error
29+
// Chmod changes the mode of the named file to mode. If the file is a symbolic link,
30+
// it changes the mode of the link's target.
31+
Chmod(name string, mode os.FileMode) error
32+
// Chown changes the numeric uid and gid of the named file. If the file is a symbolic link,
33+
// it changes the uid and gid of the link's target. A uid or gid of -1 means to not change that value
34+
Chown(name string, uid, gid int) error
1535
// ReadDir read the contents of a directory
16-
ReadDir(string) ([]os.FileInfo, error)
36+
ReadDir(path string) ([]os.FileInfo, error)
1737
// OpenFile open a handle to read or write to a file
18-
OpenFile(string, int) (File, error)
38+
OpenFile(path string, flag int) (File, error)
39+
// Rename renames (moves) oldpath to newpath. If newpath already exists and is not a directory, Rename replaces it.
40+
Rename(oldpath, newpath string) error
41+
// removes the named file or (empty) directory.
42+
Remove(path string) error
1943
// Label get the label for the filesystem, or "" if none. Be careful to trim it, as it may contain
2044
// leading or following whitespace. The label is passed as-is and not cleaned up at all.
2145
Label() string
2246
// SetLabel changes the label on the writable filesystem. Different file system may hav different
2347
// length constraints.
24-
SetLabel(string) error
48+
SetLabel(label string) error
2549
}
2650

2751
// Type represents the type of disk this is

Diff for: filesystem/iso9660/file.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"fmt"
55
"io"
66
"os"
7+
8+
"github.com/diskfs/go-diskfs/filesystem"
79
)
810

911
// File represents a single file in an iso9660 filesystem
@@ -65,7 +67,7 @@ func (fl *File) Read(b []byte) (int, error) {
6567
//
6668
// you cannot write to an iso, so this returns an error
6769
func (fl *File) Write(_ []byte) (int, error) {
68-
return 0, fmt.Errorf("cannot write to a read-only iso filesystem")
70+
return 0, filesystem.ErrReadonlyFilesystem
6971
}
7072

7173
// Seek set the offset to a particular point in the file

Diff for: filesystem/iso9660/iso9660.go

+56-2
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,9 @@ func Read(file util.File, size, start, blocksize int64) (*FileSystem, error) {
282282
return fs, nil
283283
}
284284

285+
// interface guard
286+
var _ filesystem.FileSystem = (*FileSystem)(nil)
287+
285288
// Type returns the type code for the filesystem. Always returns filesystem.TypeFat32
286289
func (fsm *FileSystem) Type() filesystem.Type {
287290
return filesystem.TypeISO9660
@@ -295,7 +298,7 @@ func (fsm *FileSystem) Type() filesystem.Type {
295298
// if readonly and not in workspace, will return an error
296299
func (fsm *FileSystem) Mkdir(p string) error {
297300
if fsm.workspace == "" {
298-
return fmt.Errorf("cannot write to read-only filesystem")
301+
return filesystem.ErrReadonlyFilesystem
299302
}
300303
err := os.MkdirAll(path.Join(fsm.workspace, p), 0o755)
301304
if err != nil {
@@ -305,6 +308,42 @@ func (fsm *FileSystem) Mkdir(p string) error {
305308
return err
306309
}
307310

311+
// creates a filesystem node (file, device special file, or named pipe) named pathname,
312+
// with attributes specified by mode and dev
313+
func (fs *FileSystem) Mknod(path string, mode uint32, dev int) error {
314+
// Rock Ridge has device files support
315+
// https://en.wikipedia.org/wiki/ISO_9660#Rock_Ridge
316+
return filesystem.ErrNotImplemented
317+
}
318+
319+
// creates a new link (also known as a hard link) to an existing file.
320+
func (fs *FileSystem) Link(oldpath string, newpath string) error {
321+
return filesystem.ErrNotSupported
322+
}
323+
324+
// creates a symbolic link named linkpath which contains the string target.
325+
func (fs *FileSystem) Symlink(oldpath string, newpath string) error {
326+
// Rock Ridge has symlink support
327+
// https://en.wikipedia.org/wiki/ISO_9660#Rock_Ridge
328+
return filesystem.ErrNotImplemented
329+
}
330+
331+
// Chmod changes the mode of the named file to mode. If the file is a symbolic link,
332+
// it changes the mode of the link's target.
333+
func (fs *FileSystem) Chmod(name string, mode os.FileMode) error {
334+
// Rock Ridge has UNIX-style file modes support
335+
// https://en.wikipedia.org/wiki/ISO_9660#Rock_Ridge
336+
return filesystem.ErrNotImplemented
337+
}
338+
339+
// Chown changes the numeric uid and gid of the named file. If the file is a symbolic link,
340+
// it changes the uid and gid of the link's target. A uid or gid of -1 means to not change that value
341+
func (fs *FileSystem) Chown(name string, uid, gid int) error {
342+
// Rock Ridge has user ids and group ids support
343+
// https://en.wikipedia.org/wiki/ISO_9660#Rock_Ridge
344+
return filesystem.ErrNotImplemented
345+
}
346+
308347
// ReadDir return the contents of a given directory in a given filesystem.
309348
//
310349
// Returns a slice of os.FileInfo with all of the entries in the directory.
@@ -368,7 +407,7 @@ func (fsm *FileSystem) OpenFile(p string, flag int) (filesystem.File, error) {
368407
writeMode := flag&os.O_WRONLY != 0 || flag&os.O_RDWR != 0 || flag&os.O_APPEND != 0 || flag&os.O_CREATE != 0 || flag&os.O_TRUNC != 0 || flag&os.O_EXCL != 0
369408
if fsm.workspace == "" {
370409
if writeMode {
371-
return nil, fmt.Errorf("cannot write to read-only filesystem")
410+
return nil, filesystem.ErrReadonlyFilesystem
372411
}
373412

374413
// get the directory entries
@@ -414,6 +453,21 @@ func (fsm *FileSystem) OpenFile(p string, flag int) (filesystem.File, error) {
414453
return f, nil
415454
}
416455

456+
// Rename renames (moves) oldpath to newpath. If newpath already exists and is not a directory, Rename replaces it.
457+
func (fsm *FileSystem) Rename(oldpath, newpath string) error {
458+
if fsm.workspace == "" {
459+
return filesystem.ErrReadonlyFilesystem
460+
}
461+
return os.Rename(path.Join(fsm.workspace, oldpath), path.Join(fsm.workspace, newpath))
462+
}
463+
464+
func (fsm *FileSystem) Remove(p string) error {
465+
if fsm.workspace == "" {
466+
return filesystem.ErrReadonlyFilesystem
467+
}
468+
return os.Remove(path.Join(fsm.workspace, p))
469+
}
470+
417471
// readDirectory - read directory entry on iso only (not workspace)
418472
func (fsm *FileSystem) readDirectory(p string) ([]*directoryEntry, error) {
419473
var (

Diff for: filesystem/squashfs/file.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"fmt"
55
"io"
66
"os"
7+
8+
"github.com/diskfs/go-diskfs/filesystem"
79
)
810

911
// File represents a single file in a squashfs filesystem
@@ -148,7 +150,7 @@ func (fl *File) Read(b []byte) (int, error) {
148150
//
149151
//nolint:unused,revive // but it is important to implement the interface
150152
func (fl *File) Write(p []byte) (int, error) {
151-
return 0, fmt.Errorf("cannot write to a read-only squashfs filesystem")
153+
return 0, filesystem.ErrReadonlyFilesystem
152154
}
153155

154156
// Seek set the offset to a particular point in the file

0 commit comments

Comments
 (0)