github.com/scaleoutsean/fusego@v0.0.0-20220224074057-4a6429e46bb8/samples/memfs/memfs_test.go (about)

     1  // Copyright 2015 Google Inc. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package memfs_test
    16  
    17  import (
    18  	"bytes"
    19  	"io"
    20  	"io/ioutil"
    21  	"os"
    22  	"os/user"
    23  	"path"
    24  	"reflect"
    25  	"runtime"
    26  	"strconv"
    27  	"syscall"
    28  	"testing"
    29  	"time"
    30  
    31  	fallocate "github.com/detailyang/go-fallocate"
    32  	"github.com/scaleoutsean/fusego"
    33  	"github.com/scaleoutsean/fusego/fusetesting"
    34  	"github.com/scaleoutsean/fusego/samples"
    35  	"github.com/scaleoutsean/fusego/samples/memfs"
    36  	. "github.com/jacobsa/oglematchers"
    37  	. "github.com/jacobsa/ogletest"
    38  	"golang.org/x/sys/unix"
    39  )
    40  
    41  func TestMemFS(t *testing.T) { RunTests(t) }
    42  
    43  // The radius we use for "expect mtime is within"-style assertions. We can't
    44  // share a synchronized clock with the ultimate source of mtimes because with
    45  // writeback caching enabled the kernel manufactures them based on wall time.
    46  const timeSlop = 25 * time.Millisecond
    47  
    48  ////////////////////////////////////////////////////////////////////////
    49  // Helpers
    50  ////////////////////////////////////////////////////////////////////////
    51  
    52  func currentUid() uint32 {
    53  	user, err := user.Current()
    54  	if err != nil {
    55  		panic(err)
    56  	}
    57  
    58  	uid, err := strconv.ParseUint(user.Uid, 10, 32)
    59  	if err != nil {
    60  		panic(err)
    61  	}
    62  
    63  	return uint32(uid)
    64  }
    65  
    66  func currentGid() uint32 {
    67  	user, err := user.Current()
    68  	if err != nil {
    69  		panic(err)
    70  	}
    71  
    72  	gid, err := strconv.ParseUint(user.Gid, 10, 32)
    73  	if err != nil {
    74  		panic(err)
    75  	}
    76  
    77  	return uint32(gid)
    78  }
    79  
    80  // Transform the supplied mode by the current umask.
    81  func applyUmask(m os.FileMode) os.FileMode {
    82  	// HACK(jacobsa): Use umask(2) to change and restore the umask in order to
    83  	// figure out what the mask is. See the listing in `man getumask`.
    84  	umask := syscall.Umask(0)
    85  	syscall.Umask(umask)
    86  
    87  	// Apply it.
    88  	return m &^ os.FileMode(umask)
    89  }
    90  
    91  ////////////////////////////////////////////////////////////////////////
    92  // Boilerplate
    93  ////////////////////////////////////////////////////////////////////////
    94  
    95  type memFSTest struct {
    96  	samples.SampleTest
    97  }
    98  
    99  func (t *memFSTest) SetUp(ti *TestInfo) {
   100  	t.Server = memfs.NewMemFS(currentUid(), currentGid())
   101  	t.SampleTest.SetUp(ti)
   102  }
   103  
   104  ////////////////////////////////////////////////////////////////////////
   105  // Basics
   106  ////////////////////////////////////////////////////////////////////////
   107  
   108  type MemFSTest struct {
   109  	memFSTest
   110  }
   111  
   112  func init() { RegisterTestSuite(&MemFSTest{}) }
   113  
   114  func (t *MemFSTest) ContentsOfEmptyFileSystem() {
   115  	entries, err := fusetesting.ReadDirPicky(t.Dir)
   116  
   117  	AssertEq(nil, err)
   118  	ExpectThat(entries, ElementsAre())
   119  }
   120  
   121  func (t *MemFSTest) Mkdir_OneLevel() {
   122  	var err error
   123  	var fi os.FileInfo
   124  	var stat *syscall.Stat_t
   125  	var entries []os.FileInfo
   126  
   127  	dirName := path.Join(t.Dir, "dir")
   128  
   129  	// Create a directory within the root.
   130  	createTime := time.Now()
   131  	err = os.Mkdir(dirName, 0754)
   132  	AssertEq(nil, err)
   133  
   134  	// Stat the directory.
   135  	fi, err = os.Stat(dirName)
   136  	stat = fi.Sys().(*syscall.Stat_t)
   137  
   138  	AssertEq(nil, err)
   139  	ExpectEq("dir", fi.Name())
   140  	ExpectEq(0, fi.Size())
   141  	ExpectEq(os.ModeDir|applyUmask(0754), fi.Mode())
   142  	ExpectThat(fi, fusetesting.MtimeIsWithin(createTime, timeSlop))
   143  	ExpectThat(fi, fusetesting.BirthtimeIsWithin(createTime, timeSlop))
   144  	ExpectTrue(fi.IsDir())
   145  
   146  	ExpectNe(0, stat.Ino)
   147  	ExpectEq(1, stat.Nlink)
   148  	ExpectEq(currentUid(), stat.Uid)
   149  	ExpectEq(currentGid(), stat.Gid)
   150  	ExpectEq(0, stat.Size)
   151  
   152  	// Check the root's mtime.
   153  	fi, err = os.Stat(t.Dir)
   154  
   155  	AssertEq(nil, err)
   156  	ExpectThat(fi, fusetesting.MtimeIsWithin(createTime, timeSlop))
   157  
   158  	// Read the directory.
   159  	entries, err = fusetesting.ReadDirPicky(dirName)
   160  
   161  	AssertEq(nil, err)
   162  	ExpectThat(entries, ElementsAre())
   163  
   164  	// Read the root.
   165  	entries, err = fusetesting.ReadDirPicky(t.Dir)
   166  
   167  	AssertEq(nil, err)
   168  	AssertEq(1, len(entries))
   169  
   170  	fi = entries[0]
   171  	ExpectEq("dir", fi.Name())
   172  	ExpectEq(os.ModeDir|applyUmask(0754), fi.Mode())
   173  }
   174  
   175  func (t *MemFSTest) Mkdir_TwoLevels() {
   176  	var err error
   177  	var fi os.FileInfo
   178  	var stat *syscall.Stat_t
   179  	var entries []os.FileInfo
   180  
   181  	// Create a directory within the root.
   182  	err = os.Mkdir(path.Join(t.Dir, "parent"), 0700)
   183  	AssertEq(nil, err)
   184  
   185  	// Create a child of that directory.
   186  	createTime := time.Now()
   187  	err = os.Mkdir(path.Join(t.Dir, "parent/dir"), 0754)
   188  	AssertEq(nil, err)
   189  
   190  	// Stat the directory.
   191  	fi, err = os.Stat(path.Join(t.Dir, "parent/dir"))
   192  	stat = fi.Sys().(*syscall.Stat_t)
   193  
   194  	AssertEq(nil, err)
   195  	ExpectEq("dir", fi.Name())
   196  	ExpectEq(0, fi.Size())
   197  	ExpectEq(os.ModeDir|applyUmask(0754), fi.Mode())
   198  	ExpectThat(fi, fusetesting.MtimeIsWithin(createTime, timeSlop))
   199  	ExpectThat(fi, fusetesting.BirthtimeIsWithin(createTime, timeSlop))
   200  	ExpectTrue(fi.IsDir())
   201  
   202  	ExpectNe(0, stat.Ino)
   203  	ExpectEq(1, stat.Nlink)
   204  	ExpectEq(currentUid(), stat.Uid)
   205  	ExpectEq(currentGid(), stat.Gid)
   206  	ExpectEq(0, stat.Size)
   207  
   208  	// Check the parent's mtime.
   209  	fi, err = os.Stat(path.Join(t.Dir, "parent"))
   210  	AssertEq(nil, err)
   211  	ExpectThat(fi, fusetesting.MtimeIsWithin(createTime, timeSlop))
   212  
   213  	// Read the directory.
   214  	entries, err = fusetesting.ReadDirPicky(path.Join(t.Dir, "parent/dir"))
   215  
   216  	AssertEq(nil, err)
   217  	ExpectThat(entries, ElementsAre())
   218  
   219  	// Read the parent.
   220  	entries, err = fusetesting.ReadDirPicky(path.Join(t.Dir, "parent"))
   221  
   222  	AssertEq(nil, err)
   223  	AssertEq(1, len(entries))
   224  
   225  	fi = entries[0]
   226  	ExpectEq("dir", fi.Name())
   227  	ExpectEq(os.ModeDir|applyUmask(0754), fi.Mode())
   228  }
   229  
   230  func (t *MemFSTest) Mkdir_AlreadyExists() {
   231  	var err error
   232  	dirName := path.Join(t.Dir, "dir")
   233  
   234  	// Create the directory once.
   235  	err = os.Mkdir(dirName, 0754)
   236  	AssertEq(nil, err)
   237  
   238  	// Attempt to create it again.
   239  	err = os.Mkdir(dirName, 0754)
   240  
   241  	AssertNe(nil, err)
   242  	ExpectThat(err, Error(HasSubstr("exists")))
   243  }
   244  
   245  func (t *MemFSTest) Mkdir_IntermediateIsFile() {
   246  	var err error
   247  
   248  	// Create a file.
   249  	fileName := path.Join(t.Dir, "foo")
   250  	err = ioutil.WriteFile(fileName, []byte{}, 0700)
   251  	AssertEq(nil, err)
   252  
   253  	// Attempt to create a directory within the file.
   254  	dirName := path.Join(fileName, "dir")
   255  	err = os.Mkdir(dirName, 0754)
   256  
   257  	AssertNe(nil, err)
   258  	ExpectThat(err, Error(HasSubstr("not a directory")))
   259  }
   260  
   261  func (t *MemFSTest) Mkdir_IntermediateIsNonExistent() {
   262  	var err error
   263  
   264  	// Attempt to create a sub-directory of a non-existent sub-directory.
   265  	dirName := path.Join(t.Dir, "foo/dir")
   266  	err = os.Mkdir(dirName, 0754)
   267  
   268  	AssertNe(nil, err)
   269  	ExpectThat(err, Error(HasSubstr("no such file or directory")))
   270  }
   271  
   272  func (t *MemFSTest) Mkdir_PermissionDenied() {
   273  	var err error
   274  
   275  	// Create a directory within the root without write permissions.
   276  	err = os.Mkdir(path.Join(t.Dir, "parent"), 0500)
   277  	AssertEq(nil, err)
   278  
   279  	// Attempt to create a child of that directory.
   280  	err = os.Mkdir(path.Join(t.Dir, "parent/dir"), 0754)
   281  
   282  	AssertNe(nil, err)
   283  	ExpectThat(err, Error(HasSubstr("permission denied")))
   284  }
   285  
   286  func (t *MemFSTest) CreateNewFile_InRoot() {
   287  	var err error
   288  	var fi os.FileInfo
   289  	var stat *syscall.Stat_t
   290  
   291  	// Write a file.
   292  	fileName := path.Join(t.Dir, "foo")
   293  	const contents = "Hello\x00world"
   294  
   295  	createTime := time.Now()
   296  	err = ioutil.WriteFile(fileName, []byte(contents), 0400)
   297  	AssertEq(nil, err)
   298  
   299  	// Stat it.
   300  	fi, err = os.Stat(fileName)
   301  	stat = fi.Sys().(*syscall.Stat_t)
   302  
   303  	AssertEq(nil, err)
   304  	ExpectEq("foo", fi.Name())
   305  	ExpectEq(len(contents), fi.Size())
   306  	ExpectEq(applyUmask(0400), fi.Mode())
   307  	ExpectThat(fi, fusetesting.MtimeIsWithin(createTime, timeSlop))
   308  	ExpectThat(fi, fusetesting.BirthtimeIsWithin(createTime, timeSlop))
   309  	ExpectFalse(fi.IsDir())
   310  
   311  	ExpectNe(0, stat.Ino)
   312  	ExpectEq(1, stat.Nlink)
   313  	ExpectEq(currentUid(), stat.Uid)
   314  	ExpectEq(currentGid(), stat.Gid)
   315  	ExpectEq(len(contents), stat.Size)
   316  
   317  	// Read it back.
   318  	slice, err := ioutil.ReadFile(fileName)
   319  	AssertEq(nil, err)
   320  	ExpectEq(contents, string(slice))
   321  }
   322  
   323  func (t *MemFSTest) CreateNewFile_InSubDir() {
   324  	var err error
   325  	var fi os.FileInfo
   326  	var stat *syscall.Stat_t
   327  
   328  	// Create a sub-dir.
   329  	dirName := path.Join(t.Dir, "dir")
   330  	err = os.Mkdir(dirName, 0700)
   331  	AssertEq(nil, err)
   332  
   333  	// Write a file.
   334  	fileName := path.Join(dirName, "foo")
   335  	const contents = "Hello\x00world"
   336  
   337  	createTime := time.Now()
   338  	err = ioutil.WriteFile(fileName, []byte(contents), 0400)
   339  	AssertEq(nil, err)
   340  
   341  	// Stat it.
   342  	fi, err = os.Stat(fileName)
   343  	stat = fi.Sys().(*syscall.Stat_t)
   344  
   345  	AssertEq(nil, err)
   346  	ExpectEq("foo", fi.Name())
   347  	ExpectEq(len(contents), fi.Size())
   348  	ExpectEq(applyUmask(0400), fi.Mode())
   349  	ExpectThat(fi, fusetesting.MtimeIsWithin(createTime, timeSlop))
   350  	ExpectThat(fi, fusetesting.BirthtimeIsWithin(createTime, timeSlop))
   351  	ExpectFalse(fi.IsDir())
   352  
   353  	ExpectNe(0, stat.Ino)
   354  	ExpectEq(1, stat.Nlink)
   355  	ExpectEq(currentUid(), stat.Uid)
   356  	ExpectEq(currentGid(), stat.Gid)
   357  	ExpectEq(len(contents), stat.Size)
   358  
   359  	// Read it back.
   360  	slice, err := ioutil.ReadFile(fileName)
   361  	AssertEq(nil, err)
   362  	ExpectEq(contents, string(slice))
   363  }
   364  
   365  func (t *MemFSTest) ModifyExistingFile_InRoot() {
   366  	var err error
   367  	var n int
   368  	var fi os.FileInfo
   369  	var stat *syscall.Stat_t
   370  
   371  	// Write a file.
   372  	fileName := path.Join(t.Dir, "foo")
   373  
   374  	createTime := time.Now()
   375  	err = ioutil.WriteFile(fileName, []byte("Hello, world!"), 0600)
   376  	AssertEq(nil, err)
   377  
   378  	// Open the file and modify it.
   379  	f, err := os.OpenFile(fileName, os.O_WRONLY, 0400)
   380  	t.ToClose = append(t.ToClose, f)
   381  	AssertEq(nil, err)
   382  
   383  	modifyTime := time.Now()
   384  	n, err = f.WriteAt([]byte("H"), 0)
   385  	AssertEq(nil, err)
   386  	AssertEq(1, n)
   387  
   388  	// Stat the file.
   389  	fi, err = os.Stat(fileName)
   390  	stat = fi.Sys().(*syscall.Stat_t)
   391  
   392  	AssertEq(nil, err)
   393  	ExpectEq("foo", fi.Name())
   394  	ExpectEq(len("Hello, world!"), fi.Size())
   395  	ExpectEq(applyUmask(0600), fi.Mode())
   396  	ExpectThat(fi, fusetesting.MtimeIsWithin(modifyTime, timeSlop))
   397  	ExpectThat(fi, fusetesting.BirthtimeIsWithin(createTime, timeSlop))
   398  	ExpectFalse(fi.IsDir())
   399  
   400  	ExpectNe(0, stat.Ino)
   401  	ExpectEq(1, stat.Nlink)
   402  	ExpectEq(currentUid(), stat.Uid)
   403  	ExpectEq(currentGid(), stat.Gid)
   404  	ExpectEq(len("Hello, world!"), stat.Size)
   405  
   406  	// Read the file back.
   407  	slice, err := ioutil.ReadFile(fileName)
   408  	AssertEq(nil, err)
   409  	ExpectEq("Hello, world!", string(slice))
   410  }
   411  
   412  func (t *MemFSTest) ModifyExistingFile_InSubDir() {
   413  	var err error
   414  	var n int
   415  	var fi os.FileInfo
   416  	var stat *syscall.Stat_t
   417  
   418  	// Create a sub-directory.
   419  	dirName := path.Join(t.Dir, "dir")
   420  	err = os.Mkdir(dirName, 0700)
   421  	AssertEq(nil, err)
   422  
   423  	// Write a file.
   424  	fileName := path.Join(dirName, "foo")
   425  
   426  	createTime := time.Now()
   427  	err = ioutil.WriteFile(fileName, []byte("Hello, world!"), 0600)
   428  	AssertEq(nil, err)
   429  
   430  	// Open the file and modify it.
   431  	f, err := os.OpenFile(fileName, os.O_WRONLY, 0400)
   432  	t.ToClose = append(t.ToClose, f)
   433  	AssertEq(nil, err)
   434  
   435  	modifyTime := time.Now()
   436  	n, err = f.WriteAt([]byte("H"), 0)
   437  	AssertEq(nil, err)
   438  	AssertEq(1, n)
   439  
   440  	// Stat the file.
   441  	fi, err = os.Stat(fileName)
   442  	stat = fi.Sys().(*syscall.Stat_t)
   443  
   444  	AssertEq(nil, err)
   445  	ExpectEq("foo", fi.Name())
   446  	ExpectEq(len("Hello, world!"), fi.Size())
   447  	ExpectEq(applyUmask(0600), fi.Mode())
   448  	ExpectThat(fi, fusetesting.MtimeIsWithin(modifyTime, timeSlop))
   449  	ExpectThat(fi, fusetesting.BirthtimeIsWithin(createTime, timeSlop))
   450  	ExpectFalse(fi.IsDir())
   451  
   452  	ExpectNe(0, stat.Ino)
   453  	ExpectEq(1, stat.Nlink)
   454  	ExpectEq(currentUid(), stat.Uid)
   455  	ExpectEq(currentGid(), stat.Gid)
   456  	ExpectEq(len("Hello, world!"), stat.Size)
   457  
   458  	// Read the file back.
   459  	slice, err := ioutil.ReadFile(fileName)
   460  	AssertEq(nil, err)
   461  	ExpectEq("Hello, world!", string(slice))
   462  }
   463  
   464  func (t *MemFSTest) UnlinkFile_Exists() {
   465  	var err error
   466  
   467  	// Write a file.
   468  	fileName := path.Join(t.Dir, "foo")
   469  	err = ioutil.WriteFile(fileName, []byte("Hello, world!"), 0600)
   470  	AssertEq(nil, err)
   471  
   472  	// Unlink it.
   473  	err = os.Remove(fileName)
   474  	AssertEq(nil, err)
   475  
   476  	// Statting it should fail.
   477  	_, err = os.Stat(fileName)
   478  
   479  	AssertNe(nil, err)
   480  	ExpectThat(err, Error(HasSubstr("no such file")))
   481  
   482  	// Nothing should be in the directory.
   483  	entries, err := fusetesting.ReadDirPicky(t.Dir)
   484  	AssertEq(nil, err)
   485  	ExpectThat(entries, ElementsAre())
   486  }
   487  
   488  func (t *MemFSTest) UnlinkFile_NonExistent() {
   489  	err := os.Remove(path.Join(t.Dir, "foo"))
   490  
   491  	AssertNe(nil, err)
   492  	ExpectThat(err, Error(HasSubstr("no such file")))
   493  }
   494  
   495  func (t *MemFSTest) UnlinkFile_StillOpen() {
   496  	fileName := path.Join(t.Dir, "foo")
   497  
   498  	// Create and open a file.
   499  	f, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE, 0600)
   500  	t.ToClose = append(t.ToClose, f)
   501  	AssertEq(nil, err)
   502  
   503  	// Write some data into it.
   504  	n, err := f.Write([]byte("taco"))
   505  	AssertEq(nil, err)
   506  	AssertEq(4, n)
   507  
   508  	// Unlink it.
   509  	err = os.Remove(fileName)
   510  	AssertEq(nil, err)
   511  
   512  	// The directory should no longer contain it.
   513  	entries, err := fusetesting.ReadDirPicky(t.Dir)
   514  	AssertEq(nil, err)
   515  	ExpectThat(entries, ElementsAre())
   516  
   517  	// We should be able to stat the file. It should still show as having
   518  	// contents, but with no links.
   519  	fi, err := f.Stat()
   520  
   521  	AssertEq(nil, err)
   522  	ExpectEq(4, fi.Size())
   523  	ExpectEq(0, fi.Sys().(*syscall.Stat_t).Nlink)
   524  
   525  	// The contents should still be available.
   526  	buf := make([]byte, 1024)
   527  	n, err = f.ReadAt(buf, 0)
   528  
   529  	AssertEq(io.EOF, err)
   530  	AssertEq(4, n)
   531  	ExpectEq("taco", string(buf[:4]))
   532  
   533  	// Writing should still work, too.
   534  	n, err = f.Write([]byte("burrito"))
   535  	AssertEq(nil, err)
   536  	AssertEq(len("burrito"), n)
   537  }
   538  
   539  func (t *MemFSTest) Rmdir_NonEmpty() {
   540  	var err error
   541  
   542  	// Create two levels of directories.
   543  	err = os.MkdirAll(path.Join(t.Dir, "foo/bar"), 0754)
   544  	AssertEq(nil, err)
   545  
   546  	// Attempt to remove the parent.
   547  	err = os.Remove(path.Join(t.Dir, "foo"))
   548  
   549  	AssertNe(nil, err)
   550  	ExpectThat(err, Error(HasSubstr("not empty")))
   551  }
   552  
   553  func (t *MemFSTest) Rmdir_Empty() {
   554  	var err error
   555  	var entries []os.FileInfo
   556  
   557  	// Create two levels of directories.
   558  	err = os.MkdirAll(path.Join(t.Dir, "foo/bar"), 0754)
   559  	AssertEq(nil, err)
   560  
   561  	// Remove the leaf.
   562  	rmTime := time.Now()
   563  	err = os.Remove(path.Join(t.Dir, "foo/bar"))
   564  	AssertEq(nil, err)
   565  
   566  	// There should be nothing left in the parent.
   567  	entries, err = fusetesting.ReadDirPicky(path.Join(t.Dir, "foo"))
   568  
   569  	AssertEq(nil, err)
   570  	ExpectThat(entries, ElementsAre())
   571  
   572  	// Check the parent's mtime.
   573  	fi, err := os.Stat(path.Join(t.Dir, "foo"))
   574  	AssertEq(nil, err)
   575  	ExpectThat(fi, fusetesting.MtimeIsWithin(rmTime, timeSlop))
   576  
   577  	// Remove the parent.
   578  	err = os.Remove(path.Join(t.Dir, "foo"))
   579  	AssertEq(nil, err)
   580  
   581  	// Now the root directory should be empty, too.
   582  	entries, err = fusetesting.ReadDirPicky(t.Dir)
   583  
   584  	AssertEq(nil, err)
   585  	ExpectThat(entries, ElementsAre())
   586  }
   587  
   588  func (t *MemFSTest) Rmdir_NonExistent() {
   589  	err := os.Remove(path.Join(t.Dir, "blah"))
   590  
   591  	AssertNe(nil, err)
   592  	ExpectThat(err, Error(HasSubstr("no such file or directory")))
   593  }
   594  
   595  func (t *MemFSTest) Rmdir_OpenedForReading() {
   596  	var err error
   597  
   598  	// Create a directory.
   599  	createTime := time.Now()
   600  	err = os.Mkdir(path.Join(t.Dir, "dir"), 0700)
   601  	AssertEq(nil, err)
   602  
   603  	// Open the directory for reading.
   604  	f, err := os.Open(path.Join(t.Dir, "dir"))
   605  	defer func() {
   606  		if f != nil {
   607  			ExpectEq(nil, f.Close())
   608  		}
   609  	}()
   610  
   611  	AssertEq(nil, err)
   612  
   613  	// Remove the directory.
   614  	err = os.Remove(path.Join(t.Dir, "dir"))
   615  	AssertEq(nil, err)
   616  
   617  	// Create a new directory, with the same name even, and add some contents
   618  	// within it.
   619  	err = os.MkdirAll(path.Join(t.Dir, "dir/foo"), 0700)
   620  	AssertEq(nil, err)
   621  
   622  	err = os.MkdirAll(path.Join(t.Dir, "dir/bar"), 0700)
   623  	AssertEq(nil, err)
   624  
   625  	err = os.MkdirAll(path.Join(t.Dir, "dir/baz"), 0700)
   626  	AssertEq(nil, err)
   627  
   628  	// We should still be able to stat the open file handle. It should show up as
   629  	// unlinked.
   630  	fi, err := f.Stat()
   631  
   632  	ExpectEq("dir", fi.Name())
   633  	ExpectThat(fi, fusetesting.MtimeIsWithin(createTime, timeSlop))
   634  	ExpectEq(0, fi.Sys().(*syscall.Stat_t).Nlink)
   635  
   636  	// Attempt to read from the directory. This shouldn't see any junk from the
   637  	// new directory. It should either succeed with an empty result or should
   638  	// return ENOENT.
   639  	names, err := f.Readdirnames(0)
   640  
   641  	if err != nil {
   642  		ExpectThat(err, Error(HasSubstr("no such file")))
   643  	} else {
   644  		ExpectThat(names, ElementsAre())
   645  	}
   646  }
   647  
   648  func (t *MemFSTest) CaseSensitive() {
   649  	var err error
   650  
   651  	// Create a file.
   652  	err = ioutil.WriteFile(path.Join(t.Dir, "file"), []byte{}, 0400)
   653  	AssertEq(nil, err)
   654  
   655  	// Create a directory.
   656  	err = os.Mkdir(path.Join(t.Dir, "dir"), 0400)
   657  	AssertEq(nil, err)
   658  
   659  	// Attempt to stat with the wrong case.
   660  	names := []string{
   661  		"FILE",
   662  		"File",
   663  		"filE",
   664  		"DIR",
   665  		"Dir",
   666  		"dIr",
   667  	}
   668  
   669  	for _, name := range names {
   670  		_, err = os.Stat(path.Join(t.Dir, name))
   671  		AssertNe(nil, err, "Name: %s", name)
   672  		AssertThat(err, Error(HasSubstr("no such file or directory")))
   673  	}
   674  }
   675  
   676  func (t *MemFSTest) WriteOverlapsEndOfFile() {
   677  	var err error
   678  	var n int
   679  
   680  	// Create a file.
   681  	f, err := os.Create(path.Join(t.Dir, "foo"))
   682  	t.ToClose = append(t.ToClose, f)
   683  	AssertEq(nil, err)
   684  
   685  	// Make it 4 bytes long.
   686  	err = f.Truncate(4)
   687  	AssertEq(nil, err)
   688  
   689  	// Write the range [2, 6).
   690  	n, err = f.WriteAt([]byte("taco"), 2)
   691  	AssertEq(nil, err)
   692  	AssertEq(4, n)
   693  
   694  	// Read the full contents of the file.
   695  	contents, err := ioutil.ReadAll(f)
   696  	AssertEq(nil, err)
   697  	ExpectEq("\x00\x00taco", string(contents))
   698  }
   699  
   700  func (t *MemFSTest) WriteStartsAtEndOfFile() {
   701  	var err error
   702  	var n int
   703  
   704  	// Create a file.
   705  	f, err := os.Create(path.Join(t.Dir, "foo"))
   706  	t.ToClose = append(t.ToClose, f)
   707  	AssertEq(nil, err)
   708  
   709  	// Make it 2 bytes long.
   710  	err = f.Truncate(2)
   711  	AssertEq(nil, err)
   712  
   713  	// Write the range [2, 6).
   714  	n, err = f.WriteAt([]byte("taco"), 2)
   715  	AssertEq(nil, err)
   716  	AssertEq(4, n)
   717  
   718  	// Read the full contents of the file.
   719  	contents, err := ioutil.ReadAll(f)
   720  	AssertEq(nil, err)
   721  	ExpectEq("\x00\x00taco", string(contents))
   722  }
   723  
   724  func (t *MemFSTest) WriteStartsPastEndOfFile() {
   725  	var err error
   726  	var n int
   727  
   728  	// Create a file.
   729  	f, err := os.Create(path.Join(t.Dir, "foo"))
   730  	t.ToClose = append(t.ToClose, f)
   731  	AssertEq(nil, err)
   732  
   733  	// Write the range [2, 6).
   734  	n, err = f.WriteAt([]byte("taco"), 2)
   735  	AssertEq(nil, err)
   736  	AssertEq(4, n)
   737  
   738  	// Read the full contents of the file.
   739  	contents, err := ioutil.ReadAll(f)
   740  	AssertEq(nil, err)
   741  	ExpectEq("\x00\x00taco", string(contents))
   742  }
   743  
   744  func (t *MemFSTest) WriteAtDoesntChangeOffset_NotAppendMode() {
   745  	var err error
   746  	var n int
   747  
   748  	// Create a file.
   749  	f, err := os.Create(path.Join(t.Dir, "foo"))
   750  	t.ToClose = append(t.ToClose, f)
   751  	AssertEq(nil, err)
   752  
   753  	// Make it 16 bytes long.
   754  	err = f.Truncate(16)
   755  	AssertEq(nil, err)
   756  
   757  	// Seek to offset 4.
   758  	_, err = f.Seek(4, 0)
   759  	AssertEq(nil, err)
   760  
   761  	// Write the range [10, 14).
   762  	n, err = f.WriteAt([]byte("taco"), 2)
   763  	AssertEq(nil, err)
   764  	AssertEq(4, n)
   765  
   766  	// We should still be at offset 4.
   767  	offset, err := getFileOffset(f)
   768  	AssertEq(nil, err)
   769  	ExpectEq(4, offset)
   770  }
   771  
   772  func (t *MemFSTest) WriteAtDoesntChangeOffset_AppendMode() {
   773  	var err error
   774  	var n int
   775  
   776  	// Create a file in append mode.
   777  	f, err := os.OpenFile(
   778  		path.Join(t.Dir, "foo"),
   779  		os.O_RDWR|os.O_CREATE,
   780  		0600)
   781  
   782  	t.ToClose = append(t.ToClose, f)
   783  	AssertEq(nil, err)
   784  
   785  	// Make it 16 bytes long.
   786  	err = f.Truncate(16)
   787  	AssertEq(nil, err)
   788  
   789  	// Seek to offset 4.
   790  	_, err = f.Seek(4, 0)
   791  	AssertEq(nil, err)
   792  
   793  	// Write the range [10, 14).
   794  	n, err = f.WriteAt([]byte("taco"), 2)
   795  	AssertEq(nil, err)
   796  	AssertEq(4, n)
   797  
   798  	// We should still be at offset 4.
   799  	offset, err := getFileOffset(f)
   800  	AssertEq(nil, err)
   801  	ExpectEq(4, offset)
   802  }
   803  
   804  func (t *MemFSTest) LargeFile() {
   805  	var err error
   806  
   807  	// Create a file.
   808  	f, err := os.Create(path.Join(t.Dir, "foo"))
   809  	t.ToClose = append(t.ToClose, f)
   810  	AssertEq(nil, err)
   811  
   812  	// Copy in large contents.
   813  	const size = 1 << 24
   814  	contents := bytes.Repeat([]byte{0x20}, size)
   815  
   816  	_, err = io.Copy(f, bytes.NewReader(contents))
   817  	AssertEq(nil, err)
   818  
   819  	// Read the full contents of the file.
   820  	contents, err = ioutil.ReadFile(f.Name())
   821  	AssertEq(nil, err)
   822  	ExpectEq(size, len(contents))
   823  }
   824  
   825  func (t *MemFSTest) AppendMode() {
   826  	var err error
   827  	var n int
   828  	var off int64
   829  	buf := make([]byte, 1024)
   830  
   831  	// Create a file with some contents.
   832  	fileName := path.Join(t.Dir, "foo")
   833  	err = ioutil.WriteFile(fileName, []byte("Jello, "), 0600)
   834  	AssertEq(nil, err)
   835  
   836  	// Open the file in append mode.
   837  	f, err := os.OpenFile(fileName, os.O_RDWR|os.O_APPEND, 0600)
   838  	t.ToClose = append(t.ToClose, f)
   839  	AssertEq(nil, err)
   840  
   841  	// Seek to somewhere silly and then write.
   842  	off, err = f.Seek(2, 0)
   843  	AssertEq(nil, err)
   844  	AssertEq(2, off)
   845  
   846  	n, err = f.Write([]byte("world!"))
   847  	AssertEq(nil, err)
   848  	AssertEq(6, n)
   849  
   850  	// The offset should have been updated to point at the end of the file.
   851  	off, err = getFileOffset(f)
   852  	AssertEq(nil, err)
   853  	ExpectEq(13, off)
   854  
   855  	off, err = getFileOffset(f)
   856  	AssertEq(nil, err)
   857  	ExpectEq(13, off)
   858  
   859  	// Read back the contents of the file, which should be correct even though we
   860  	// seeked to a silly place before writing the world part.
   861  	//
   862  	// Linux's support for pwrite is buggy; the pwrite(2) man page says this:
   863  	//
   864  	//     POSIX requires that opening a file with the O_APPEND flag should have
   865  	//     no affect on the location at which pwrite() writes data.  However, on
   866  	//     Linux,  if  a  file  is opened with O_APPEND, pwrite() appends data to
   867  	//     the end of the file, regardless of the value of offset.
   868  	//
   869  	// So we allow either the POSIX result or the Linux result.
   870  	n, err = f.ReadAt(buf, 0)
   871  	AssertEq(io.EOF, err)
   872  	ExpectThat(string(buf[:n]), AnyOf("Jello, world!", "Jello, world!H"))
   873  }
   874  
   875  func (t *MemFSTest) ReadsPastEndOfFile() {
   876  	var err error
   877  	var n int
   878  	buf := make([]byte, 1024)
   879  
   880  	// Create a file.
   881  	f, err := os.Create(path.Join(t.Dir, "foo"))
   882  	t.ToClose = append(t.ToClose, f)
   883  	AssertEq(nil, err)
   884  
   885  	// Give it some contents.
   886  	n, err = f.Write([]byte("taco"))
   887  	AssertEq(nil, err)
   888  	AssertEq(4, n)
   889  
   890  	// Read a range overlapping EOF.
   891  	n, err = f.ReadAt(buf[:4], 2)
   892  	AssertEq(io.EOF, err)
   893  	ExpectEq(2, n)
   894  	ExpectEq("co", string(buf[:n]))
   895  
   896  	// Read a range starting at EOF.
   897  	n, err = f.ReadAt(buf[:4], 4)
   898  	AssertEq(io.EOF, err)
   899  	ExpectEq(0, n)
   900  	ExpectEq("", string(buf[:n]))
   901  
   902  	// Read a range starting past EOF.
   903  	n, err = f.ReadAt(buf[:4], 100)
   904  	AssertEq(io.EOF, err)
   905  	ExpectEq(0, n)
   906  	ExpectEq("", string(buf[:n]))
   907  }
   908  
   909  func (t *MemFSTest) Truncate_Smaller() {
   910  	var err error
   911  	fileName := path.Join(t.Dir, "foo")
   912  
   913  	// Create a file.
   914  	err = ioutil.WriteFile(fileName, []byte("taco"), 0600)
   915  	AssertEq(nil, err)
   916  
   917  	// Open it for modification.
   918  	f, err := os.OpenFile(fileName, os.O_RDWR, 0)
   919  	t.ToClose = append(t.ToClose, f)
   920  	AssertEq(nil, err)
   921  
   922  	// Truncate it.
   923  	err = f.Truncate(2)
   924  	AssertEq(nil, err)
   925  
   926  	// Stat it.
   927  	fi, err := f.Stat()
   928  	AssertEq(nil, err)
   929  	ExpectEq(2, fi.Size())
   930  
   931  	// Read the contents.
   932  	contents, err := ioutil.ReadFile(fileName)
   933  	AssertEq(nil, err)
   934  	ExpectEq("ta", string(contents))
   935  }
   936  
   937  func (t *MemFSTest) Truncate_SameSize() {
   938  	var err error
   939  	fileName := path.Join(t.Dir, "foo")
   940  
   941  	// Create a file.
   942  	err = ioutil.WriteFile(fileName, []byte("taco"), 0600)
   943  	AssertEq(nil, err)
   944  
   945  	// Open it for modification.
   946  	f, err := os.OpenFile(fileName, os.O_RDWR, 0)
   947  	t.ToClose = append(t.ToClose, f)
   948  	AssertEq(nil, err)
   949  
   950  	// Truncate it.
   951  	err = f.Truncate(4)
   952  	AssertEq(nil, err)
   953  
   954  	// Stat it.
   955  	fi, err := f.Stat()
   956  	AssertEq(nil, err)
   957  	ExpectEq(4, fi.Size())
   958  
   959  	// Read the contents.
   960  	contents, err := ioutil.ReadFile(fileName)
   961  	AssertEq(nil, err)
   962  	ExpectEq("taco", string(contents))
   963  }
   964  
   965  func (t *MemFSTest) Truncate_Larger() {
   966  	var err error
   967  	fileName := path.Join(t.Dir, "foo")
   968  
   969  	// Create a file.
   970  	err = ioutil.WriteFile(fileName, []byte("taco"), 0600)
   971  	AssertEq(nil, err)
   972  
   973  	// Open it for modification.
   974  	f, err := os.OpenFile(fileName, os.O_RDWR, 0)
   975  	t.ToClose = append(t.ToClose, f)
   976  	AssertEq(nil, err)
   977  
   978  	// Truncate it.
   979  	err = f.Truncate(6)
   980  	AssertEq(nil, err)
   981  
   982  	// Stat it.
   983  	fi, err := f.Stat()
   984  	AssertEq(nil, err)
   985  	ExpectEq(6, fi.Size())
   986  
   987  	// Read the contents.
   988  	contents, err := ioutil.ReadFile(fileName)
   989  	AssertEq(nil, err)
   990  	ExpectEq("taco\x00\x00", string(contents))
   991  }
   992  
   993  func (t *MemFSTest) Chmod() {
   994  	var err error
   995  	fileName := path.Join(t.Dir, "foo")
   996  
   997  	// Create a file.
   998  	err = ioutil.WriteFile(fileName, []byte(""), 0600)
   999  	AssertEq(nil, err)
  1000  
  1001  	// Chmod it.
  1002  	err = os.Chmod(fileName, 0754)
  1003  	AssertEq(nil, err)
  1004  
  1005  	// Stat it.
  1006  	fi, err := os.Stat(fileName)
  1007  	AssertEq(nil, err)
  1008  	ExpectEq(0754, fi.Mode())
  1009  }
  1010  
  1011  func (t *MemFSTest) Chtimes() {
  1012  	var err error
  1013  	fileName := path.Join(t.Dir, "foo")
  1014  
  1015  	// Create a file.
  1016  	err = ioutil.WriteFile(fileName, []byte(""), 0600)
  1017  	AssertEq(nil, err)
  1018  
  1019  	// Chtimes it.
  1020  	expectedMtime := time.Now().Add(123 * time.Second).Round(time.Second)
  1021  	err = os.Chtimes(fileName, time.Now(), expectedMtime)
  1022  	AssertEq(nil, err)
  1023  
  1024  	// Stat it.
  1025  	fi, err := os.Stat(fileName)
  1026  	AssertEq(nil, err)
  1027  	ExpectThat(fi, fusetesting.MtimeIsWithin(expectedMtime, timeSlop))
  1028  }
  1029  
  1030  func (t *MemFSTest) ReadDirWhileModifying() {
  1031  	dirName := path.Join(t.Dir, "dir")
  1032  	createFile := func(name string) {
  1033  		AssertEq(nil, ioutil.WriteFile(path.Join(dirName, name), []byte{}, 0400))
  1034  	}
  1035  
  1036  	// Create a directory.
  1037  	err := os.Mkdir(dirName, 0700)
  1038  	AssertEq(nil, err)
  1039  
  1040  	// Open the directory.
  1041  	d, err := os.Open(dirName)
  1042  	t.ToClose = append(t.ToClose, d)
  1043  	AssertEq(nil, err)
  1044  
  1045  	// Add four files.
  1046  	createFile("foo")
  1047  	createFile("bar")
  1048  	createFile("baz")
  1049  	createFile("qux")
  1050  
  1051  	// Read one entry from the directory.
  1052  	names, err := d.Readdirnames(1)
  1053  	AssertEq(nil, err)
  1054  	AssertThat(names, ElementsAre("foo"))
  1055  
  1056  	// Make two holes in the directory.
  1057  	AssertEq(nil, os.Remove(path.Join(dirName, "foo")))
  1058  	AssertEq(nil, os.Remove(path.Join(dirName, "baz")))
  1059  
  1060  	// Add a bunch of files to the directory.
  1061  	createFile("blah_0")
  1062  	createFile("blah_1")
  1063  	createFile("blah_2")
  1064  	createFile("blah_3")
  1065  	createFile("blah_4")
  1066  
  1067  	// Continue reading from the directory, noting the names we see.
  1068  	namesSeen := make(map[string]bool)
  1069  	for {
  1070  		names, err = d.Readdirnames(1)
  1071  		for _, n := range names {
  1072  			namesSeen[n] = true
  1073  		}
  1074  
  1075  		if err == io.EOF {
  1076  			break
  1077  		}
  1078  
  1079  		AssertEq(nil, err)
  1080  	}
  1081  
  1082  	// Posix requires that we should have seen bar and qux, which we didn't
  1083  	// delete.
  1084  	ExpectTrue(namesSeen["bar"])
  1085  	ExpectTrue(namesSeen["qux"])
  1086  }
  1087  
  1088  func (t *MemFSTest) CreateSymlink() {
  1089  	var fi os.FileInfo
  1090  	var err error
  1091  
  1092  	symlinkName := path.Join(t.Dir, "foo")
  1093  	target := "taco/burrito"
  1094  
  1095  	// Create the link.
  1096  	err = os.Symlink(target, symlinkName)
  1097  	AssertEq(nil, err)
  1098  
  1099  	// Stat the link.
  1100  	fi, err = os.Lstat(symlinkName)
  1101  	AssertEq(nil, err)
  1102  
  1103  	ExpectEq("foo", fi.Name())
  1104  	ExpectEq(0444|os.ModeSymlink, fi.Mode())
  1105  
  1106  	// Read the link.
  1107  	actual, err := os.Readlink(symlinkName)
  1108  	AssertEq(nil, err)
  1109  	ExpectEq(target, actual)
  1110  
  1111  	// Read the parent directory.
  1112  	entries, err := fusetesting.ReadDirPicky(t.Dir)
  1113  	AssertEq(nil, err)
  1114  	AssertEq(1, len(entries))
  1115  
  1116  	fi = entries[0]
  1117  	ExpectEq("foo", fi.Name())
  1118  	ExpectEq(0444|os.ModeSymlink, fi.Mode())
  1119  }
  1120  
  1121  func (t *MemFSTest) CreateSymlink_AlreadyExists() {
  1122  	var err error
  1123  
  1124  	// Create a file and a directory.
  1125  	fileName := path.Join(t.Dir, "foo")
  1126  	err = ioutil.WriteFile(fileName, []byte{}, 0400)
  1127  	AssertEq(nil, err)
  1128  
  1129  	dirName := path.Join(t.Dir, "bar")
  1130  	err = os.Mkdir(dirName, 0700)
  1131  	AssertEq(nil, err)
  1132  
  1133  	// Create an existing symlink.
  1134  	symlinkName := path.Join(t.Dir, "baz")
  1135  	err = os.Symlink("blah", symlinkName)
  1136  	AssertEq(nil, err)
  1137  
  1138  	// Symlinking on top of any of them should fail.
  1139  	names := []string{
  1140  		fileName,
  1141  		dirName,
  1142  		symlinkName,
  1143  	}
  1144  
  1145  	for _, n := range names {
  1146  		err = os.Symlink("blah", n)
  1147  		ExpectThat(err, Error(HasSubstr("exists")))
  1148  	}
  1149  }
  1150  
  1151  func (t *MemFSTest) ReadLink_NonExistent() {
  1152  	_, err := os.Readlink(path.Join(t.Dir, "foo"))
  1153  	ExpectTrue(os.IsNotExist(err), "err: %v", err)
  1154  }
  1155  
  1156  func (t *MemFSTest) ReadLink_NotASymlink() {
  1157  	var err error
  1158  
  1159  	// Create a file and a directory.
  1160  	fileName := path.Join(t.Dir, "foo")
  1161  	err = ioutil.WriteFile(fileName, []byte{}, 0400)
  1162  	AssertEq(nil, err)
  1163  
  1164  	dirName := path.Join(t.Dir, "bar")
  1165  	err = os.Mkdir(dirName, 0700)
  1166  	AssertEq(nil, err)
  1167  
  1168  	// Reading either of them as a symlink should fail.
  1169  	names := []string{
  1170  		fileName,
  1171  		dirName,
  1172  	}
  1173  
  1174  	for _, n := range names {
  1175  		_, err = os.Readlink(n)
  1176  		ExpectThat(err, Error(HasSubstr("invalid argument")))
  1177  	}
  1178  }
  1179  
  1180  func (t *MemFSTest) DeleteSymlink() {
  1181  	var err error
  1182  
  1183  	symlinkName := path.Join(t.Dir, "foo")
  1184  	target := "taco/burrito"
  1185  
  1186  	// Create the link.
  1187  	err = os.Symlink(target, symlinkName)
  1188  	AssertEq(nil, err)
  1189  
  1190  	// Remove it.
  1191  	err = os.Remove(symlinkName)
  1192  	AssertEq(nil, err)
  1193  
  1194  	// Statting should now fail.
  1195  	_, err = os.Lstat(symlinkName)
  1196  	ExpectTrue(os.IsNotExist(err), "err: %v", err)
  1197  
  1198  	// Read the parent directory.
  1199  	entries, err := fusetesting.ReadDirPicky(t.Dir)
  1200  
  1201  	AssertEq(nil, err)
  1202  	ExpectThat(entries, ElementsAre())
  1203  }
  1204  
  1205  func (t *MemFSTest) CreateHardlink() {
  1206  	var fi os.FileInfo
  1207  	var err error
  1208  
  1209  	// Create a file.
  1210  	fileName := path.Join(t.Dir, "regular_file")
  1211  	const contents = "Hello\x00world"
  1212  
  1213  	err = ioutil.WriteFile(fileName, []byte(contents), 0444)
  1214  	AssertEq(nil, err)
  1215  
  1216  	// Clean up the file at the end.
  1217  	defer func() {
  1218  		err := os.Remove(fileName)
  1219  		AssertEq(nil, err)
  1220  	}()
  1221  
  1222  	// Create a link to the file.
  1223  	linkName := path.Join(t.Dir, "foo")
  1224  	err = os.Link(fileName, linkName)
  1225  	AssertEq(nil, err)
  1226  
  1227  	// Clean up the file at the end.
  1228  	defer func() {
  1229  		err := os.Remove(linkName)
  1230  		AssertEq(nil, err)
  1231  	}()
  1232  
  1233  	// Stat the link.
  1234  	fi, err = os.Lstat(linkName)
  1235  	AssertEq(nil, err)
  1236  
  1237  	ExpectEq("foo", fi.Name())
  1238  	ExpectEq(0444, fi.Mode())
  1239  
  1240  	// Read the parent directory.
  1241  	entries, err := fusetesting.ReadDirPicky(t.Dir)
  1242  	AssertEq(nil, err)
  1243  	AssertEq(2, len(entries))
  1244  
  1245  	fi = entries[0]
  1246  	ExpectEq("foo", fi.Name())
  1247  	ExpectEq(0444, fi.Mode())
  1248  
  1249  	fi = entries[1]
  1250  	ExpectEq("regular_file", fi.Name())
  1251  	ExpectEq(0444, fi.Mode())
  1252  }
  1253  
  1254  func (t *MemFSTest) CreateHardlink_AlreadyExists() {
  1255  	var err error
  1256  
  1257  	// Create a file and a directory.
  1258  	fileName := path.Join(t.Dir, "foo")
  1259  	err = ioutil.WriteFile(fileName, []byte{}, 0400)
  1260  	AssertEq(nil, err)
  1261  
  1262  	dirName := path.Join(t.Dir, "bar")
  1263  	err = os.Mkdir(dirName, 0700)
  1264  	AssertEq(nil, err)
  1265  
  1266  	// Create an existing symlink.
  1267  	symlinkName := path.Join(t.Dir, "baz")
  1268  	err = os.Symlink("blah", symlinkName)
  1269  	AssertEq(nil, err)
  1270  
  1271  	// Create another link to the file.
  1272  	hardlinkName := path.Join(t.Dir, "qux")
  1273  	err = os.Link(fileName, hardlinkName)
  1274  	AssertEq(nil, err)
  1275  
  1276  	// Symlinking on top of any of them should fail.
  1277  	names := []string{
  1278  		fileName,
  1279  		dirName,
  1280  		symlinkName,
  1281  		hardlinkName,
  1282  	}
  1283  
  1284  	for _, n := range names {
  1285  		err = os.Link(fileName, n)
  1286  		ExpectThat(err, Error(HasSubstr("exists")))
  1287  	}
  1288  }
  1289  
  1290  func (t *MemFSTest) DeleteHardlink() {
  1291  	var fi os.FileInfo
  1292  	var err error
  1293  
  1294  	// Create a file.
  1295  	fileName := path.Join(t.Dir, "regular_file")
  1296  	const contents = "Hello\x00world"
  1297  
  1298  	err = ioutil.WriteFile(fileName, []byte(contents), 0444)
  1299  	AssertEq(nil, err)
  1300  
  1301  	// Step #1: We will create and remove a link and verify that
  1302  	// after removal everything is as expected.
  1303  
  1304  	// Create a link to the file.
  1305  	linkName := path.Join(t.Dir, "foo")
  1306  	err = os.Link(fileName, linkName)
  1307  	AssertEq(nil, err)
  1308  
  1309  	// Remove the link.
  1310  	err = os.Remove(linkName)
  1311  	AssertEq(nil, err)
  1312  
  1313  	// Stat the link.
  1314  	fi, err = os.Lstat(linkName)
  1315  	AssertEq(nil, fi)
  1316  	ExpectThat(err, Error(HasSubstr("no such file")))
  1317  
  1318  	// Read the parent directory.
  1319  	entries, err := fusetesting.ReadDirPicky(t.Dir)
  1320  	AssertEq(nil, err)
  1321  	AssertEq(1, len(entries))
  1322  
  1323  	fi = entries[0]
  1324  	ExpectEq("regular_file", fi.Name())
  1325  	ExpectEq(0444, fi.Mode())
  1326  
  1327  	// Step #2: We will create a link and remove the original file subsequently
  1328  	// and verify that after removal everything is as expected.
  1329  
  1330  	// Create a link to the file.
  1331  	linkName = path.Join(t.Dir, "bar")
  1332  	err = os.Link(fileName, linkName)
  1333  	AssertEq(nil, err)
  1334  
  1335  	// Remove the original file.
  1336  	err = os.Remove(fileName)
  1337  	AssertEq(nil, err)
  1338  
  1339  	// Stat the link.
  1340  	fi, err = os.Lstat(linkName)
  1341  	AssertEq(nil, err)
  1342  	ExpectEq("bar", fi.Name())
  1343  	ExpectEq(0444, fi.Mode())
  1344  
  1345  	// Stat the original file.
  1346  	fi, err = os.Lstat(fileName)
  1347  	AssertEq(nil, fi)
  1348  	ExpectThat(err, Error(HasSubstr("no such file")))
  1349  
  1350  	// Read the parent directory.
  1351  	entries, err = fusetesting.ReadDirPicky(t.Dir)
  1352  	AssertEq(nil, err)
  1353  	AssertEq(1, len(entries))
  1354  
  1355  	fi = entries[0]
  1356  	ExpectEq("bar", fi.Name())
  1357  	ExpectEq(0444, fi.Mode())
  1358  
  1359  	// Cleanup.
  1360  	err = os.Remove(linkName)
  1361  	AssertEq(nil, err)
  1362  }
  1363  
  1364  func (t *MemFSTest) ReadHardlink() {
  1365  	var err error
  1366  
  1367  	// Create a file.
  1368  	fileName := path.Join(t.Dir, "regular_file")
  1369  	const contents = "Hello\x00world"
  1370  
  1371  	err = ioutil.WriteFile(fileName, []byte(contents), 0444)
  1372  	AssertEq(nil, err)
  1373  
  1374  	// Clean up the file at the end.
  1375  	defer func() {
  1376  		err := os.Remove(fileName)
  1377  		AssertEq(nil, err)
  1378  	}()
  1379  
  1380  	// Create a link to the file.
  1381  	linkName := path.Join(t.Dir, "foo")
  1382  	err = os.Link(fileName, linkName)
  1383  	AssertEq(nil, err)
  1384  
  1385  	// Clean up the file at the end.
  1386  	defer func() {
  1387  		err := os.Remove(linkName)
  1388  		AssertEq(nil, err)
  1389  	}()
  1390  
  1391  	// Read files.
  1392  	original, err := ioutil.ReadFile(fileName)
  1393  	AssertEq(nil, err)
  1394  	linked, err := ioutil.ReadFile(linkName)
  1395  	AssertEq(nil, err)
  1396  
  1397  	// Check if the bytes are the same.
  1398  	AssertEq(true, reflect.DeepEqual(original, linked))
  1399  }
  1400  
  1401  func (t *MemFSTest) CreateInParallel_NoTruncate() {
  1402  	fusetesting.RunCreateInParallelTest_NoTruncate(t.Ctx, t.Dir)
  1403  }
  1404  
  1405  func (t *MemFSTest) CreateInParallel_Truncate() {
  1406  	fusetesting.RunCreateInParallelTest_Truncate(t.Ctx, t.Dir)
  1407  }
  1408  
  1409  func (t *MemFSTest) CreateInParallel_Exclusive() {
  1410  	fusetesting.RunCreateInParallelTest_Exclusive(t.Ctx, t.Dir)
  1411  }
  1412  
  1413  func (t *MemFSTest) MkdirInParallel() {
  1414  	fusetesting.RunMkdirInParallelTest(t.Ctx, t.Dir)
  1415  }
  1416  
  1417  func (t *MemFSTest) SymlinkInParallel() {
  1418  	fusetesting.RunSymlinkInParallelTest(t.Ctx, t.Dir)
  1419  }
  1420  
  1421  func (t *MemFSTest) HardlinkInParallel() {
  1422  	fusetesting.RunHardlinkInParallelTest(t.Ctx, t.Dir)
  1423  }
  1424  
  1425  func (t *MemFSTest) RenameWithinDir_File() {
  1426  	var err error
  1427  
  1428  	// Create a parent directory.
  1429  	parentPath := path.Join(t.Dir, "parent")
  1430  
  1431  	err = os.Mkdir(parentPath, 0700)
  1432  	AssertEq(nil, err)
  1433  
  1434  	// And a file within it.
  1435  	oldPath := path.Join(parentPath, "foo")
  1436  
  1437  	err = ioutil.WriteFile(oldPath, []byte("taco"), 0400)
  1438  	AssertEq(nil, err)
  1439  
  1440  	// Rename it.
  1441  	newPath := path.Join(parentPath, "bar")
  1442  
  1443  	err = os.Rename(oldPath, newPath)
  1444  	AssertEq(nil, err)
  1445  
  1446  	// The old name shouldn't work.
  1447  	_, err = os.Stat(oldPath)
  1448  	ExpectTrue(os.IsNotExist(err), "err: %v", err)
  1449  
  1450  	_, err = ioutil.ReadFile(oldPath)
  1451  	ExpectTrue(os.IsNotExist(err), "err: %v", err)
  1452  
  1453  	// The new name should.
  1454  	fi, err := os.Stat(newPath)
  1455  	AssertEq(nil, err)
  1456  	ExpectEq(len("taco"), fi.Size())
  1457  	ExpectEq(os.FileMode(0400), fi.Mode())
  1458  
  1459  	contents, err := ioutil.ReadFile(newPath)
  1460  	AssertEq(nil, err)
  1461  	ExpectEq("taco", string(contents))
  1462  
  1463  	// There should only be the new entry in the directory.
  1464  	entries, err := fusetesting.ReadDirPicky(parentPath)
  1465  	AssertEq(nil, err)
  1466  	AssertEq(1, len(entries))
  1467  	fi = entries[0]
  1468  
  1469  	ExpectEq(path.Base(newPath), fi.Name())
  1470  	ExpectEq(os.FileMode(0400), fi.Mode())
  1471  }
  1472  
  1473  func (t *MemFSTest) RenameWithinDir_Directory() {
  1474  	var err error
  1475  
  1476  	// Create a parent directory.
  1477  	parentPath := path.Join(t.Dir, "parent")
  1478  
  1479  	err = os.Mkdir(parentPath, 0700)
  1480  	AssertEq(nil, err)
  1481  
  1482  	// And a non-empty directory within it.
  1483  	oldPath := path.Join(parentPath, "foo")
  1484  
  1485  	err = os.MkdirAll(path.Join(oldPath, "child"), 0700)
  1486  	AssertEq(nil, err)
  1487  
  1488  	// Rename it.
  1489  	newPath := path.Join(parentPath, "bar")
  1490  
  1491  	err = os.Rename(oldPath, newPath)
  1492  	AssertEq(nil, err)
  1493  
  1494  	// The old name shouldn't work.
  1495  	_, err = os.Stat(oldPath)
  1496  	ExpectTrue(os.IsNotExist(err), "err: %v", err)
  1497  
  1498  	// The new name should.
  1499  	fi, err := os.Stat(newPath)
  1500  	AssertEq(nil, err)
  1501  	ExpectEq(os.FileMode(0700)|os.ModeDir, fi.Mode())
  1502  
  1503  	// There should only be the new entry in the parent.
  1504  	entries, err := fusetesting.ReadDirPicky(parentPath)
  1505  	AssertEq(nil, err)
  1506  	AssertEq(1, len(entries))
  1507  	fi = entries[0]
  1508  
  1509  	ExpectEq(path.Base(newPath), fi.Name())
  1510  	ExpectEq(os.FileMode(0700)|os.ModeDir, fi.Mode())
  1511  
  1512  	// And the child should still be present.
  1513  	entries, err = fusetesting.ReadDirPicky(newPath)
  1514  	AssertEq(nil, err)
  1515  	AssertEq(1, len(entries))
  1516  	fi = entries[0]
  1517  
  1518  	ExpectEq("child", fi.Name())
  1519  	ExpectEq(os.FileMode(0700)|os.ModeDir, fi.Mode())
  1520  }
  1521  
  1522  func (t *MemFSTest) RenameWithinDir_SameName() {
  1523  	var err error
  1524  
  1525  	// Create a parent directory.
  1526  	parentPath := path.Join(t.Dir, "parent")
  1527  
  1528  	err = os.Mkdir(parentPath, 0700)
  1529  	AssertEq(nil, err)
  1530  
  1531  	// And a file within it.
  1532  	filePath := path.Join(parentPath, "foo")
  1533  
  1534  	err = ioutil.WriteFile(filePath, []byte("taco"), 0400)
  1535  	AssertEq(nil, err)
  1536  
  1537  	// Attempt to rename it.
  1538  	err = os.Rename(filePath, filePath)
  1539  	AssertEq(nil, err)
  1540  
  1541  	// The file should still exist.
  1542  	contents, err := ioutil.ReadFile(filePath)
  1543  	AssertEq(nil, err)
  1544  	ExpectEq("taco", string(contents))
  1545  
  1546  	// There should only be the one entry in the directory.
  1547  	entries, err := fusetesting.ReadDirPicky(parentPath)
  1548  	AssertEq(nil, err)
  1549  	AssertEq(1, len(entries))
  1550  	fi := entries[0]
  1551  
  1552  	ExpectEq(path.Base(filePath), fi.Name())
  1553  	ExpectEq(os.FileMode(0400), fi.Mode())
  1554  }
  1555  
  1556  func (t *MemFSTest) RenameAcrossDirs_File() {
  1557  	var err error
  1558  
  1559  	// Create two parent directories.
  1560  	oldParentPath := path.Join(t.Dir, "old")
  1561  	newParentPath := path.Join(t.Dir, "new")
  1562  
  1563  	err = os.Mkdir(oldParentPath, 0700)
  1564  	AssertEq(nil, err)
  1565  
  1566  	err = os.Mkdir(newParentPath, 0700)
  1567  	AssertEq(nil, err)
  1568  
  1569  	// And a file within the first.
  1570  	oldPath := path.Join(oldParentPath, "foo")
  1571  
  1572  	err = ioutil.WriteFile(oldPath, []byte("taco"), 0400)
  1573  	AssertEq(nil, err)
  1574  
  1575  	// Rename it.
  1576  	newPath := path.Join(newParentPath, "bar")
  1577  
  1578  	err = os.Rename(oldPath, newPath)
  1579  	AssertEq(nil, err)
  1580  
  1581  	// The old name shouldn't work.
  1582  	_, err = os.Stat(oldPath)
  1583  	ExpectTrue(os.IsNotExist(err), "err: %v", err)
  1584  
  1585  	_, err = ioutil.ReadFile(oldPath)
  1586  	ExpectTrue(os.IsNotExist(err), "err: %v", err)
  1587  
  1588  	// The new name should.
  1589  	fi, err := os.Stat(newPath)
  1590  	AssertEq(nil, err)
  1591  	ExpectEq(len("taco"), fi.Size())
  1592  	ExpectEq(os.FileMode(0400), fi.Mode())
  1593  
  1594  	contents, err := ioutil.ReadFile(newPath)
  1595  	AssertEq(nil, err)
  1596  	ExpectEq("taco", string(contents))
  1597  
  1598  	// Check the old parent.
  1599  	entries, err := fusetesting.ReadDirPicky(oldParentPath)
  1600  	AssertEq(nil, err)
  1601  	AssertEq(0, len(entries))
  1602  
  1603  	// And the new one.
  1604  	entries, err = fusetesting.ReadDirPicky(newParentPath)
  1605  	AssertEq(nil, err)
  1606  	AssertEq(1, len(entries))
  1607  	fi = entries[0]
  1608  
  1609  	ExpectEq(path.Base(newPath), fi.Name())
  1610  	ExpectEq(os.FileMode(0400), fi.Mode())
  1611  }
  1612  
  1613  func (t *MemFSTest) RenameAcrossDirs_Directory() {
  1614  	var err error
  1615  
  1616  	// Create two parent directories.
  1617  	oldParentPath := path.Join(t.Dir, "old")
  1618  	newParentPath := path.Join(t.Dir, "new")
  1619  
  1620  	err = os.Mkdir(oldParentPath, 0700)
  1621  	AssertEq(nil, err)
  1622  
  1623  	err = os.Mkdir(newParentPath, 0700)
  1624  	AssertEq(nil, err)
  1625  
  1626  	// And a non-empty directory within the first.
  1627  	oldPath := path.Join(oldParentPath, "foo")
  1628  
  1629  	err = os.MkdirAll(path.Join(oldPath, "child"), 0700)
  1630  	AssertEq(nil, err)
  1631  
  1632  	// Rename it.
  1633  	newPath := path.Join(newParentPath, "bar")
  1634  
  1635  	err = os.Rename(oldPath, newPath)
  1636  	AssertEq(nil, err)
  1637  
  1638  	// The old name shouldn't work.
  1639  	_, err = os.Stat(oldPath)
  1640  	ExpectTrue(os.IsNotExist(err), "err: %v", err)
  1641  
  1642  	// The new name should.
  1643  	fi, err := os.Stat(newPath)
  1644  	AssertEq(nil, err)
  1645  	ExpectEq(os.FileMode(0700)|os.ModeDir, fi.Mode())
  1646  
  1647  	// And the child should still be present.
  1648  	entries, err := fusetesting.ReadDirPicky(newPath)
  1649  	AssertEq(nil, err)
  1650  	AssertEq(1, len(entries))
  1651  	fi = entries[0]
  1652  
  1653  	ExpectEq("child", fi.Name())
  1654  	ExpectEq(os.FileMode(0700)|os.ModeDir, fi.Mode())
  1655  
  1656  	// Check the old parent.
  1657  	entries, err = fusetesting.ReadDirPicky(oldParentPath)
  1658  	AssertEq(nil, err)
  1659  	AssertEq(0, len(entries))
  1660  
  1661  	// And the new one.
  1662  	entries, err = fusetesting.ReadDirPicky(newParentPath)
  1663  	AssertEq(nil, err)
  1664  	AssertEq(1, len(entries))
  1665  	fi = entries[0]
  1666  
  1667  	ExpectEq(path.Base(newPath), fi.Name())
  1668  	ExpectEq(os.FileMode(0700)|os.ModeDir, fi.Mode())
  1669  }
  1670  
  1671  func (t *MemFSTest) RenameOutOfFileSystem() {
  1672  	var err error
  1673  
  1674  	// Create a file.
  1675  	oldPath := path.Join(t.Dir, "foo")
  1676  
  1677  	err = ioutil.WriteFile(oldPath, []byte("taco"), 0400)
  1678  	AssertEq(nil, err)
  1679  
  1680  	// Attempt to move it out of the file system.
  1681  	tempDir, err := ioutil.TempDir("", "memfs_test")
  1682  	AssertEq(nil, err)
  1683  	defer os.RemoveAll(tempDir)
  1684  
  1685  	err = os.Rename(oldPath, path.Join(tempDir, "bar"))
  1686  	ExpectThat(err, Error(HasSubstr("cross-device")))
  1687  }
  1688  
  1689  func (t *MemFSTest) RenameIntoFileSystem() {
  1690  	var err error
  1691  
  1692  	// Create a file outside of our file system.
  1693  	f, err := ioutil.TempFile("", "memfs_test")
  1694  	AssertEq(nil, err)
  1695  	defer f.Close()
  1696  
  1697  	oldPath := f.Name()
  1698  	defer os.Remove(oldPath)
  1699  
  1700  	// Attempt to move it into the file system.
  1701  	err = os.Rename(oldPath, path.Join(t.Dir, "bar"))
  1702  	ExpectThat(err, Error(HasSubstr("cross-device")))
  1703  }
  1704  
  1705  func (t *MemFSTest) RenameOverExistingFile() {
  1706  	var err error
  1707  
  1708  	// Create two files.
  1709  	oldPath := path.Join(t.Dir, "foo")
  1710  	err = ioutil.WriteFile(oldPath, []byte("taco"), 0400)
  1711  	AssertEq(nil, err)
  1712  
  1713  	newPath := path.Join(t.Dir, "bar")
  1714  	err = ioutil.WriteFile(newPath, []byte("burrito"), 0600)
  1715  	AssertEq(nil, err)
  1716  
  1717  	// Rename one over the other.
  1718  	err = os.Rename(oldPath, newPath)
  1719  	AssertEq(nil, err)
  1720  
  1721  	// Check the file contents.
  1722  	contents, err := ioutil.ReadFile(newPath)
  1723  	AssertEq(nil, err)
  1724  	ExpectEq("taco", string(contents))
  1725  
  1726  	// And the parent listing.
  1727  	entries, err := fusetesting.ReadDirPicky(t.Dir)
  1728  	AssertEq(nil, err)
  1729  	AssertEq(1, len(entries))
  1730  	fi := entries[0]
  1731  
  1732  	ExpectEq(path.Base(newPath), fi.Name())
  1733  	ExpectEq(os.FileMode(0400), fi.Mode())
  1734  	ExpectEq(len("taco"), fi.Size())
  1735  }
  1736  
  1737  func (t *MemFSTest) RenameOverExistingDirectory() {
  1738  	var err error
  1739  
  1740  	// Create two directories, the first non-empty.
  1741  	oldPath := path.Join(t.Dir, "foo")
  1742  	err = os.MkdirAll(path.Join(oldPath, "child"), 0700)
  1743  	AssertEq(nil, err)
  1744  
  1745  	newPath := path.Join(t.Dir, "bar")
  1746  	err = os.Mkdir(newPath, 0600)
  1747  	AssertEq(nil, err)
  1748  
  1749  	// Renaming over the non-empty directory shouldn't work.
  1750  	err = os.Rename(newPath, oldPath)
  1751  	ExpectThat(err, Error(MatchesRegexp("not empty|file exists")))
  1752  
  1753  	// As of Go 1.8 this shouldn't work the other way around either (see
  1754  	// https://github.com/golang/go/commit/321c312).
  1755  	if atLeastGo18 {
  1756  		err = os.Rename(oldPath, newPath)
  1757  		ExpectThat(err, Error(HasSubstr("file exists")))
  1758  
  1759  		// Both should still be present in the parent listing.
  1760  		entries, err := fusetesting.ReadDirPicky(t.Dir)
  1761  		AssertEq(nil, err)
  1762  		ExpectEq(2, len(entries))
  1763  	}
  1764  }
  1765  
  1766  func (t *MemFSTest) RenameOverExisting_WrongType() {
  1767  	var err error
  1768  
  1769  	// Create a file and a directory.
  1770  	filePath := path.Join(t.Dir, "foo")
  1771  	err = ioutil.WriteFile(filePath, []byte("taco"), 0400)
  1772  	AssertEq(nil, err)
  1773  
  1774  	dirPath := path.Join(t.Dir, "bar")
  1775  	err = os.Mkdir(dirPath, 0700)
  1776  	AssertEq(nil, err)
  1777  
  1778  	// Renaming either over the other shouldn't work.
  1779  	err = os.Rename(filePath, dirPath)
  1780  	ExpectThat(err, Error(MatchesRegexp("is a directory|file exists")))
  1781  
  1782  	err = os.Rename(dirPath, filePath)
  1783  	ExpectThat(err, Error(HasSubstr("not a directory")))
  1784  }
  1785  
  1786  func (t *MemFSTest) RenameNonExistentFile() {
  1787  	var err error
  1788  
  1789  	err = os.Rename(path.Join(t.Dir, "foo"), path.Join(t.Dir, "bar"))
  1790  	ExpectThat(err, Error(HasSubstr("no such file")))
  1791  }
  1792  
  1793  func (t *MemFSTest) NoXattrs() {
  1794  	var err error
  1795  	var sz int
  1796  	var smallBuf [1]byte
  1797  
  1798  	// Create a file.
  1799  	filePath := path.Join(t.Dir, "foo")
  1800  	err = ioutil.WriteFile(filePath, []byte("taco"), 0400)
  1801  	AssertEq(nil, err)
  1802  
  1803  	// List xattr names.
  1804  	sz, err = unix.Listxattr(filePath, nil)
  1805  	AssertEq(nil, err)
  1806  	AssertEq(0, sz)
  1807  
  1808  	// Attempt to read a non-existent xattr.
  1809  	_, err = unix.Getxattr(filePath, "foo", nil)
  1810  	ExpectEq(fuse.ENOATTR, err)
  1811  
  1812  	// Attempt to read a non-existent xattr with a buf.
  1813  	_, err = unix.Getxattr(filePath, "foo", smallBuf[:])
  1814  	ExpectEq(fuse.ENOATTR, err)
  1815  
  1816  	// List xattr names with a buf.
  1817  	sz, err = unix.Listxattr(filePath, smallBuf[:])
  1818  	AssertEq(nil, err)
  1819  	ExpectEq(0, sz)
  1820  }
  1821  
  1822  func (t *MemFSTest) SetXAttr() {
  1823  	var err error
  1824  	var sz int
  1825  	var buf [1024]byte
  1826  
  1827  	// Create a file.
  1828  	filePath := path.Join(t.Dir, "foo")
  1829  	err = ioutil.WriteFile(filePath, []byte("taco"), 0600)
  1830  	AssertEq(nil, err)
  1831  
  1832  	err = unix.Setxattr(filePath, "foo", []byte("bar"), unix.XATTR_REPLACE)
  1833  	AssertEq(fuse.ENOATTR, err)
  1834  
  1835  	err = unix.Setxattr(filePath, "foo", []byte("bar"), unix.XATTR_CREATE)
  1836  	AssertEq(nil, err)
  1837  
  1838  	// List xattr with a buf that is too small.
  1839  	_, err = unix.Listxattr(filePath, buf[:1])
  1840  	ExpectEq(unix.ERANGE, err)
  1841  
  1842  	// List xattr to ask for name size.
  1843  	sz, err = unix.Listxattr(filePath, nil)
  1844  	AssertEq(nil, err)
  1845  	AssertEq(4, sz)
  1846  
  1847  	// List xattr names.
  1848  	sz, err = unix.Listxattr(filePath, buf[:sz])
  1849  	AssertEq(nil, err)
  1850  	AssertEq(4, sz)
  1851  	AssertEq("foo\000", string(buf[:sz]))
  1852  
  1853  	// Read xattr with a buf that is too small.
  1854  	_, err = unix.Getxattr(filePath, "foo", buf[:1])
  1855  	ExpectEq(unix.ERANGE, err)
  1856  
  1857  	// Read xattr to ask for value size.
  1858  	sz, err = unix.Getxattr(filePath, "foo", nil)
  1859  	AssertEq(nil, err)
  1860  	AssertEq(3, sz)
  1861  
  1862  	// Read xattr value.
  1863  	sz, err = unix.Getxattr(filePath, "foo", buf[:sz])
  1864  	AssertEq(nil, err)
  1865  	AssertEq(3, sz)
  1866  	AssertEq("bar", string(buf[:sz]))
  1867  }
  1868  
  1869  func (t *MemFSTest) RemoveXAttr() {
  1870  	var err error
  1871  
  1872  	// Create a file
  1873  	filePath := path.Join(t.Dir, "foo")
  1874  	err = ioutil.WriteFile(filePath, []byte("taco"), 0600)
  1875  	AssertEq(nil, err)
  1876  
  1877  	err = unix.Removexattr(filePath, "foo")
  1878  	AssertEq(fuse.ENOATTR, err)
  1879  
  1880  	err = unix.Setxattr(filePath, "foo", []byte("bar"), unix.XATTR_CREATE)
  1881  	AssertEq(nil, err)
  1882  
  1883  	err = unix.Removexattr(filePath, "foo")
  1884  	AssertEq(nil, err)
  1885  
  1886  	_, err = unix.Getxattr(filePath, "foo", nil)
  1887  	AssertEq(fuse.ENOATTR, err)
  1888  }
  1889  
  1890  ////////////////////////////////////////////////////////////////////////
  1891  // Mknod
  1892  ////////////////////////////////////////////////////////////////////////
  1893  
  1894  type MknodTest struct {
  1895  	memFSTest
  1896  }
  1897  
  1898  func init() { RegisterTestSuite(&MknodTest{}) }
  1899  
  1900  func (t *MknodTest) File() {
  1901  	// mknod(2) only works for root on OS X.
  1902  	if runtime.GOOS == "darwin" {
  1903  		return
  1904  	}
  1905  
  1906  	var err error
  1907  	p := path.Join(t.Dir, "foo")
  1908  
  1909  	// Create
  1910  	err = syscall.Mknod(p, syscall.S_IFREG|0641, 0)
  1911  	AssertEq(nil, err)
  1912  
  1913  	// Stat
  1914  	fi, err := os.Stat(p)
  1915  	AssertEq(nil, err)
  1916  
  1917  	ExpectEq(path.Base(p), fi.Name())
  1918  	ExpectEq(0, fi.Size())
  1919  	ExpectEq(os.FileMode(0641), fi.Mode())
  1920  
  1921  	// Read
  1922  	contents, err := ioutil.ReadFile(p)
  1923  	AssertEq(nil, err)
  1924  	ExpectEq("", string(contents))
  1925  }
  1926  
  1927  func (t *MknodTest) Directory() {
  1928  	// mknod(2) only works for root on OS X.
  1929  	if runtime.GOOS == "darwin" {
  1930  		return
  1931  	}
  1932  
  1933  	var err error
  1934  	p := path.Join(t.Dir, "foo")
  1935  
  1936  	// Quoth `man 2 mknod`: "Under Linux, this call cannot be used to create
  1937  	// directories."
  1938  	err = syscall.Mknod(p, syscall.S_IFDIR|0700, 0)
  1939  	ExpectEq(syscall.EPERM, err)
  1940  }
  1941  
  1942  func (t *MknodTest) AlreadyExists() {
  1943  	// mknod(2) only works for root on OS X.
  1944  	if runtime.GOOS == "darwin" {
  1945  		return
  1946  	}
  1947  
  1948  	var err error
  1949  	p := path.Join(t.Dir, "foo")
  1950  
  1951  	// Create (first)
  1952  	err = ioutil.WriteFile(p, []byte("taco"), 0600)
  1953  	AssertEq(nil, err)
  1954  
  1955  	// Create (second)
  1956  	err = syscall.Mknod(p, syscall.S_IFREG|0600, 0)
  1957  	ExpectEq(syscall.EEXIST, err)
  1958  
  1959  	// Read
  1960  	contents, err := ioutil.ReadFile(p)
  1961  	AssertEq(nil, err)
  1962  	ExpectEq("taco", string(contents))
  1963  }
  1964  
  1965  func (t *MknodTest) NonExistentParent() {
  1966  	// mknod(2) only works for root on OS X.
  1967  	if runtime.GOOS == "darwin" {
  1968  		return
  1969  	}
  1970  
  1971  	var err error
  1972  	p := path.Join(t.Dir, "foo/bar")
  1973  
  1974  	err = syscall.Mknod(p, syscall.S_IFREG|0600, 0)
  1975  	ExpectEq(syscall.ENOENT, err)
  1976  }
  1977  
  1978  func (t *MknodTest) Fallocate_Larger() {
  1979  	var err error
  1980  	fileName := path.Join(t.Dir, "foo")
  1981  
  1982  	// Create a file.
  1983  	err = ioutil.WriteFile(fileName, []byte("taco"), 0600)
  1984  	AssertEq(nil, err)
  1985  
  1986  	// Open it for modification.
  1987  	f, err := os.OpenFile(fileName, os.O_RDWR, 0)
  1988  	t.ToClose = append(t.ToClose, f)
  1989  	AssertEq(nil, err)
  1990  
  1991  	// Truncate it.
  1992  	err = fallocate.Fallocate(f, 5, 1)
  1993  	AssertEq(nil, err)
  1994  
  1995  	// Stat it.
  1996  	fi, err := f.Stat()
  1997  	AssertEq(nil, err)
  1998  	ExpectEq(6, fi.Size())
  1999  
  2000  	// Read the contents.
  2001  	contents, err := ioutil.ReadFile(fileName)
  2002  	AssertEq(nil, err)
  2003  	ExpectEq("taco\x00\x00", string(contents))
  2004  }