func compareDirectories(request *subproto.UpdateRequest, state *state, subDirectory, requiredDirectory *filesystem.Directory, parentName string, filter *filter.Filter) { requiredPathName := path.Join(parentName, requiredDirectory.Name) // First look for entries that should be deleted. makeSubDirectory := false if subDirectory == nil { makeSubDirectory = true } else { subPathName := path.Join(parentName, subDirectory.Name) for name, subEntry := range subDirectory.EntriesByName { pathname := path.Join(subPathName, entryName(subEntry)) if filter.Match(pathname) { continue } if _, ok := requiredDirectory.EntriesByName[name]; !ok { request.PathsToDelete = append(request.PathsToDelete, pathname) fmt.Printf("Delete: %s\n", pathname) // HACK } } if !filesystem.CompareDirectoriesMetadata(subDirectory, requiredDirectory, os.Stdout) { fmt.Printf("Different directory: %s...\n", requiredPathName) // HACK makeSubDirectory = true // TODO(rgooch): Update metadata. } } if makeSubDirectory { var newdir subproto.Directory newdir.Name = requiredPathName newdir.Mode = requiredDirectory.Mode newdir.Uid = requiredDirectory.Uid newdir.Gid = requiredDirectory.Gid request.DirectoriesToMake = append(request.DirectoriesToMake, newdir) } for name, requiredEntry := range requiredDirectory.EntriesByName { pathname := path.Join(requiredPathName, entryName(requiredEntry)) if filter.Match(pathname) { continue } if subDirectory == nil { compareEntries(request, state, nil, requiredEntry, requiredPathName, filter) } else { if subEntry, ok := subDirectory.EntriesByName[name]; ok { compareEntries(request, state, subEntry, requiredEntry, requiredPathName, filter) } else { compareEntries(request, state, nil, requiredEntry, requiredPathName, filter) } } } }
func (inode *DirectoryInode) filter(newFS *FileSystem, filter *filter.Filter, name string) *DirectoryInode { newInode := new(DirectoryInode) newInode.Mode = inode.Mode newInode.Uid = inode.Uid newInode.Gid = inode.Gid for _, entry := range inode.EntryList { subName := path.Join(name, entry.Name) if filter.Match(subName) { continue } var newEntry *DirectoryEntry if inode, ok := entry.inode.(*DirectoryInode); ok { newEntry = new(DirectoryEntry) newEntry.Name = entry.Name newEntry.InodeNumber = entry.InodeNumber newEntry.inode = inode.filter(newFS, filter, subName) } else { newEntry = entry } newInode.EntryList = append(newInode.EntryList, newEntry) newFS.InodeTable[entry.InodeNumber] = newEntry.inode } newFS.DirectoryCount++ return newInode }
func compareDirectories(request *subproto.UpdateRequest, state *state, subDirectory, requiredDirectory *filesystem.DirectoryInode, myPathName string, filter *filter.Filter) { // First look for entries that should be deleted. if subDirectory != nil { for name := range subDirectory.EntriesByName { pathname := path.Join(myPathName, name) if filter.Match(pathname) { continue } if _, ok := requiredDirectory.EntriesByName[name]; !ok { request.PathsToDelete = append(request.PathsToDelete, pathname) } } } for name, requiredEntry := range requiredDirectory.EntriesByName { pathname := path.Join(myPathName, name) if filter.Match(pathname) { continue } var subEntry *filesystem.DirectoryEntry if subDirectory != nil { if se, ok := subDirectory.EntriesByName[name]; ok { subEntry = se } } if subEntry == nil { addEntry(request, state, requiredEntry, pathname) } else { compareEntries(request, state, subEntry, requiredEntry, pathname, filter) } // If a directory: descend (possibly with the directory for the sub). requiredInode := requiredEntry.Inode() if requiredInode, ok := requiredInode.(*filesystem.DirectoryInode); ok { var subInode *filesystem.DirectoryInode if subEntry != nil { if si, ok := subEntry.Inode().(*filesystem.DirectoryInode); ok { subInode = si } } compareDirectories(request, state, subInode, requiredInode, pathname, filter) } } }
func (inode *DirectoryInode) list(w io.Writer, name string, numLinksTable NumLinksTable, numLinks int, listSelector ListSelector, filter *filter.Filter) error { if err := listUntilName(w, inode.Mode, numLinks, inode.Uid, inode.Gid, 0, -1, -1, name, true, listSelector); err != nil { return err } for _, dirent := range inode.EntryList { pathname := path.Join(name, dirent.Name) if filter != nil && filter.Match(pathname) { continue } err := dirent.inode.List(w, pathname, numLinksTable, numLinksTable[dirent.InodeNumber], listSelector, filter) if err != nil { return err } } return nil }
func decode(tarReader *tar.Reader, hasher Hasher, filter *filter.Filter) ( *filesystem.FileSystem, error) { var decoderData decoderData decoderData.inodeTable = make(map[string]uint64) decoderData.directoryTable = make(map[string]*filesystem.DirectoryInode) fileSystem := &decoderData.fileSystem fileSystem.InodeTable = make(filesystem.InodeTable) // Create a default top-level directory which may be updated. decoderData.addInode("/", &fileSystem.DirectoryInode) fileSystem.DirectoryInode.Mode = syscall.S_IFDIR | syscall.S_IRWXU | syscall.S_IRGRP | syscall.S_IXGRP | syscall.S_IROTH | syscall.S_IXOTH decoderData.directoryTable["/"] = &fileSystem.DirectoryInode for { header, err := tarReader.Next() if err == io.EOF { break } if err != nil { return nil, err } header.Name = normaliseFilename(header.Name) if header.Name == "/.subd" || strings.HasPrefix(header.Name, "/.subd/") { continue } if filter != nil && filter.Match(header.Name) { continue } err = decoderData.addHeader(tarReader, hasher, header) if err != nil { return nil, err } } delete(fileSystem.InodeTable, 0) fileSystem.DirectoryCount = uint64(len(decoderData.directoryTable)) fileSystem.ComputeTotalDataBytes() sortDirectory(&fileSystem.DirectoryInode) return fileSystem, nil }
func decode(tarReader *tar.Reader, dataHandler DataHandler, filter *filter.Filter) (*filesystem.FileSystem, error) { var decoderData decoderData decoderData.regularInodeTable = make(map[string]uint64) decoderData.symlinkInodeTable = make(map[string]uint64) decoderData.inodeTable = make(map[string]uint64) decoderData.directoryTable = make(map[string]*filesystem.Directory) fileSystem := &decoderData.fileSystem fileSystem.RegularInodeTable = make(filesystem.RegularInodeTable) fileSystem.SymlinkInodeTable = make(filesystem.SymlinkInodeTable) fileSystem.InodeTable = make(filesystem.InodeTable) // Create a container directory for the top-level directory. var containerDir filesystem.Directory decoderData.directoryTable["/"] = &containerDir for { header, err := tarReader.Next() if err == io.EOF { break } if err != nil { return nil, err } header.Name = normaliseFilename(header.Name) if filter.Match(header.Name) { continue } err = decoderData.addHeader(tarReader, dataHandler, header) if err != nil { return nil, err } } fileSystem.Directory = *containerDir.DirectoryList[0] sortDirectory(&fileSystem.Directory) fileSystem.DirectoryCount = uint64(len(decoderData.directoryTable)) fileSystem.RebuildInodePointers() fileSystem.ComputeTotalDataBytes() return fileSystem, nil }