diff --git a/fs/changes.go b/fs/changes.go index 9bd315ad82..659f688c45 100644 --- a/fs/changes.go +++ b/fs/changes.go @@ -125,20 +125,3 @@ func (mp *Mountpoint) Reset() error { } return nil } - -// Open opens the named file for reading. -// func (fs *Filesystem) OpenFile(path string, flag int, perm os.FileMode) (*os.File, error) { -// if err := fs.EnsureMounted(); err != nil { -// return nil, err -// } -// return os.OpenFile(filepath.Join(fs.RootFS, path), flag, perm) -// } - -// ReadDir reads the directory named by dirname, relative to the Filesystem's root, -// and returns a list of sorted directory entries -// func (fs *Filesystem) ReadDir(dirname string) ([]os.FileInfo, error) { -// if err := fs.EnsureMounted(); err != nil { -// return nil, err -// } -// return ioutil.ReadDir(filepath.Join(fs.RootFS, dirname)) -// } diff --git a/fs/store.go b/fs/store.go index 4a4b0ce808..4f4ed368e3 100644 --- a/fs/store.go +++ b/fs/store.go @@ -8,6 +8,7 @@ import ( _ "github.com/mattn/go-sqlite3" "github.com/shykes/gorp" //Forked to implement CreateTablesOpts "io" + "io/ioutil" "os" "path" "path/filepath" @@ -100,6 +101,26 @@ func (store *Store) List(pth string) ([]*Image, error) { return store.imageList(images), nil } +func (store *Store) Find(pth string) (*Image, error) { + pth = path.Clean(pth) + img, err := store.Get(pth) + if err != nil { + return nil, err + } else if img != nil { + return img, nil + } + + images, err := store.orm.Select(Image{}, "select images.* from images, paths where Path=? and paths.Image=images.Id order by images.Created desc limit 1", pth) + if err != nil { + return nil, err + } else if len(images) < 1 { + return nil, nil + } + img = images[0].(*Image) + img.store = store + return img, nil +} + func (store *Store) Get(id string) (*Image, error) { img, err := store.orm.Get(Image{}, id) if img == nil { @@ -115,6 +136,7 @@ func (store *Store) Create(layerData Archive, parent *Image, pth, comment string img := &Image{ Id: future.RandomId(), Comment: comment, + Created: time.Now().Unix(), store: store, } if parent != nil { @@ -166,6 +188,7 @@ type Image struct { Id string Parent string Comment string + Created int64 store *Store `db:"-"` } @@ -358,6 +381,23 @@ func (store *Store) FetchMountpoint(root, rw string) (*Mountpoint, error) { return mp, nil } +// OpenFile opens the named file for reading. +func (mp *Mountpoint) OpenFile(path string, flag int, perm os.FileMode) (*os.File, error) { + if err := mp.EnsureMounted(); err != nil { + return nil, err + } + return os.OpenFile(filepath.Join(mp.Root, path), flag, perm) +} + +// ReadDir reads the directory named by dirname, relative to the Mountpoint's root, +// and returns a list of sorted directory entries +func (mp *Mountpoint) ReadDir(dirname string) ([]os.FileInfo, error) { + if err := mp.EnsureMounted(); err != nil { + return nil, err + } + return ioutil.ReadDir(filepath.Join(mp.Root, dirname)) +} + func (store *Store) AddTag(imageId, tagName string) error { if image, err := store.Get(imageId); err != nil { return err diff --git a/server/server.go b/server/server.go index 91e037ca03..a2a2eada06 100644 --- a/server/server.go +++ b/server/server.go @@ -88,10 +88,18 @@ func (srv *Server) CmdWait(stdin io.ReadCloser, stdout io.Writer, args ...string // 'docker info': display system-wide information. func (srv *Server) CmdInfo(stdin io.ReadCloser, stdout io.Writer, args ...string) error { + images, _ := srv.images.Images() + var imgcount int + if images == nil { + imgcount = 0 + } else { + imgcount = len(images) + } + fmt.Fprintf(stdout, "containers: %d\nversion: %s\nimages: %d\n", len(srv.containers.List()), VERSION, - 0) // FIXME: Number of images + imgcount) return nil } @@ -210,73 +218,73 @@ func (srv *Server) CmdMount(stdin io.ReadCloser, stdout io.Writer, args ...strin return nil } -// func (srv *Server) CmdCat(stdin io.ReadCloser, stdout io.Writer, args ...string) error { -// cmd := rcli.Subcmd(stdout, "cat", "[OPTIONS] CONTAINER PATH", "write the contents of a container's file to standard output") -// if err := cmd.Parse(args); err != nil { -// cmd.Usage() -// return nil -// } -// if cmd.NArg() < 2 { -// cmd.Usage() -// return nil -// } -// name, path := cmd.Arg(0), cmd.Arg(1) -// if container := srv.containers.Get(name); container != nil { -// if f, err := container.Mountpoint.OpenFile(path, os.O_RDONLY, 0); err != nil { -// return err -// } else if _, err := io.Copy(stdout, f); err != nil { -// return err -// } -// return nil -// } -// return errors.New("No such container: " + name) -// } +func (srv *Server) CmdCat(stdin io.ReadCloser, stdout io.Writer, args ...string) error { + cmd := rcli.Subcmd(stdout, "cat", "[OPTIONS] CONTAINER PATH", "write the contents of a container's file to standard output") + if err := cmd.Parse(args); err != nil { + cmd.Usage() + return nil + } + if cmd.NArg() < 2 { + cmd.Usage() + return nil + } + name, path := cmd.Arg(0), cmd.Arg(1) + if container := srv.containers.Get(name); container != nil { + if f, err := container.Mountpoint.OpenFile(path, os.O_RDONLY, 0); err != nil { + return err + } else if _, err := io.Copy(stdout, f); err != nil { + return err + } + return nil + } + return errors.New("No such container: " + name) +} -// func (srv *Server) CmdWrite(stdin io.ReadCloser, stdout io.Writer, args ...string) error { -// cmd := rcli.Subcmd(stdout, "write", "[OPTIONS] CONTAINER PATH", "write the contents of standard input to a container's file") -// if err := cmd.Parse(args); err != nil { -// cmd.Usage() -// return nil -// } -// if cmd.NArg() < 2 { -// cmd.Usage() -// return nil -// } -// name, path := cmd.Arg(0), cmd.Arg(1) -// if container := srv.containers.Get(name); container != nil { -// if f, err := container.Mountpoint.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0600); err != nil { -// return err -// } else if _, err := io.Copy(f, stdin); err != nil { -// return err -// } -// return nil -// } -// return errors.New("No such container: " + name) -// } +func (srv *Server) CmdWrite(stdin io.ReadCloser, stdout io.Writer, args ...string) error { + cmd := rcli.Subcmd(stdout, "write", "[OPTIONS] CONTAINER PATH", "write the contents of standard input to a container's file") + if err := cmd.Parse(args); err != nil { + cmd.Usage() + return nil + } + if cmd.NArg() < 2 { + cmd.Usage() + return nil + } + name, path := cmd.Arg(0), cmd.Arg(1) + if container := srv.containers.Get(name); container != nil { + if f, err := container.Mountpoint.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0600); err != nil { + return err + } else if _, err := io.Copy(f, stdin); err != nil { + return err + } + return nil + } + return errors.New("No such container: " + name) +} -// func (srv *Server) CmdLs(stdin io.ReadCloser, stdout io.Writer, args ...string) error { -// cmd := rcli.Subcmd(stdout, "ls", "[OPTIONS] CONTAINER PATH", "List the contents of a container's directory") -// if err := cmd.Parse(args); err != nil { -// cmd.Usage() -// return nil -// } -// if cmd.NArg() < 2 { -// cmd.Usage() -// return nil -// } -// name, path := cmd.Arg(0), cmd.Arg(1) -// if container := srv.containers.Get(name); container != nil { -// if files, err := container.Mountpoint.ReadDir(path); err != nil { -// return err -// } else { -// for _, f := range files { -// fmt.Fprintln(stdout, f.Name()) -// } -// } -// return nil -// } -// return errors.New("No such container: " + name) -// } +func (srv *Server) CmdLs(stdin io.ReadCloser, stdout io.Writer, args ...string) error { + cmd := rcli.Subcmd(stdout, "ls", "[OPTIONS] CONTAINER PATH", "List the contents of a container's directory") + if err := cmd.Parse(args); err != nil { + cmd.Usage() + return nil + } + if cmd.NArg() < 2 { + cmd.Usage() + return nil + } + name, path := cmd.Arg(0), cmd.Arg(1) + if container := srv.containers.Get(name); container != nil { + if files, err := container.Mountpoint.ReadDir(path); err != nil { + return err + } else { + for _, f := range files { + fmt.Fprintln(stdout, f.Name()) + } + } + return nil + } + return errors.New("No such container: " + name) +} func (srv *Server) CmdInspect(stdin io.ReadCloser, stdout io.Writer, args ...string) error { cmd := rcli.Subcmd(stdout, "inspect", "[OPTIONS] CONTAINER", "Return low-level information on a container") @@ -484,7 +492,7 @@ func (srv *Server) CmdImages(stdin io.ReadCloser, stdout io.Writer, args ...stri for idx, field := range []string{ /* NAME */ name, /* ID */ img.Id, - /* CREATED */ future.HumanDuration(time.Now().Sub(time.Now())) + " ago", // FIXME: should be img.Created + /* CREATED */ future.HumanDuration(time.Now().Sub(time.Unix(img.Created, 0))) + " ago", /* PARENT */ img.Parent, } { if idx == 0 { @@ -827,7 +835,7 @@ func (srv *Server) CmdRun(stdin io.ReadCloser, stdout io.Writer, args ...string) cmdline = []string{"/bin/bash", "-i"} } // Find the image - img, err := srv.images.Get(name) + img, err := srv.images.Find(name) if err != nil { return err } else if img == nil {