func (decoderData *decoderData) addSpecialFile(header *tar.Header, parent *filesystem.DirectoryInode, name string) error { var newInode filesystem.SpecialInode if header.Typeflag == tar.TypeChar { newInode.Mode = filesystem.FileMode((header.Mode & ^syscall.S_IFMT) | syscall.S_IFCHR) } else if header.Typeflag == tar.TypeBlock { newInode.Mode = filesystem.FileMode((header.Mode & ^syscall.S_IFMT) | syscall.S_IFBLK) } else if header.Typeflag == tar.TypeFifo { newInode.Mode = filesystem.FileMode((header.Mode & ^syscall.S_IFMT) | syscall.S_IFIFO) } else { return errors.New(fmt.Sprintf("unsupported type: %v", header.Typeflag)) } newInode.Uid = uint32(header.Uid) newInode.Gid = uint32(header.Gid) newInode.MtimeNanoSeconds = int32(header.ModTime.Nanosecond()) newInode.MtimeSeconds = header.ModTime.Unix() if header.Devminor > 255 { return errors.New(fmt.Sprintf("minor device number: %d too large", header.Devminor)) } newInode.Rdev = uint64(header.Devmajor<<8 | header.Devminor) decoderData.addEntry(parent, header.Name, name, &newInode) return nil }
func (decoderData *decoderData) addFile(header *tar.Header, parent *filesystem.Directory, name string) error { var newInode filesystem.Inode if header.Typeflag == tar.TypeChar { newInode.Mode = filesystem.FileMode((header.Mode & ^syscall.S_IFMT) | syscall.S_IFCHR) } else if header.Typeflag == tar.TypeBlock { newInode.Mode = filesystem.FileMode((header.Mode & ^syscall.S_IFMT) | syscall.S_IFBLK) } else if header.Typeflag == tar.TypeFifo { newInode.Mode = filesystem.FileMode((header.Mode & ^syscall.S_IFMT) | syscall.S_IFIFO) } else { return errors.New(fmt.Sprintf("unsupported type: %v", header.Typeflag)) } newInode.Uid = uint32(header.Uid) newInode.Gid = uint32(header.Gid) newInode.MtimeNanoSeconds = int32(header.ModTime.Nanosecond()) newInode.MtimeSeconds = header.ModTime.Unix() if header.Devminor > 255 { return errors.New(fmt.Sprintf("minor device number: %d too large", header.Devminor)) } newInode.Rdev = uint64(header.Devmajor<<8 | header.Devminor) decoderData.inodeTable[header.Name] = decoderData.nextInodeNumber decoderData.fileSystem.InodeTable[decoderData.nextInodeNumber] = &newInode var newEntry filesystem.File newEntry.Name = name newEntry.InodeNumber = decoderData.nextInodeNumber parent.FileList = append(parent.FileList, &newEntry) decoderData.nextInodeNumber++ return nil }
func addDirectory(dirent, oldDirent *filesystem.DirectoryEntry, fileSystem, oldFS *FileSystem, directoryPathName string, stat *syscall.Stat_t) error { myPathName := path.Join(directoryPathName, dirent.Name) if stat.Ino == fileSystem.inodeNumber { return errors.New("Recursive directory: " + myPathName) } if _, ok := fileSystem.InodeTable[stat.Ino]; ok { return errors.New("Hardlinked directory: " + myPathName) } inode := new(filesystem.DirectoryInode) dirent.SetInode(inode) fileSystem.InodeTable[stat.Ino] = inode inode.Mode = filesystem.FileMode(stat.Mode) inode.Uid = stat.Uid inode.Gid = stat.Gid var oldInode *filesystem.DirectoryInode if oldDirent != nil { if oi, ok := oldDirent.Inode().(*filesystem.DirectoryInode); ok { oldInode = oi } } err, copied := scanDirectory(inode, oldInode, fileSystem, oldFS, myPathName) if err != nil { return err } if copied && filesystem.CompareDirectoriesMetadata(inode, oldInode, nil) { dirent.SetInode(oldInode) fileSystem.InodeTable[stat.Ino] = oldInode } fileSystem.DirectoryCount++ return nil }
func makeSpecialInode(stat *syscall.Stat_t) *filesystem.SpecialInode { var inode filesystem.SpecialInode inode.Mode = filesystem.FileMode(stat.Mode) inode.Uid = stat.Uid inode.Gid = stat.Gid inode.MtimeSeconds = stat.Mtim.Sec inode.MtimeNanoSeconds = int32(stat.Mtim.Nsec) inode.Rdev = stat.Rdev return &inode }
func makeRegularInode(stat *syscall.Stat_t) *filesystem.RegularInode { var inode filesystem.RegularInode inode.Mode = filesystem.FileMode(stat.Mode) inode.Uid = stat.Uid inode.Gid = stat.Gid inode.MtimeSeconds = stat.Mtim.Sec inode.MtimeNanoSeconds = int32(stat.Mtim.Nsec) inode.Size = uint64(stat.Size) return &inode }
func (decoderData *decoderData) addDirectory(header *tar.Header, parent *filesystem.Directory, name string) error { var newEntry filesystem.Directory newEntry.Name = name newEntry.Mode = filesystem.FileMode((header.Mode & ^syscall.S_IFMT) | syscall.S_IFDIR) newEntry.Uid = uint32(header.Uid) newEntry.Gid = uint32(header.Gid) parent.DirectoryList = append(parent.DirectoryList, &newEntry) decoderData.directoryTable[header.Name] = &newEntry return nil }
func pushFile(getSubClient getSubClientFunc, source, dest string) error { var sourceStat wsyscall.Stat_t if err := wsyscall.Stat(source, &sourceStat); err != nil { return err } sourceFile, err := os.Open(source) if err != nil { return err } defer sourceFile.Close() srpcClient := getSubClient() objClient := objclient.AttachObjectClient(srpcClient) defer objClient.Close() if err != nil { return err } hashVal, _, err := objClient.AddObject(sourceFile, uint64(sourceStat.Size), nil) if err != nil { return err } newRegularInode := &filesystem.RegularInode{ Mode: filesystem.FileMode(sourceStat.Mode), Uid: sourceStat.Uid, Gid: sourceStat.Gid, MtimeNanoSeconds: int32(sourceStat.Mtim.Nsec), MtimeSeconds: sourceStat.Mtim.Sec, Size: uint64(sourceStat.Size), Hash: hashVal} newInode := sub.Inode{Name: dest, GenericInode: newRegularInode} var updateRequest sub.UpdateRequest var updateReply sub.UpdateResponse updateRequest.Wait = true updateRequest.InodesToMake = append(updateRequest.InodesToMake, newInode) if *triggersFile != "" { updateRequest.Triggers, err = triggers.Load(*triggersFile) if err != nil { return err } } else if *triggersString != "" { updateRequest.Triggers, err = triggers.Decode([]byte(*triggersString)) if err != nil { return err } } startTime := showStart("Subd.Update()") err = client.CallUpdate(srpcClient, updateRequest, &updateReply) showTimeTaken(startTime) return err }
func (decoderData *decoderData) addDirectory(header *tar.Header, parent *filesystem.DirectoryInode, name string) error { var newInode filesystem.DirectoryInode newInode.Mode = filesystem.FileMode((header.Mode & ^syscall.S_IFMT) | syscall.S_IFDIR) newInode.Uid = uint32(header.Uid) newInode.Gid = uint32(header.Gid) if header.Name == "/" { *decoderData.directoryTable[header.Name] = newInode return nil } decoderData.addEntry(parent, header.Name, name, &newInode) decoderData.directoryTable[header.Name] = &newInode return nil }
func scanFileSystem(rootDirectoryName string, fsScanContext *fsrateio.ReaderContext, scanFilter *filter.Filter, checkScanDisableRequest func() bool, hasher Hasher, oldFS *FileSystem) ( *FileSystem, error) { var fileSystem FileSystem fileSystem.rootDirectoryName = rootDirectoryName fileSystem.fsScanContext = fsScanContext fileSystem.scanFilter = scanFilter fileSystem.checkScanDisableRequest = checkScanDisableRequest if hasher == nil { fileSystem.hasher = GetSimpleHasher(false) } else { fileSystem.hasher = hasher } var stat wsyscall.Stat_t if err := wsyscall.Lstat(rootDirectoryName, &stat); err != nil { return nil, err } fileSystem.InodeTable = make(filesystem.InodeTable) fileSystem.dev = stat.Dev fileSystem.inodeNumber = stat.Ino fileSystem.Mode = filesystem.FileMode(stat.Mode) fileSystem.Uid = stat.Uid fileSystem.Gid = stat.Gid fileSystem.DirectoryCount++ var tmpInode filesystem.RegularInode if sha512.New().Size() != len(tmpInode.Hash) { return nil, errors.New("incompatible hash size") } var oldDirectory *filesystem.DirectoryInode if oldFS != nil && oldFS.InodeTable != nil { oldDirectory = &oldFS.DirectoryInode } err, _ := scanDirectory(&fileSystem.FileSystem.DirectoryInode, oldDirectory, &fileSystem, oldFS, "/") oldFS = nil oldDirectory = nil if err != nil { return nil, err } fileSystem.ComputeTotalDataBytes() if err = fileSystem.RebuildInodePointers(); err != nil { panic(err) } return &fileSystem, nil }
func (fileSystem *FileSystem) getInode(stat *syscall.Stat_t) ( *filesystem.Inode, bool) { inode := fileSystem.InodeTable[stat.Ino] new := false if inode == nil { var _inode filesystem.Inode inode = &_inode _inode.Mode = filesystem.FileMode(stat.Mode) _inode.Uid = stat.Uid _inode.Gid = stat.Gid _inode.MtimeSeconds = stat.Mtim.Sec _inode.MtimeNanoSeconds = int32(stat.Mtim.Nsec) _inode.Rdev = stat.Rdev fileSystem.InodeTable[stat.Ino] = inode new = true } return inode, new }
func addDirectory(directory *filesystem.Directory, fileSystem, oldFS *FileSystem, name string, directoryPathName string, stat *syscall.Stat_t) error { myPathName := path.Join(directoryPathName, name) if fileSystem.directoryInodeList[stat.Ino] { return errors.New("Hardlinked directory: " + myPathName) } fileSystem.directoryInodeList[stat.Ino] = true var dir filesystem.Directory dir.Name = name dir.Mode = filesystem.FileMode(stat.Mode) dir.Uid = stat.Uid dir.Gid = stat.Gid err := scanDirectory(&dir, fileSystem, oldFS, directoryPathName) if err != nil { return err } directory.DirectoryList = append(directory.DirectoryList, &dir) return nil }
func scanFileSystem(rootDirectoryName string, cacheDirectoryName string, configuration *Configuration, oldFS *FileSystem) (*FileSystem, error) { var fileSystem FileSystem fileSystem.configuration = configuration fileSystem.rootDirectoryName = rootDirectoryName fileSystem.cacheDirectoryName = cacheDirectoryName var stat syscall.Stat_t if err := syscall.Lstat(rootDirectoryName, &stat); err != nil { return nil, err } fileSystem.InodeTable = make(filesystem.InodeTable) fileSystem.dev = stat.Dev fileSystem.inodeNumber = stat.Ino fileSystem.Mode = filesystem.FileMode(stat.Mode) fileSystem.Uid = stat.Uid fileSystem.Gid = stat.Gid fileSystem.DirectoryCount++ var tmpInode filesystem.RegularInode if sha512.New().Size() != len(tmpInode.Hash) { return nil, errors.New("Incompatible hash size") } var oldDirectory *filesystem.DirectoryInode if oldFS != nil && oldFS.InodeTable != nil { oldDirectory = &oldFS.DirectoryInode } err, _ := scanDirectory(&fileSystem.FileSystem.DirectoryInode, oldDirectory, &fileSystem, oldFS, "/") oldFS = nil oldDirectory = nil if err != nil { return nil, err } if err = fileSystem.scanObjectCache(); err != nil { return nil, err } fileSystem.ComputeTotalDataBytes() if err = fileSystem.RebuildInodePointers(); err != nil { panic(err) } return &fileSystem, nil }
func (decoderData *decoderData) addRegularFile(tarReader *tar.Reader, hasher Hasher, header *tar.Header, parent *filesystem.DirectoryInode, name string) error { var newInode filesystem.RegularInode newInode.Mode = filesystem.FileMode((header.Mode & ^syscall.S_IFMT) | syscall.S_IFREG) newInode.Uid = uint32(header.Uid) newInode.Gid = uint32(header.Gid) newInode.MtimeNanoSeconds = int32(header.ModTime.Nanosecond()) newInode.MtimeSeconds = header.ModTime.Unix() newInode.Size = uint64(header.Size) if header.Size > 0 { var err error newInode.Hash, err = hasher.Hash(tarReader, uint64(header.Size)) if err != nil { return err } } decoderData.addEntry(parent, header.Name, name, &newInode) return nil }
func scanFileSystem(rootDirectoryName string, cacheDirectoryName string, configuration *Configuration, oldFS *FileSystem) (*FileSystem, error) { var fileSystem FileSystem fileSystem.configuration = configuration fileSystem.rootDirectoryName = rootDirectoryName fileSystem.cacheDirectoryName = cacheDirectoryName fileSystem.Name = "/" var stat syscall.Stat_t err := syscall.Lstat(rootDirectoryName, &stat) if err != nil { return nil, err } fileSystem.RegularInodeTable = make(filesystem.RegularInodeTable) fileSystem.SymlinkInodeTable = make(filesystem.SymlinkInodeTable) fileSystem.InodeTable = make(filesystem.InodeTable) fileSystem.directoryInodeList = make(directoryInodeList) fileSystem.directoryInodeList[stat.Ino] = true fileSystem.dev = stat.Dev fileSystem.Mode = filesystem.FileMode(stat.Mode) fileSystem.Uid = stat.Uid fileSystem.Gid = stat.Gid var tmpInode filesystem.RegularInode if sha512.New().Size() != len(tmpInode.Hash) { return nil, errors.New("Incompatible hash size") } err = scanDirectory(&fileSystem.FileSystem.Directory, &fileSystem, oldFS, "") oldFS = nil fileSystem.DirectoryCount = uint64(len(fileSystem.directoryInodeList)) fileSystem.directoryInodeList = nil if err != nil { return nil, err } err = fileSystem.scanObjectCache() if err != nil { return nil, err } fileSystem.ComputeTotalDataBytes() return &fileSystem, nil }
func (decoderData *decoderData) addRegularFile(tarReader *tar.Reader, dataHandler DataHandler, header *tar.Header, parent *filesystem.Directory, name string) error { var newInode filesystem.RegularInode newInode.Mode = filesystem.FileMode((header.Mode & ^syscall.S_IFMT) | syscall.S_IFREG) newInode.Uid = uint32(header.Uid) newInode.Gid = uint32(header.Gid) newInode.MtimeNanoSeconds = int32(header.ModTime.Nanosecond()) newInode.MtimeSeconds = header.ModTime.Unix() newInode.Size = uint64(header.Size) if header.Size > 0 { data, err := ioutil.ReadAll(tarReader) if err != nil { return errors.New("error reading file data" + err.Error()) } if int64(len(data)) != header.Size { return errors.New(fmt.Sprintf( "failed to read file data, wanted: %d, got: %d bytes", header.Size, len(data))) } newInode.Hash, err = dataHandler.HandleData(data) if err != nil { return err } } decoderData.regularInodeTable[header.Name] = decoderData.nextInodeNumber decoderData.fileSystem.RegularInodeTable[decoderData.nextInodeNumber] = &newInode var newEntry filesystem.RegularFile newEntry.Name = name newEntry.InodeNumber = decoderData.nextInodeNumber parent.RegularFileList = append(parent.RegularFileList, &newEntry) decoderData.nextInodeNumber++ return nil }