func writeImage(fs *filesystem.FileSystem) (string, error) { file, err := ioutil.TempFile("", "imagetool") if err != nil { return "", err } defer file.Close() writer := bufio.NewWriter(file) defer writer.Flush() return file.Name(), fs.List(writer) }
func applyDeleteFilter(fs *filesystem.FileSystem) ( *filesystem.FileSystem, error) { if *deleteFilter == "" { return fs, nil } filter, err := filter.Load(*deleteFilter) if err != nil { return nil, err } return fs.Filter(filter), nil }
func readFileSystem(name string) (*filesystem.FileSystem, error) { file, err := os.Open(name) if err != nil { return nil, err } defer file.Close() var fileSystem filesystem.FileSystem if err := gob.NewDecoder(file).Decode(&fileSystem); err != nil { return nil, err } fileSystem.RebuildInodePointers() return &fileSystem, nil }
func deleteUnneededFiles(srpcClient *srpc.Client, subFS *filesystem.FileSystem, imgFS *filesystem.FileSystem, logger *log.Logger) bool { startTime := showStart("compute early files to delete") pathsToDelete := make([]string, 0) imgHashToInodesTable := imgFS.HashToInodesTable() imgFilenameToInodeTable := imgFS.FilenameToInodeTable() for pathname, inum := range subFS.FilenameToInodeTable() { if inode, ok := subFS.InodeTable[inum].(*filesystem.RegularInode); ok { if inode.Size > 0 { if _, ok := imgHashToInodesTable[inode.Hash]; !ok { pathsToDelete = append(pathsToDelete, pathname) } } else { if _, ok := imgFilenameToInodeTable[pathname]; !ok { pathsToDelete = append(pathsToDelete, pathname) } } } } showTimeTaken(startTime) if len(pathsToDelete) < 1 { return false } updateRequest := sub.UpdateRequest{ Wait: true, PathsToDelete: pathsToDelete} var updateReply sub.UpdateResponse startTime = showStart("Subd.Update() for early files to delete") err := client.CallUpdate(srpcClient, updateRequest, &updateReply) showTimeTaken(startTime) if err != nil { logger.Println(err) } return true }
func layerImages(baseFS *filesystem.FileSystem, layerFS *filesystem.FileSystem) error { for filename, layerInum := range layerFS.FilenameToInodeTable() { layerInode := layerFS.InodeTable[layerInum] if _, ok := layerInode.(*filesystem.DirectoryInode); ok { continue } baseInum, ok := baseFS.FilenameToInodeTable()[filename] if !ok { return errors.New(filename + " missing in base image") } baseInode := baseFS.InodeTable[baseInum] sameType, sameMetadata, sameData := filesystem.CompareInodes(baseInode, layerInode, nil) if !sameType { return errors.New(filename + " changed type") } if sameMetadata && sameData { continue } baseFS.InodeTable[baseInum] = layerInode } return nil }
func spliceComputedFiles(fs *filesystem.FileSystem) error { if *computedFiles == "" { return nil } computedFileList, err := loadComputedFiles(*computedFiles) if err != nil { return errors.New("cannot load computed files list from: " + *computedFiles + ": " + err.Error()) } filenameToInodeTable := fs.FilenameToInodeTable() inodeToFilenamesTable := fs.InodeToFilenamesTable() for _, computedFile := range computedFileList { inum, ok := filenameToInodeTable[computedFile.Filename] if !ok { return errors.New(computedFile.Filename + ": missing from image") } if filenames, ok := inodeToFilenamesTable[inum]; !ok { panic(computedFile.Filename + ": no corresponding list of files") } else if len(filenames) != 1 { return fmt.Errorf("%s: multiple inodes: %d", computedFile.Filename, len(filenames)) } if inode, ok := fs.InodeTable[inum].(*filesystem.ComputedRegularInode); ok { inode.Source = computedFile.Source continue } if oldInode, ok := fs.InodeTable[inum].(*filesystem.RegularInode); !ok { return fmt.Errorf("%s: type: %T is not a regular inode", computedFile.Filename, fs.InodeTable[inum]) } else { newInode := new(filesystem.ComputedRegularInode) newInode.Mode = oldInode.Mode newInode.Uid = oldInode.Uid newInode.Gid = oldInode.Gid newInode.Source = computedFile.Source fs.InodeTable[inum] = newInode } } fs.ComputeTotalDataBytes() clearInodePointers(&fs.DirectoryInode, "") return fs.RebuildInodePointers() }
func copyMissingObjects(fs *filesystem.FileSystem, imageSClient *srpc.Client, objectClient *objectclient.ObjectClient, subName string) error { // Check to see which objects are in the objectserver. hashes := make([]hash.Hash, 0, fs.NumRegularInodes) for hash, _ := range fs.HashToInodesTable() { hashes = append(hashes, hash) } objectSizes, err := objectClient.CheckObjects(hashes) if err != nil { return err } missingHashes := make([]hash.Hash, 0) for index, size := range objectSizes { if size < 1 { missingHashes = append(missingHashes, hashes[index]) } } if len(missingHashes) < 1 { return nil } // Get missing objects from sub. filesForMissingObjects := make([]string, 0, len(missingHashes)) for _, hash := range missingHashes { if inums, ok := fs.HashToInodesTable()[hash]; !ok { return fmt.Errorf("no inode for object: %x", hash) } else if files, ok := fs.InodeToFilenamesTable()[inums[0]]; !ok { return fmt.Errorf("no file for inode: %d", inums[0]) } else { filesForMissingObjects = append(filesForMissingObjects, files[0]) } } objAdderQueue, err := objectclient.NewObjectAdderQueue(imageSClient) if err != nil { return err } subClient, err := srpc.DialHTTP("tcp", fmt.Sprintf("%s:%d", subName, constants.SubPortNumber), 0) if err != nil { return fmt.Errorf("error dialing %s", err) } defer subClient.Close() if err := subclient.GetFiles(subClient, filesForMissingObjects, func(reader io.Reader, size uint64) error { _, err := objAdderQueue.Add(reader, size) return err }); err != nil { return err } return objAdderQueue.Close() }