func testGitFS(mnt string, t *testing.T) { fi, err := os.Lstat(mnt + "/file") if err != nil { t.Fatalf("Lstat: %v", err) } else if fi.IsDir() { t.Fatalf("got mode %v, want file", fi.Mode()) } else if fi.Size() != 5 { t.Fatalf("got size %d, want file size 5", fi.Size()) } if fi, err := os.Lstat(mnt + "/dir"); err != nil { t.Fatalf("Lstat: %v", err) } else if !fi.IsDir() { t.Fatalf("got %v, want dir", fi) } if fi, err := os.Lstat(mnt + "/dir/subfile"); err != nil { t.Fatalf("Lstat: %v", err) } else if fi.IsDir() || fi.Size() != 5 || fi.Mode()&0x111 == 0 { t.Fatalf("got %v, want +x file size 5", fi) } if fi, err := os.Lstat(mnt + "/link"); err != nil { t.Fatalf("Lstat: %v", err) } else if fi.Mode()&os.ModeSymlink == 0 { t.Fatalf("got %v, want symlink", fi.Mode()) } if content, err := ioutil.ReadFile(mnt + "/file"); err != nil { t.Fatalf("ReadFile: %v", err) } else if string(content) != "hello" { t.Errorf("got %q, want %q", content, "hello") } }
func TestUnionFsDelete(t *testing.T) { wd, clean := setupUfs(t) defer clean() writeToFile(wd+"/ro/file", "a") _, err := os.Lstat(wd + "/mnt/file") CheckSuccess(err) err = os.Remove(wd + "/mnt/file") CheckSuccess(err) _, err = os.Lstat(wd + "/mnt/file") if err == nil { t.Fatal("should have disappeared.") } delPath := wd + "/rw/" + testOpts.DeletionDirName names := dirNames(delPath) if len(names) != 1 { t.Fatal("Should have 1 deletion", names) } for k, _ := range names { c, err := ioutil.ReadFile(delPath + "/" + k) CheckSuccess(err) if string(c) != "file" { t.Fatal("content mismatch", string(c)) } } }
func TestUnionFsLink(t *testing.T) { wd, clean := setupUfs(t) defer clean() content := "blabla" fn := wd + "/ro/file" err := ioutil.WriteFile(fn, []byte(content), 0666) CheckSuccess(err) freezeRo(wd + "/ro") err = os.Link(wd+"/mnt/file", wd+"/mnt/linked") CheckSuccess(err) fi2, err := os.Lstat(wd + "/mnt/linked") CheckSuccess(err) fi1, err := os.Lstat(wd + "/mnt/file") CheckSuccess(err) if fi1.Ino != fi2.Ino { t.Errorf("inode numbers should be equal for linked files %v, %v", fi1.Ino, fi2.Ino) } c, err := ioutil.ReadFile(wd + "/mnt/linked") if string(c) != content { t.Errorf("content mismatch got %q want %q", string(c), content) } }
// DirMove moves src directory to this remote using server side move // operations. // // Will only be called if src.Fs().Name() == f.Name() // // If it isn't possible then return fs.ErrorCantDirMove // // If destination exists then return fs.ErrorDirExists func (f *Fs) DirMove(src fs.Fs) error { srcFs, ok := src.(*Fs) if !ok { fs.Debug(srcFs, "Can't move directory - not same remote type") return fs.ErrorCantDirMove } // Check if source exists sstat, err := os.Lstat(srcFs.root) if err != nil { return err } // And is a directory if !sstat.IsDir() { return fs.ErrorCantDirMove } // Check if destination exists _, err = os.Lstat(f.root) if !os.IsNotExist(err) { return fs.ErrorDirExists } // Do the move return os.Rename(srcFs.root, f.root) }
func (rw *rollingFileWriter) createFileAndFolderIfNeeded() error { var err error if len(rw.currentDirPath) != 0 { err = os.MkdirAll(rw.currentDirPath, defaultDirectoryPermissions) if err != nil { return err } } rw.fileName = rw.self.getCurrentModifiedFileName(rw.originalFileName) filePath := filepath.Join(rw.currentDirPath, rw.fileName) // If exists stat, err := os.Lstat(filePath) if err == nil { rw.currentFile, err = os.OpenFile(filePath, os.O_WRONLY|os.O_APPEND, defaultFilePermissions) stat, err = os.Lstat(filePath) if err != nil { return err } rw.currentFileSize = stat.Size() } else { rw.currentFile, err = os.Create(filePath) rw.currentFileSize = 0 } if err != nil { return err } return nil }
func (s *suite) TestConfigPerm(c *gc.C) { testing.MakeSampleJujuHome(c) path := gitjujutesting.HomePath(".juju") info, err := os.Lstat(path) c.Assert(err, jc.ErrorIsNil) oldPerm := info.Mode().Perm() env := ` environments: only: type: dummy state-server: false authorized-keys: i-am-a-key ` outfile, err := environs.WriteEnvirons("", env) c.Assert(err, jc.ErrorIsNil) info, err = os.Lstat(outfile) c.Assert(err, jc.ErrorIsNil) // Windows is not fully POSIX compliant. Normal permission // checking will yield unexpected results if runtime.GOOS != "windows" { c.Assert(info.Mode().Perm(), gc.Equals, os.FileMode(0600)) } info, err = os.Lstat(filepath.Dir(outfile)) c.Assert(err, jc.ErrorIsNil) if runtime.GOOS != "windows" { c.Assert(info.Mode().Perm(), gc.Equals, oldPerm) } }
func TestExplicitScan(t *testing.T) { wd, clean := setup(t) defer clean() err := os.Mkdir(wd+"/store/backing1", 0755) CheckSuccess(err) os.Symlink(wd+"/ro", wd+"/store/backing1/READONLY") CheckSuccess(err) fi, _ := os.Lstat(wd + "/mnt/backing1") if fi != nil { t.Error("Should not have file:", fi) } scan := wd + "/mnt/config/" + _SCAN_CONFIG _, err = os.Lstat(scan) if err != nil { t.Error(".scan_config missing:", err) } err = ioutil.WriteFile(scan, []byte("something"), 0644) if err != nil { t.Error("error writing:", err) } _, err = os.Lstat(wd + "/mnt/backing1") if err != nil { t.Error("Should have workspace backing1:", err) } }
func TestUnionFsCheckHiddenFiles(t *testing.T) { wd, clean := setupUfs(t) defer clean() err := ioutil.WriteFile(wd+"/ro/hidden", []byte("bla"), 0644) if err != nil { t.Fatalf("WriteFile failed: %v", err) } err = ioutil.WriteFile(wd+"/ro/not_hidden", []byte("bla"), 0644) if err != nil { t.Fatalf("WriteFile failed: %v", err) } setRecursiveWritable(t, wd+"/ro", false) fi, _ := os.Lstat(wd + "/mnt/hidden") if fi != nil { t.Fatal("Lstat() should have failed", fi) } _, err = os.Lstat(wd + "/mnt/not_hidden") if err != nil { t.Fatalf("Lstat failed: %v", err) } names, err := Readdirnames(wd + "/mnt") if err != nil { t.Fatalf("Readdirnames failed: %v", err) } if len(names) != 1 || names[0] != "not_hidden" { t.Fatal("unexpected names", names) } }
func TestUnionFsDelete(t *testing.T) { wd, clean := setupUfs(t) defer clean() WriteFile(t, wd+"/ro/file", "a") _, err := os.Lstat(wd + "/mnt/file") if err != nil { t.Fatalf("Lstat failed: %v", err) } err = os.Remove(wd + "/mnt/file") if err != nil { t.Fatalf("Remove failed: %v", err) } _, err = os.Lstat(wd + "/mnt/file") if err == nil { t.Fatal("should have disappeared.") } delPath := wd + "/rw/" + testOpts.DeletionDirName names := dirNames(t, delPath) if len(names) != 1 { t.Fatal("Should have 1 deletion", names) } for k := range names { c, err := ioutil.ReadFile(delPath + "/" + k) if err != nil { t.Fatalf("ReadFile failed: %v", err) } if string(c) != "file" { t.Fatal("content mismatch", string(c)) } } }
func TestChmod(t *testing.T) { wd, clean := setupUfs(t) defer clean() ro_fn := wd + "/ro/file" m_fn := wd + "/mount/file" writeToFile(ro_fn, "a") err := os.Chmod(m_fn, 07070) CheckSuccess(err) err = os.Chown(m_fn, 0, 0) code := fuse.OsErrorToErrno(err) if code != fuse.EPERM { t.Error("Unexpected error code", code, err) } fi, err := os.Lstat(m_fn) CheckSuccess(err) if fi.Mode&07777 != 07272 { t.Errorf("Unexpected mode found: %o", fi.Mode) } _, err = os.Lstat(wd + "/rw/file") if err != nil { t.Errorf("File not promoted") } }
func TestCopyChmod(t *testing.T) { t.Log("TestCopyChmod") wd, clean := setupUfs(t) defer clean() contents := "hello" fn := wd + "/mount/y" err := ioutil.WriteFile(fn, []byte(contents), 0644) CheckSuccess(err) err = os.Chmod(fn, 0755) CheckSuccess(err) fi, err := os.Lstat(fn) CheckSuccess(err) if fi.Mode&0111 == 0 { t.Errorf("1st attr error %o", fi.Mode) } time.Sleep(entryTtl * 1.1e9) fi, err = os.Lstat(fn) CheckSuccess(err) if fi.Mode&0111 == 0 { t.Errorf("uncached attr error %o", fi.Mode) } }
func TestDailyRotationAtOpen(t *testing.T) { path := "test_daily.log" stat, _ := os.Lstat(path) if stat != nil { os.Remove(path) } rotator := NewDailyRotator(path) rotator.WriteString("FIRST LOG") rotator.Close() now := time.Now() // simulate next day rotator = NewDailyRotator(path) defer rotator.Close() rotator.Now = time.Unix(now.Unix()+86400, 0) rotator.WriteString("NEXT LOG") stat, _ = os.Lstat(path + "." + now.Format(dateFormat)) assert.NotNil(t, stat) os.Remove(path) os.Remove(path + "." + now.Format(dateFormat)) }
func TestEntryNotify(t *testing.T) { test := NewNotifyTest(t) defer test.Clean() dir := test.dir test.fs.sizeChan <- 42 test.fs.existChan <- false fn := dir + "/dir/file" fi, _ := os.Lstat(fn) if fi != nil { t.Errorf("File should not exist, %#v", fi) } test.fs.existChan <- true fi, _ = os.Lstat(fn) if fi != nil { t.Errorf("negative entry should have been cached: %#v", fi) } code := test.pathfs.EntryNotify("dir", "file") if !code.Ok() { t.Errorf("EntryNotify returns error: %v", code) } fi, err := os.Lstat(fn) if err != nil { t.Fatalf("Lstat failed: %v", err) } }
func (w *FileLogWriter) intRotate() error { if w.file != nil { fmt.Fprint(w.file, FormatLogRecord(w.trailer, &LogRecord{Created: time.Now()})) w.file.Close() } if w.rotate { _, err := os.Lstat(w.filename) if err == nil { num := 1 fname := "" // 如果设置按日切换,并且当前时间不等于上次文件打开时间 if w.daily && time.Now().Day() != w.daily_opendate { // 获得昨天日期 yesterday := time.Now().AddDate(0, 0, -1).Format("2006-01-02") // 从1 到 999 找到一个空文件 // 一天最多999个日志文件 for ; err == nil && num <= 999; num++ { // 新文件名 = 文件名.昨日日期.num fname = w.filename + fmt.Sprintf(".%s.%03d", yesterday, num) _, err = os.Lstat(fname) } } else { // 如果不是按日,则使用当前时间 for ; err == nil && num <= 999; num++ { fname = w.filename + fmt.Sprintf(".%s.%03d", time.Now().Format("2006-01-02"), num) _, err = os.Lstat(fname) } } // 如果err 为空,则表示 有文件不存在 if err == nil { return fmt.Errorf("Rotate: Canot find free log number to rename %s\n", w.filename) } w.file.Close() // 文件重命名 err = os.Rename(w.filename, fname) if err != nil { return fmt.Errorf("Rotate: %s\n", err) } } } // 重新打开文件 fd, err := os.OpenFile(w.filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0660) if err != nil { return err } w.file = fd now := time.Now() fmt.Fprint(w.file, FormatLogRecord(w.header, &LogRecord{Created: now})) w.daily_opendate = now.Day() w.maxlines_curlines = 0 w.maxsize_cursize = 0 return nil }
// Try to get Lockfile lock. Returns nil, if successful and and error describing the reason, it didn't work out. // Please note, that existing lockfiles containing pids of dead processes and lockfiles containing no pid at all // are deleted. func (l Lockfile) TryLock() error { name := string(l) // This has been checked by New already. If we trigger here, // the caller didn't use New and re-implemented it's functionality badly. // So panic, that he might find this easily during testing. if !filepath.IsAbs(string(name)) { panic(ErrNeedAbsPath) } tmplock, err := ioutil.TempFile(filepath.Dir(name), "") if err != nil { return err } else { defer tmplock.Close() defer os.Remove(tmplock.Name()) } _, err = tmplock.WriteString(fmt.Sprintf("%d\n", os.Getpid())) if err != nil { return err } // return value intentionally ignored, as ignoring it is part of the algorithm _ = os.Link(tmplock.Name(), name) fiTmp, err := os.Lstat(tmplock.Name()) if err != nil { return err } fiLock, err := os.Lstat(name) if err != nil { return err } // Success if os.SameFile(fiTmp, fiLock) { return nil } _, err = l.GetOwner() switch err { default: // Other errors -> defensively fail and let caller handle this return err case nil: return ErrBusy case ErrDeadOwner, ErrInvalidPid: // cases we can fix below } // clean stale/invalid lockfile err = os.Remove(name) if err != nil { return err } // now that we cleaned up the stale lockfile, let's recurse return l.TryLock() }
func TestUnionFsRenameSymlink(t *testing.T) { wd, clean := setupUfs(t) defer clean() err := os.Symlink("linktarget", wd+"/ro/link") if err != nil { t.Fatalf("Symlink failed: %v", err) } err = os.Rename(wd+"/mnt/link", wd+"/mnt/renamed") if err != nil { t.Fatalf("Rename failed: %v", err) } if fi, _ := os.Lstat(wd + "/mnt/link"); fi != nil { t.Fatalf("%s/mnt/link should have disappeared: %v", wd, fi) } if fi, _ := os.Lstat(wd + "/mnt/renamed"); fi == nil || fi.Mode()&os.ModeSymlink == 0 { t.Fatalf("%s/mnt/renamed should be link: %v", wd, fi) } if link, err := os.Readlink(wd + "/mnt/renamed"); err != nil || link != "linktarget" { t.Fatalf("readlink(%s/mnt/renamed) should point to 'linktarget': %v, err %v", wd, link, err) } }
func (me *DiskFileCache) SaveContents(content []byte, dest string) os.Error { d, _ := filepath.Split(dest) if fi, _ := os.Lstat(d); fi == nil { if err := os.MkdirAll(d, 0700); err != nil { return err } } f, err := ioutil.TempFile(me.dir, ".diskcache_temp") if err != nil { return err } _, err = f.Write(content) if err != nil { return err } f.Close() if err != nil { return err } err = os.Rename(f.Name(), dest) if err != nil { if fi, _ := os.Lstat(dest); fi != nil { os.Remove(f.Name()) return nil } } return err }
func TestUnionFsCopyChmod(t *testing.T) { wd, clean := setupUfs(t) defer clean() contents := "hello" fn := wd + "/mnt/y" err := ioutil.WriteFile(fn, []byte(contents), 0644) if err != nil { t.Fatalf("WriteFile failed: %v", err) } err = os.Chmod(fn, 0755) if err != nil { t.Fatalf("Chmod failed: %v", err) } fi, err := os.Lstat(fn) if err != nil { t.Fatalf("Lstat failed: %v", err) } if fi.Mode()&0111 == 0 { t.Errorf("1st attr error %o", fi.Mode()) } time.Sleep(entryTtl) fi, err = os.Lstat(fn) if err != nil { t.Fatalf("Lstat failed: %v", err) } if fi.Mode()&0111 == 0 { t.Errorf("uncached attr error %o", fi.Mode()) } }
func TestRename(t *testing.T) { tc := NewTestCase(t) defer tc.Cleanup() contents := []byte{1, 2, 3} err := ioutil.WriteFile(tc.origFile, []byte(contents), 0700) if err != nil { t.Fatalf("WriteFile failed: %v", err) } sd := tc.mnt + "/testRename" err = os.MkdirAll(sd, 0777) subFile := sd + "/subfile" err = os.Rename(tc.mountFile, subFile) if err != nil { t.Fatalf("Rename failed: %v", err) } f, _ := os.Lstat(tc.origFile) if f != nil { t.Errorf("original %v still exists.", tc.origFile) } f, _ = os.Lstat(subFile) if f == nil { t.Errorf("destination %v does not exist.", subFile) } }
// Deal correctly with hard links implied by matching client inode // numbers. func TestLinkExisting(t *testing.T) { me := NewTestCase(t) defer me.Cleanup() c := "hello" err := ioutil.WriteFile(me.orig+"/file1", []byte(c), 0644) CheckSuccess(err) err = os.Link(me.orig+"/file1", me.orig+"/file2") CheckSuccess(err) f1, err := os.Lstat(me.mnt + "/file1") CheckSuccess(err) f2, err := os.Lstat(me.mnt + "/file2") CheckSuccess(err) if f1.Ino != f2.Ino { t.Errorf("linked files should have identical inodes %v %v", f1.Ino, f2.Ino) } c1, err := ioutil.ReadFile(me.mnt + "/file1") CheckSuccess(err) if string(c1) != c { t.Errorf("Content mismatch relative to original.") } }
func mainHandler(rw http.ResponseWriter, req *http.Request) { relPath := req.URL.Path[1:] // serveFile URL paths start with '/' if strings.Contains(relPath, "..") { return } if strings.HasPrefix(relPath, "gw/") { path := relPath[3:] http.Redirect(rw, req, "http://camlistore.org/code/?p=camlistore.git;f="+path+";hb=master", http.StatusFound) return } absPath := filepath.Join(*root, "content", relPath) fi, err := os.Lstat(absPath) if err != nil { log.Print(err) serveError(rw, req, relPath, err) return } if fi.IsDir() { relPath += "/index.html" absPath = filepath.Join(*root, "content", relPath) fi, err = os.Lstat(absPath) if err != nil { log.Print(err) serveError(rw, req, relPath, err) return } } switch { case !fi.IsDir(): serveFile(rw, req, relPath, absPath) } }
func (t *GcsfuseTest) CannedContents() { var err error var fi os.FileInfo // Mount. args := []string{canned.FakeBucketName, t.dir} err = t.runGcsfuse(args) AssertEq(nil, err) defer unmount(t.dir) // Check the expected contents of the file system. fi, err = os.Lstat(path.Join(t.dir, canned.TopLevelFile)) AssertEq(nil, err) ExpectEq(os.FileMode(0644), fi.Mode()) contents, err := ioutil.ReadFile(path.Join(t.dir, canned.TopLevelFile)) AssertEq(nil, err) ExpectEq(canned.TopLevelFile_Contents, string(contents)) fi, err = os.Lstat(path.Join(t.dir, canned.TopLevelDir)) AssertEq(nil, err) ExpectEq(0755|os.ModeDir, fi.Mode()) // The implicit directory shouldn't be visible, since we don't have implicit // directories enabled. _, err = os.Lstat(path.Join(t.dir, path.Dir(canned.ImplicitDirFile))) ExpectTrue(os.IsNotExist(err), "err: %v", err) }
func (suite) TestConfigPerm(c *C) { defer testing.MakeSampleHome(c).Restore() path := testing.HomePath(".juju") info, err := os.Lstat(path) c.Assert(err, IsNil) oldPerm := info.Mode().Perm() env := ` environments: only: type: dummy state-server: false authorized-keys: i-am-a-key ` outfile, err := environs.WriteEnvirons("", env) c.Assert(err, IsNil) info, err = os.Lstat(outfile) c.Assert(err, IsNil) c.Assert(info.Mode().Perm(), Equals, os.FileMode(0600)) info, err = os.Lstat(filepath.Dir(outfile)) c.Assert(err, IsNil) c.Assert(info.Mode().Perm(), Equals, oldPerm) }
func (t *GcsfuseTest) FileAndDirModeFlags() { var err error var fi os.FileInfo // Mount with non-standard modes. args := []string{ "--file-mode", "461", "--dir-mode", "511", canned.FakeBucketName, t.dir, } err = t.runGcsfuse(args) AssertEq(nil, err) defer unmount(t.dir) // Stat contents. fi, err = os.Lstat(path.Join(t.dir, canned.TopLevelFile)) AssertEq(nil, err) ExpectEq(os.FileMode(0461), fi.Mode()) fi, err = os.Lstat(path.Join(t.dir, canned.TopLevelDir)) AssertEq(nil, err) ExpectEq(0511|os.ModeDir, fi.Mode()) }
func TestUnionFsPromoteDirTimeStamp(t *testing.T) { wd, clean := setupUfs(t) defer clean() err := os.Mkdir(wd+"/ro/subdir", 0750) CheckSuccess(err) err = ioutil.WriteFile(wd+"/ro/subdir/file", []byte("hello"), 0644) CheckSuccess(err) freezeRo(wd + "/ro") err = os.Chmod(wd+"/mnt/subdir/file", 0060) CheckSuccess(err) fRo, err := os.Lstat(wd + "/ro/subdir") CheckSuccess(err) fRw, err := os.Lstat(wd + "/rw/subdir") CheckSuccess(err) // TODO - need to update timestamps after promoteDirsTo calls, // not during. if false && fRo.Mtime_ns != fRw.Mtime_ns { t.Errorf("Changed timestamps on promoted subdir: ro %d rw %d", fRo.Mtime_ns, fRw.Mtime_ns) } if fRo.Mode|0200 != fRw.Mode { t.Errorf("Changed mode ro: %o, rw: %o", fRo.Mode, fRw.Mode) } }
func (t *GcsfuseTest) UidAndGidFlags() { var err error var fi os.FileInfo // Mount, setting the flags. Make sure to set the directory mode such that we // can actually see the contents. args := []string{ "--uid", "1719", "--gid", "2329", "--dir-mode", "555", canned.FakeBucketName, t.dir, } err = t.runGcsfuse(args) AssertEq(nil, err) defer unmount(t.dir) // Stat contents. fi, err = os.Lstat(path.Join(t.dir, canned.TopLevelFile)) AssertEq(nil, err) ExpectEq(1719, fi.Sys().(*syscall.Stat_t).Uid) ExpectEq(2329, fi.Sys().(*syscall.Stat_t).Gid) fi, err = os.Lstat(path.Join(t.dir, canned.TopLevelDir)) AssertEq(nil, err) ExpectEq(1719, fi.Sys().(*syscall.Stat_t).Uid) ExpectEq(2329, fi.Sys().(*syscall.Stat_t).Gid) }
func TestUnionFsRenameDirBasic(t *testing.T) { wd, clean := setupUfs(t) defer clean() err := os.MkdirAll(wd+"/ro/dir/subdir", 0755) CheckSuccess(err) err = os.Rename(wd+"/mnt/dir", wd+"/mnt/renamed") CheckSuccess(err) if fi, _ := os.Lstat(wd + "/mnt/dir"); fi != nil { t.Fatalf("%s/mnt/dir should have disappeared: %v", wd, fi) } if fi, _ := os.Lstat(wd + "/mnt/renamed"); fi == nil || !fi.IsDirectory() { t.Fatalf("%s/mnt/renamed should be directory: %v", wd, fi) } entries, err := ioutil.ReadDir(wd + "/mnt/renamed") if err != nil || len(entries) != 1 || entries[0].Name != "subdir" { t.Errorf("readdir(%s/mnt/renamed) should have one entry: %v, err %v", wd, entries, err) } if err = os.Mkdir(wd+"/mnt/dir", 0755); err != nil { t.Errorf("mkdir should succeed %v", err) } }
func (driver *FsDriver) dlFileWithProgress(src, des string) { src = driver.AbsPath(src) des, _ = filepath.Abs(des) barSize := 1 upInfo, err := driver.up.GetInfo(src) if err == nil && upInfo.Size != 0 { barSize = int(upInfo.Size) } skip := false if dkInfo, e := os.Lstat(des); e == nil && int(upInfo.Size) == int(dkInfo.Size()) { return } bar := driver.NewProgressBar(barSize, skip, driver.dlFile, src, des) for upInfo != nil && bar.Current() != bar.Total { time.Sleep(time.Millisecond * 40) if dkInfo, e := os.Lstat(des); e == nil { v := int(dkInfo.Size()) if v == int(upInfo.Size) { bar.Set(bar.Total) break } bar.Set(v) } } }
// EvalSymlinks returns the path name after the evaluation of any symbolic // links. // If path is relative it will be evaluated relative to the current directory. func EvalSymlinks(path string) (string, os.Error) { if runtime.GOOS == "windows" { // Symlinks are not supported under windows. _, err := os.Lstat(path) if err != nil { return "", err } return Clean(path), nil } const maxIter = 255 originalPath := path // consume path by taking each frontmost path element, // expanding it if it's a symlink, and appending it to b var b bytes.Buffer for n := 0; path != ""; n++ { if n > maxIter { return "", os.NewError("EvalSymlinks: too many links in " + originalPath) } // find next path component, p i := strings.IndexRune(path, Separator) var p string if i == -1 { p, path = path, "" } else { p, path = path[:i], path[i+1:] } if p == "" { if b.Len() == 0 { // must be absolute path b.WriteRune(Separator) } continue } fi, err := os.Lstat(b.String() + p) if err != nil { return "", err } if !fi.IsSymlink() { b.WriteString(p) if path != "" { b.WriteRune(Separator) } continue } // it's a symlink, put it at the front of path dest, err := os.Readlink(b.String() + p) if err != nil { return "", err } if IsAbs(dest) { b.Reset() } path = dest + string(Separator) + path } return Clean(b.String()), nil }
func TestInodeNotify(t *testing.T) { test := NewNotifyTest() defer test.Clean() fs := test.fs dir := test.dir fs.size = 42 fi, err := os.Lstat(dir + "/file") CheckSuccess(err) if !fi.IsRegular() || fi.Size != 42 { t.Error(fi) } fs.size = 666 fi, err = os.Lstat(dir + "/file") CheckSuccess(err) if !fi.IsRegular() || fi.Size == 666 { t.Error(fi) } code := test.pathfs.FileNotify("file", -1, 0) if !code.Ok() { t.Error(code) } fi, err = os.Lstat(dir + "/file") CheckSuccess(err) if !fi.IsRegular() || fi.Size != 666 { t.Error(fi) } }