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 makeDirectory(request *subproto.UpdateRequest, requiredInode *filesystem.DirectoryInode, pathName string, create bool) { var newInode subproto.Inode newInode.Name = pathName var newDirectoryInode filesystem.DirectoryInode newDirectoryInode.Mode = requiredInode.Mode newDirectoryInode.Uid = requiredInode.Uid newDirectoryInode.Gid = requiredInode.Gid newInode.GenericInode = &newDirectoryInode if create { request.DirectoriesToMake = append(request.DirectoriesToMake, newInode) } else { request.InodesToChange = append(request.InodesToChange, newInode) } }
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 (decoderData *decoderData) addEntry(parent *filesystem.DirectoryInode, fullName, name string, inode filesystem.GenericInode) { var newEntry filesystem.DirectoryEntry newEntry.Name = name newEntry.InodeNumber = decoderData.nextInodeNumber newEntry.SetInode(inode) parent.EntryList = append(parent.EntryList, &newEntry) decoderData.addInode(fullName, inode) }
func sortDirectory(directory *filesystem.DirectoryInode) { var entryList directoryEntryList entryList = directory.EntryList sort.Sort(entryList) directory.EntryList = entryList // Recurse through directories. for _, dirent := range directory.EntryList { if inode, ok := dirent.Inode().(*filesystem.DirectoryInode); ok { sortDirectory(inode) } } }
func (decoderData *decoderData) addHardlink(header *tar.Header, parent *filesystem.DirectoryInode, name string) error { header.Linkname = normaliseFilename(header.Linkname) if inum, ok := decoderData.inodeTable[header.Linkname]; ok { var newEntry filesystem.DirectoryEntry newEntry.Name = name newEntry.InodeNumber = inum parent.EntryList = append(parent.EntryList, &newEntry) } else { return errors.New(fmt.Sprintf("missing hardlink target: %s", header.Linkname)) } return nil }
func scanDirectory(directory, oldDirectory *filesystem.DirectoryInode, fileSystem, oldFS *FileSystem, myPathName string) (error, bool) { file, err := os.Open(path.Join(fileSystem.rootDirectoryName, myPathName)) if err != nil { return err, false } names, err := file.Readdirnames(-1) file.Close() if err != nil { return err, false } sort.Strings(names) entryList := make([]*filesystem.DirectoryEntry, 0, len(names)) var copiedDirents int for _, name := range names { if directory == &fileSystem.DirectoryInode && name == ".subd" { continue } filename := path.Join(myPathName, name) if fileSystem.configuration.ScanFilter.Match(filename) { continue } var stat syscall.Stat_t err := syscall.Lstat(path.Join(fileSystem.rootDirectoryName, filename), &stat) if err != nil { if err == syscall.ENOENT { continue } return err, false } if stat.Dev != fileSystem.dev { continue } if checkScanDisableRequest() { return errors.New("DisableScan"), false } myGC() dirent := new(filesystem.DirectoryEntry) dirent.Name = name dirent.InodeNumber = stat.Ino var oldDirent *filesystem.DirectoryEntry if oldDirectory != nil { index := len(entryList) if len(oldDirectory.EntryList) > index && oldDirectory.EntryList[index].Name == name { oldDirent = oldDirectory.EntryList[index] } } if stat.Mode&syscall.S_IFMT == syscall.S_IFDIR { err = addDirectory(dirent, oldDirent, fileSystem, oldFS, myPathName, &stat) } else if stat.Mode&syscall.S_IFMT == syscall.S_IFREG { err = addRegularFile(dirent, fileSystem, oldFS, myPathName, &stat) } else if stat.Mode&syscall.S_IFMT == syscall.S_IFLNK { err = addSymlink(dirent, fileSystem, oldFS, myPathName, &stat) } else if stat.Mode&syscall.S_IFMT == syscall.S_IFSOCK { continue } else { err = addSpecialFile(dirent, fileSystem, oldFS, &stat) } if err != nil { if err == syscall.ENOENT { continue } return err, false } if oldDirent != nil && *dirent == *oldDirent { dirent = oldDirent copiedDirents++ } entryList = append(entryList, dirent) } if oldDirectory != nil && len(entryList) == copiedDirents && len(entryList) == len(oldDirectory.EntryList) { directory.EntryList = oldDirectory.EntryList return nil, true } else { directory.EntryList = entryList return nil, false } }