func (f *fs) handleCreate(r *fuse.CreateRequest) { log.Println("Inside handleCreate") log.Println(r) resp := &fuse.CreateResponse{} c, err := f.rpc.api.Create(f.getContext(), &pb.CreateRequest{Parent: uint64(r.Node), Name: r.Name, Attr: &pb.Attr{Uid: r.Uid, Gid: r.Gid, Mode: uint32(r.Mode)}}) if err != nil { log.Fatalf("Failed to create file: %v", err) } resp.Node = fuse.NodeID(c.Attr.Inode) copyAttr(&resp.Attr, c.Attr) resp.EntryValid = 5 * time.Second resp.Attr.Valid = 5 * time.Second copyAttr(&resp.LookupResponse.Attr, c.Attr) resp.LookupResponse.EntryValid = 5 * time.Second resp.LookupResponse.Attr.Valid = 5 * time.Second r.Respond(resp) }
// Creates a regular file in dir with the attributes supplied in req func (dir *Directory) Create(req *fuse.CreateRequest, resp *fuse.CreateResponse, intr fs.Intr) (fs.Node, fs.Handle, fuse.Error) { if strings.Contains(req.Name, "@") { return nil, nil, fuse.EPERM } filesystem.Lock(dir) defer filesystem.Unlock(dir) util.P_out(req.String()) rval := new(File) rval.InitFile(req.Name, req.Mode, dir) rval.Attrs.Gid = req.Gid rval.Attrs.Uid = req.Uid dir.setChild(rval) resp.Attr = rval.Attr() resp.Node = fuse.NodeID(rval.Attr().Inode) rval.dirty = true dir.dirty = true return rval, rval, nil }
// Create file in drive, allocate kernel filehandle for writes func (sc *serveConn) create(req *fuse.CreateRequest) { if *readOnly && !req.Flags.IsReadOnly() { req.RespondError(fuse.EPERM) return } pInode := uint64(req.Header.Node) parent, err := sc.db.FileByInode(pInode) if err != nil { debug.Printf("failed to get parent file: %v", err) req.RespondError(fuse.EIO) return } p := &drive.ParentReference{Id: parent.Id} f := &drive.File{Title: req.Name} f.Parents = []*drive.ParentReference{p} f, err = sc.service.Files.Insert(f).Do() if err != nil { debug.Printf("Files.Insert(f).Do(): %v", err) req.RespondError(fuse.EIO) return } inode, err := sc.db.InodeForFileId(f.Id) if err != nil { debug.Printf("failed creating inode for %v: %v", req.Name, err) req.RespondError(fuse.EIO) return } r, w := io.Pipe() // plumbing between WriteRequest and Drive h := sc.allocHandle(fuse.NodeID(inode), w) go sc.updateInDrive(f, r) // Tell fuse and the OS about the file df, err := sc.db.UpdateFile(nil, f) if err != nil { debug.Printf("failed to update levelDB for %v: %v", f.Id, err) // The write has happened to drive, but we failed to update the kernel. // The Changes API will update Fuse, and when the kernel metadata for // the parent directory expires, the new file will become visible. req.RespondError(fuse.EIO) return } resp := fuse.CreateResponse{ // describes the opened handle OpenResponse: fuse.OpenResponse{ Handle: fuse.HandleID(h), Flags: fuse.OpenNonSeekable, }, // describes the created file LookupResponse: fuse.LookupResponse{ Node: fuse.NodeID(inode), EntryValid: *driveMetadataLatency, Attr: sc.attrFromFile(*df), }, } fuse.Debug(fmt.Sprintf("Create(%v in %v): %+v", req.Name, parent.Title, resp)) req.Respond(&resp) }