Beispiel #1
0
func fetchFile(l *log.Logger, f types.File) ([]byte, error) {
	switch f.Contents.Source.Scheme {
	case "http":
		client := util.NewHttpClient(l)
		data, status, err := client.Get(f.Contents.Source.String())
		if err != nil {
			return nil, err
		}

		l.Debug("GET result: %s", http.StatusText(status))
		if status != http.StatusOK {
			return nil, ErrStatusBad
		}

		return data, nil
	case "data":
		url, err := dataurl.DecodeString(f.Contents.Source.String())
		if err != nil {
			return nil, err
		}

		return url.Data, nil
	default:
		return nil, ErrSchemeUnsupported
	}
}
Beispiel #2
0
func RenderFile(l *log.Logger, f types.File) *File {
	var contents []byte
	var err error

	fetch := func() error {
		contents, err = util.FetchResource(l, url.URL(f.Contents.Source))
		return err
	}

	validate := func() error {
		return util.AssertValid(f.Contents.Verification, contents)
	}

	decompress := func() error {
		contents, err = decompressFile(l, f, contents)
		return err
	}

	if l.LogOp(fetch, "fetching file %q", f.Path) != nil {
		return nil
	}
	if l.LogOp(validate, "validating file contents") != nil {
		return nil
	}
	if l.LogOp(decompress, "decompressing file contents") != nil {
		return nil
	}

	return &File{
		Path:     f.Path,
		Contents: []byte(contents),
		Mode:     os.FileMode(f.Mode),
		Uid:      f.User.Id,
		Gid:      f.Group.Id,
	}
}
Beispiel #3
0
// mountOEM waits for the presence of and mounts the oem partition at oemMountPath.
func mountOEM(l *log.Logger) error {
	dev := []string{oemDevicePath}
	if err := systemd.WaitOnDevices(dev, "oem-cmdline"); err != nil {
		l.Err("failed to wait for oem device: %v", err)
		return err
	}

	if err := os.MkdirAll(oemMountPath, 0700); err != nil {
		l.Err("failed to create oem mount point: %v", err)
		return err
	}

	if err := l.LogOp(
		func() error {
			return syscall.Mount(dev[0], oemMountPath, "ext4", 0, "")
		},
		"mounting %q at %q", oemDevicePath, oemMountPath,
	); err != nil {
		return fmt.Errorf("failed to mount device %q at %q: %v",
			oemDevicePath, oemMountPath, err)
	}

	return nil
}
Beispiel #4
0
// FetchResource fetches a resource given a URL. The supported schemes are http, data, and oem.
func FetchResource(l *log.Logger, u url.URL) ([]byte, error) {
	switch u.Scheme {
	case "http", "https":
		client := NewHttpClient(l)
		data, status, err := client.Get(u.String())
		if err != nil {
			return nil, err
		}

		l.Debug("GET result: %s", http.StatusText(status))
		switch status {
		case http.StatusOK, http.StatusNoContent:
			return data, nil
		case http.StatusNotFound:
			return nil, ErrNotFound
		default:
			return nil, ErrFailed
		}

	case "data":
		url, err := dataurl.DecodeString(u.String())
		if err != nil {
			return nil, err
		}

		return url.Data, nil

	case "oem":
		path := filepath.Clean(u.Path)
		if !filepath.IsAbs(path) {
			l.Err("oem path is not absolute: %q", u.Path)
			return nil, ErrPathNotAbsolute
		}

		// check if present under oemDirPath, if so use it.
		absPath := filepath.Join(oemDirPath, path)
		data, err := ioutil.ReadFile(absPath)
		if os.IsNotExist(err) {
			l.Info("oem config not found in %q, trying %q",
				oemDirPath, oemMountPath)

			// try oemMountPath, requires mounting it.
			err := mountOEM(l)
			if err != nil {
				l.Err("failed to mount oem partition: %v", err)
				return nil, ErrFailed
			}

			absPath := filepath.Join(oemMountPath, path)
			data, err = ioutil.ReadFile(absPath)
			umountOEM(l)
		} else if err != nil {
			l.Err("failed to read oem config: %v", err)
			return nil, ErrFailed
		}

		return data, nil

	default:
		return nil, ErrSchemeUnsupported
	}
}
Beispiel #5
0
// umountOEM unmounts the oem partition at oemMountPath.
func umountOEM(l *log.Logger) {
	l.LogOp(
		func() error { return syscall.Unmount(oemMountPath, 0) },
		"unmounting %q", oemMountPath,
	)
}