// containerStatPath stats the filesystem resource at the specified path in this // container. Returns stat info about the resource. func (daemon *Daemon) containerStatPath(container *container.Container, path string) (stat *types.ContainerPathStat, err error) { container.Lock() defer container.Unlock() if err = daemon.Mount(container); err != nil { return nil, err } defer daemon.Unmount(container) err = daemon.mountVolumes(container) defer container.UnmountVolumes(true, daemon.LogVolumeEvent) if err != nil { return nil, err } resolvedPath, absPath, err := container.ResolvePath(path) if err != nil { return nil, err } return container.StatPath(resolvedPath, absPath) }
// containerArchivePath creates an archive of the filesystem resource at the specified // path in this container. Returns a tar archive of the resource and stat info // about the resource. func (daemon *Daemon) containerArchivePath(container *container.Container, path string) (content io.ReadCloser, stat *types.ContainerPathStat, err error) { container.Lock() defer func() { if err != nil { // Wait to unlock the container until the archive is fully read // (see the ReadCloseWrapper func below) or if there is an error // before that occurs. container.Unlock() } }() if err = daemon.Mount(container); err != nil { return nil, nil, err } defer func() { if err != nil { // unmount any volumes container.UnmountVolumes(true, daemon.LogVolumeEvent) // unmount the container's rootfs daemon.Unmount(container) } }() if err = daemon.mountVolumes(container); err != nil { return nil, nil, err } resolvedPath, absPath, err := container.ResolvePath(path) if err != nil { return nil, nil, err } stat, err = container.StatPath(resolvedPath, absPath) if err != nil { return nil, nil, err } // We need to rebase the archive entries if the last element of the // resolved path was a symlink that was evaluated and is now different // than the requested path. For example, if the given path was "/foo/bar/", // but it resolved to "/var/lib/docker/containers/{id}/foo/baz/", we want // to ensure that the archive entries start with "bar" and not "baz". This // also catches the case when the root directory of the container is // requested: we want the archive entries to start with "/" and not the // container ID. data, err := archive.TarResourceRebase(resolvedPath, filepath.Base(absPath)) if err != nil { return nil, nil, err } content = ioutils.NewReadCloserWrapper(data, func() error { err := data.Close() container.UnmountVolumes(true, daemon.LogVolumeEvent) daemon.Unmount(container) container.Unlock() return err }) daemon.LogContainerEvent(container, "archive-path") return content, stat, nil }