func addPackageDesktopFiles(s *snap.Info) error { if err := os.MkdirAll(dirs.SnapDesktopFilesDir, 0755); err != nil { return err } baseDir := s.MountDir() desktopFiles, err := filepath.Glob(filepath.Join(baseDir, "meta", "gui", "*.desktop")) if err != nil { return fmt.Errorf("cannot get desktop files for %v: %s", baseDir, err) } for _, df := range desktopFiles { content, err := ioutil.ReadFile(df) if err != nil { return err } realBaseDir := stripGlobalRootDir(baseDir) content = sanitizeDesktopFile(s, realBaseDir, content) installedDesktopFileName := filepath.Join(dirs.SnapDesktopFilesDir, fmt.Sprintf("%s_%s", s.Name(), filepath.Base(df))) if err := osutil.AtomicWriteFile(installedDesktopFileName, []byte(content), 0755, 0); err != nil { return err } } return nil }
func enableFirstEther() error { gadget, _ := getGadget() if gadget != nil && gadget.Legacy.Gadget.SkipIfupProvisioning { return nil } var eths []string for _, glob := range globs { eths, _ = filepath.Glob(glob) if len(eths) != 0 { break } } if len(eths) == 0 { return nil } eth := filepath.Base(eths[0]) ethfile := filepath.Join(ethdir, eth) data := fmt.Sprintf("allow-hotplug %[1]s\niface %[1]s inet dhcp\n", eth) if err := osutil.AtomicWriteFile(ethfile, []byte(data), 0644, 0); err != nil { return err } ifup := exec.Command(ifup, eth) ifup.Stdout = os.Stdout ifup.Stderr = os.Stderr if err := ifup.Run(); err != nil { return err } return nil }
func addPackageBinaries(s *snap.Info) error { if err := os.MkdirAll(dirs.SnapBinariesDir, 0755); err != nil { return err } baseDir := s.MountDir() for _, app := range s.Apps { if app.Daemon != "" { continue } // this will remove the global base dir when generating the // service file, this ensures that /snap/foo/1.0/bin/start // is in the service file when the SetRoot() option // is used realBaseDir := stripGlobalRootDir(baseDir) content, err := generateSnapBinaryWrapper(app, realBaseDir) if err != nil { return err } if err := osutil.AtomicWriteFile(app.WrapperPath(), []byte(content), 0755, 0); err != nil { return err } } return nil }
// writeAuthData saves authentication details for later reuse through ReadAuthData func writeAuthData(user User) error { targetFile := storeAuthDataFilename() if err := os.MkdirAll(filepath.Dir(targetFile), 0700); err != nil { return err } outStr, err := json.Marshal(user) if err != nil { return nil } return osutil.AtomicWriteFile(targetFile, []byte(outStr), 0600, 0) }
func stampFirstBoot() error { // filepath.Dir instead of firstbootDir directly to ease testing stampDir := filepath.Dir(stampFile) if _, err := os.Stat(stampDir); os.IsNotExist(err) { if err := os.MkdirAll(stampDir, 0755); err != nil { return err } } return osutil.AtomicWriteFile(stampFile, []byte{}, 0644, 0) }
func atomicWriteEntry(data []byte, secret bool, top string, subpath ...string) error { fpath := filepath.Join(top, filepath.Join(subpath...)) dir := filepath.Dir(fpath) err := os.MkdirAll(dir, 0775) if err != nil { return err } fperm := 0664 if secret { fperm = 0600 } return osutil.AtomicWriteFile(fpath, data, os.FileMode(fperm), 0) }
// writeApparmorAdditionalFile generate a $partID.json.additional file. // // This file grants additional access on top of the existing apparmor json // rules. This is required for the Gadget hardware assign code because by // default apparmor will not allow access to /dev. We grant access here // and the ubuntu-core-launcher is then used to generate a confinement // based on the devices cgroup. func writeApparmorAdditionalFile(s *snap.Info) error { if err := os.MkdirAll(dirs.SnapAppArmorDir, 0755); err != nil { return err } for _, h := range s.Legacy.Gadget.Hardware.Assign { jsonAdditionalPath := filepath.Join(dirs.SnapAppArmorDir, fmt.Sprintf("%s.json.additional", h.PartID)) if err := osutil.AtomicWriteFile(jsonAdditionalPath, []byte(apparmorAdditionalContent), 0644, 0); err != nil { return err } } return nil }
func setPassthrough(rootDir string, pc []passthroughConfig) error { for _, c := range pc { path := filepath.Join(rootDir, c.Name) if c.Content == "" { os.Remove(path) continue } if err := osutil.AtomicWriteFile(path, []byte(c.Content), 0644, osutil.AtomicWriteFollow); err != nil { return err } } return nil }
func (s *systemd) WriteMountUnitFile(name, what, where string) (string, error) { c := fmt.Sprintf(`[Unit] Description=Squashfs mount unit for %s [Mount] What=%s Where=%s [Install] WantedBy=multi-user.target `, name, what, where) mu := MountUnitPath(where, "mount") return filepath.Base(mu), osutil.AtomicWriteFile(mu, []byte(c), 0644, 0) }
func setModules(modules []string) error { oldModules, err := getModules() if err != nil { return err } for i := range modules { m := strings.TrimSpace(modules[i]) if len(m) == 0 { continue } if m[0] == '-' { m = m[1:] idx := sort.SearchStrings(oldModules, m) if idx == len(oldModules) || oldModules[idx] != m { // not found continue } oldModules = append(oldModules[:idx], oldModules[idx+1:]...) } else { idx := sort.SearchStrings(oldModules, m) if idx < len(oldModules) && oldModules[idx] == m { // already got it continue } oldModules = append(oldModules, "") copy(oldModules[idx+1:], oldModules[idx:]) oldModules[idx] = m } } var buf bytes.Buffer // bytes' Write* methods always return nil error buf.WriteString(modulesHeader) for i := range oldModules { buf.WriteString(oldModules[i]) buf.WriteByte('\n') } return osutil.AtomicWriteFile(modulesPath, buf.Bytes(), 0644, osutil.AtomicWriteFollow) }
// SaveManifest saves the manifest at the designated location for the snap containing information not in the snap.yaml. func SaveManifest(rsnap *snap.Info) error { if rsnap.Revision == 0 { return fmt.Errorf("internal error: should not be storring manifests for sideloaded snaps") } // XXX: we store OfficialName though it may not be the blessed one later content, err := yaml.Marshal(&rsnap.SideInfo) if err != nil { return err } if err := os.MkdirAll(dirs.SnapMetaDir, 0755); err != nil { return err } p := manifestPath(rsnap.Name(), rsnap.Revision) // don't worry about previous contents return osutil.AtomicWriteFile(p, content, 0644, 0) }
func writeGadgetHardwareUdevRules(s *snap.Info) error { os.MkdirAll(dirs.SnapUdevRulesDir, 0755) // cleanup if err := cleanupGadgetHardwareUdevRules(s); err != nil { return err } // write new files for _, h := range s.Legacy.Gadget.Hardware.Assign { rulesContent, err := generateUdevRuleContent(&h) if err != nil { return err } outfile := filepath.Join(dirs.SnapUdevRulesDir, fmt.Sprintf("80-snappy_%s_%s.rules", s.Name(), h.PartID)) if err := osutil.AtomicWriteFile(outfile, []byte(rulesContent), 0644, 0); err != nil { return err } } return nil }
func addPackageServices(s *snap.Info, inter interacter) error { baseDir := s.MountDir() for _, app := range s.Apps { if app.Daemon == "" { continue } // this will remove the global base dir when generating the // service file, this ensures that /snap/foo/1.0/bin/start // is in the service file when the SetRoot() option // is used realBaseDir := stripGlobalRootDir(baseDir) // Generate service file content, err := generateSnapServicesFile(app, realBaseDir) if err != nil { return err } svcFilePath := app.ServiceFile() os.MkdirAll(filepath.Dir(svcFilePath), 0755) if err := osutil.AtomicWriteFile(svcFilePath, []byte(content), 0644, 0); err != nil { return err } // Generate systemd socket file if needed if app.Socket { content, err := generateSnapSocketFile(app, realBaseDir) if err != nil { return err } svcSocketFilePath := app.ServiceSocketFile() os.MkdirAll(filepath.Dir(svcSocketFilePath), 0755) if err := osutil.AtomicWriteFile(svcSocketFilePath, []byte(content), 0644, 0); err != nil { return err } } // daemon-reload and enable plus start serviceName := filepath.Base(app.ServiceFile()) sysd := systemd.New(dirs.GlobalRootDir, inter) if err := sysd.DaemonReload(); err != nil { return err } // enable the service if err := sysd.Enable(serviceName); err != nil { return err } if err := sysd.Start(serviceName); err != nil { return err } if app.Socket { socketName := filepath.Base(app.ServiceSocketFile()) // enable the socket if err := sysd.Enable(socketName); err != nil { return err } if err := sysd.Start(socketName); err != nil { return err } } } return nil }
func (osb *overlordStateBackend) Checkpoint(data []byte) error { return osutil.AtomicWriteFile(osb.path, data, 0600, 0) }
tz, err := ioutil.ReadFile(tzFile()) if err != nil { return "", err } return strings.TrimSpace(string(tz)), nil } // setTimezone sets the specified timezone for the system, an error is returned // if it can't. var setTimezone = func(timezone string) error { if err := osutil.CopyFile(filepath.Join(tzZoneInfoPath, timezone), tzZoneInfoTarget, osutil.CopyFlagOverwrite); err != nil { return err } return osutil.AtomicWriteFile(tzFile(), []byte(timezone), 0644, osutil.AtomicWriteFollow) } func getPassthrough(rootDir string) (pc []passthroughConfig, err error) { filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error { if info.IsDir() { return nil } content, err := ioutil.ReadFile(path) if err != nil { return err } pc = append(pc, passthroughConfig{ Name: path[len(rootDir):], Content: string(content), })