github.com/Cloud-Foundations/Dominator@v0.3.4/lib/filesystem/write.go (about) 1 package filesystem 2 3 import ( 4 "errors" 5 "os" 6 "syscall" 7 "time" 8 9 "github.com/Cloud-Foundations/Dominator/lib/fsutil" 10 ) 11 12 var modePerm FileMode = syscall.S_IRWXU | syscall.S_IRWXG | syscall.S_IRWXO 13 14 func forceWriteMetadata(inode GenericInode, name string) error { 15 err := inode.WriteMetadata(name) 16 if err == nil { 17 return nil 18 } 19 if os.IsPermission(err) { 20 // Blindly attempt to remove immutable attributes. 21 fsutil.MakeMutable(name) 22 } 23 return inode.WriteMetadata(name) 24 } 25 26 func (inode *DirectoryInode) write(name string) error { 27 if err := inode.make(name); err != nil { 28 // If existing directory, don't blow it away, just update metadata. 29 if os.IsExist(err) { 30 if fi, err := os.Lstat(name); err == nil && fi.IsDir() { 31 return inode.writeMetadata(name) 32 } 33 } 34 fsutil.ForceRemoveAll(name) 35 if err := inode.make(name); err != nil { 36 return err 37 } 38 } 39 return inode.writeMetadata(name) 40 } 41 42 func (inode *DirectoryInode) make(name string) error { 43 return syscall.Mkdir(name, uint32(inode.Mode)) 44 } 45 46 func (inode *DirectoryInode) writeMetadata(name string) error { 47 if err := os.Lchown(name, int(inode.Uid), int(inode.Gid)); err != nil { 48 return err 49 } 50 return syscall.Chmod(name, uint32(inode.Mode)) 51 } 52 53 func (inode *RegularInode) writeMetadata(name string) error { 54 if err := os.Lchown(name, int(inode.Uid), int(inode.Gid)); err != nil { 55 return err 56 } 57 if err := syscall.Chmod(name, uint32(inode.Mode)); err != nil { 58 return err 59 } 60 t := time.Unix(inode.MtimeSeconds, int64(inode.MtimeNanoSeconds)) 61 return os.Chtimes(name, t, t) 62 } 63 64 func (inode *SymlinkInode) write(name string) error { 65 if inode.make(name) != nil { 66 fsutil.ForceRemoveAll(name) 67 if err := inode.make(name); err != nil { 68 return err 69 } 70 } 71 return inode.writeMetadata(name) 72 } 73 74 func (inode *SymlinkInode) make(name string) error { 75 return os.Symlink(inode.Symlink, name) 76 } 77 78 func (inode *SymlinkInode) writeMetadata(name string) error { 79 return os.Lchown(name, int(inode.Uid), int(inode.Gid)) 80 } 81 82 func (inode *SpecialInode) write(name string) error { 83 if inode.make(name) != nil { 84 fsutil.ForceRemoveAll(name) 85 if err := inode.make(name); err != nil { 86 return err 87 } 88 } 89 return inode.writeMetadata(name) 90 } 91 92 func (inode *SpecialInode) make(name string) error { 93 if inode.Mode&syscall.S_IFBLK != 0 || inode.Mode&syscall.S_IFCHR != 0 { 94 return syscall.Mknod(name, uint32(inode.Mode), int(inode.Rdev)) 95 } else if inode.Mode&syscall.S_IFIFO != 0 { 96 return syscall.Mkfifo(name, uint32(inode.Mode)) 97 } else { 98 return errors.New("unsupported mode") 99 } 100 } 101 102 func (inode *SpecialInode) writeMetadata(name string) error { 103 if err := os.Lchown(name, int(inode.Uid), int(inode.Gid)); err != nil { 104 return err 105 } 106 if err := syscall.Chmod(name, uint32(inode.Mode)); err != nil { 107 return err 108 } 109 t := time.Unix(inode.MtimeSeconds, int64(inode.MtimeNanoSeconds)) 110 return os.Chtimes(name, t, t) 111 }