Beispiel #1
0
func (fs *CamliFileSystem) GetAttr(name string) (*fuse.Attr, fuse.Status) {
	if attr, ok := fs.nameToAttr.Get(name); ok {
		return attr.(*fuse.Attr), fuse.OK
	}

	blobref, errStatus := fs.blobRefFromName(name)
	if errStatus != fuse.OK {
		log.Printf("cammount: GetAttr(%q, %s): %v", name, blobref, errStatus)
		return nil, errStatus
	}

	ss, err := fs.fetchSchemaSuperset(blobref)
	if err != nil {
		log.Printf("cammount: GetAttr(%q, %s): fetch schema error: %v", name, blobref, err)
		return nil, fuse.EIO
	}

	out := new(fuse.Attr)
	var fi os.FileInfo

	fi.Mode = ss.UnixMode()

	// TODO: have a mode to set permissions equal to mounting user?
	fi.Uid = ss.UnixOwnerId
	fi.Gid = ss.UnixGroupId

	// TODO: other types
	if ss.Type == "file" {
		fi.Size = int64(ss.SumPartsSize())
	}

	fi.Mtime_ns = schema.NanosFromRFC3339(ss.UnixMtime)
	fi.Atime_ns = fi.Mtime_ns
	fi.Ctime_ns = fi.Mtime_ns
	if atime := schema.NanosFromRFC3339(ss.UnixAtime); atime > 0 {
		fi.Atime_ns = atime
	}
	if ctime := schema.NanosFromRFC3339(ss.UnixCtime); ctime > 0 {
		fi.Ctime_ns = ctime
	}

	fuse.CopyFileInfo(&fi, out)
	fs.nameToAttr.Add(name, out)
	return out, fuse.OK
}
Beispiel #2
0
func (p *Propolis) GetResponseMetaData(resp *http.Response, info *os.FileInfo) {
	// get the user id
	if line := resp.Header.Get("X-Amz-Meta-Uid"); line != "" {
		var uid int
		var username string
		// look up the symbolic name; if found, prefer that; else fall back to numeric id
		switch n, _ := fmt.Sscanf(line, "%d (%s)", &uid, &username); n {
		case 2:
			if localuid, err := user.Lookup(username); err == nil {
				uid = localuid.Uid
			}
		case 1:
		default:
			uid = 0
		}
		info.Uid = uid
	} else {
		info.Uid = 0
	}

	// get the group id
	if line := resp.Header.Get("X-Amz-Meta-Gid"); line != "" {
		var gid int
		if n, _ := fmt.Sscanf(line, "%d", &gid); n != 1 {
			gid = 0
		}
		info.Gid = gid
	} else {
		info.Gid = 0
	}

	// get permissions/file type
	var mode uint32
	if line := resp.Header.Get("X-Amz-Meta-Mode"); line != "" {

		// check for an octal value
		if n, _ := fmt.Sscanf(line, "0%o", &mode); n != 1 {
			// fallback: decimal?
			if n, _ = fmt.Sscanf(line, "%d", &mode); n != 1 {
				mode = 0
			}
		}
	}
	// no mode? try inferring type from Content-Type field
	if mode&s_ifmt == 0 {
		switch {
		case resp.Header.Get("Content-Type") == directory_mime_type:
			mode = 0755 | s_ifdir // permissions + directory
		case resp.Header.Get("Content-Type") == alt_directory_mime_type:
			mode = 0755 | s_ifdir // permissions + directory
		case resp.Header.Get("Content-Type") == symlink_mime_type:
			mode = 0777 | s_iflnk // permissions + symlink
		default:
			mode = 0644 | s_ifreg // permissions + regular file
		}
	}
	info.Mode = mode

	// get the mtime/atime/ctime
	// prefer X-Amz-Meta-Mtime header
	found := false
	var mtime int64
	if line := resp.Header.Get("X-Amz-Meta-Mtime"); line != "" {
		var sec, ns int64
		if n, _ := fmt.Sscanf(line, "%d.%d", &sec, &ns); n == 2 {
			mtime = sec*1e9 + ns
			found = true
		} else {
			if n, _ := fmt.Sscanf(line, "%d", &sec); n == 1 {
				mtime = sec * 1e9
				found = true
			}
		}
	}
	// fall back to Last-Modified
	if !found {
		when, err := time.Parse(time.RFC1123, resp.Header.Get("Last-Modified"))
		if err != nil {
			mtime = time.Nanoseconds()
		} else {
			mtime = when.Seconds() * 1e9
		}
	}
	info.Atime_ns = mtime
	info.Mtime_ns = mtime
	info.Ctime_ns = mtime

	// get the length from Content-Length
	if line := resp.Header.Get("Content-Length"); line != "" {
		var size int64
		if n, _ := fmt.Sscanf(line, "%d", &size); n == 1 {
			info.Size = size
		} else {
			info.Size = 0
		}
	}
}