Ejemplo n.º 1
0
func rename(oldname, newname string) error {
	e := syscall.Rename(oldname, newname)
	if e != nil {
		return &LinkError{"rename", oldname, newname, e}
	}
	return nil
}
Ejemplo n.º 2
0
func movePkg(pkg *archPkg) os.Error {
	filename := fmt.Sprintf("%s-%s-%s.%s", pkg.Name, pkg.Version, pkg.Arch, pkg.Ext)
	srcPath := fmt.Sprintf("%s/%s", *cachePath, filename)

	/* try to rename, first */
	errno := syscall.Rename(srcPath, fmt.Sprintf("%s/%s", *destPath, filename))

	switch errno {
	case syscall.EXDEV:
		src, err := os.Open(srcPath, os.O_RDONLY, 0666)
		if err != nil {
			fmt.Fprintf(os.Stderr, "%s: %s\n", os.Args[0], err.String())
			os.Exit(1)
		}
		defer src.Close()

		sfi, err := src.Stat()

		dst, err := os.Open(fmt.Sprintf("%s/%s", *destPath, filename), os.O_WRONLY|os.O_CREAT|os.O_TRUNC, sfi.Permission())
		if err != nil {
			fmt.Fprintf(os.Stderr, "%s: %s\n", os.Args[0], err.String())
			os.Exit(1)
		}
		defer dst.Close()

		err = copyFile(src, bufio.NewWriter(dst))
		if err == nil {
			return os.Remove(srcPath)
		}
		return err /* different from err outside if */
	}

	return os.Errno(errno)
}
Ejemplo n.º 3
0
func ObjDeleteHandler(writer http.ResponseWriter, request *http.Request, vars map[string]string, config ServerConfig) {
	hash_dir := ObjHashDir(vars, config)

	if os.MkdirAll(hash_dir, 0770) != nil {
		ErrorResponse(writer, 500)
		return
	}
	file_name := fmt.Sprintf("%s/%s.ts", hash_dir, request.Header.Get("X-Timestamp"))
	data_file := PrimaryFile(hash_dir)
	temp_file, err := ioutil.TempFile(ObjTempDir(vars, config), "PUT")
	if err != nil {
		ErrorResponse(writer, 500)
		return
	}
	defer temp_file.Close()
	metadata := make(map[string]interface{})
	metadata["X-Timestamp"] = request.Header.Get("X-Timestamp")
	metadata["name"] = fmt.Sprintf("/%s/%s/%s", vars["account"], vars["container"], vars["obj"])
	WriteMetadata(int(temp_file.Fd()), metadata)

	syscall.Fsync(int(temp_file.Fd()))
	syscall.Rename(temp_file.Name(), file_name)
	UpdateContainer("DELETE", metadata, request, vars)
	go CleanupHashDir(hash_dir)
	go InvalidateHash(hash_dir)
	if !strings.HasSuffix(data_file, ".data") {
		ErrorResponse(writer, 404)
	} else {
		ErrorResponse(writer, 204)
	}
}
Ejemplo n.º 4
0
// Poor man's Renameat
func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
	chdirMutex.Lock()
	defer chdirMutex.Unlock()
	// Unless both paths are absolute we have to save the old working dir and
	// Chdir(oldWd) back to it in the end. If we error out before the first
	// chdir, Chdir(oldWd) is unneccassary but does no harm.
	if !filepath.IsAbs(oldpath) || !filepath.IsAbs(newpath) {
		oldWd, err := os.Getwd()
		if err != nil {
			return err
		}
		defer os.Chdir(oldWd)
	}
	// Make oldpath absolute
	oldpath, err = dirfdAbs(olddirfd, oldpath)
	if err != nil {
		return err
	}
	// Make newpath absolute
	newpath, err = dirfdAbs(newdirfd, newpath)
	if err != nil {
		return err
	}
	return syscall.Rename(oldpath, newpath)
}
Ejemplo n.º 5
0
// Rename renames a file.
func Rename(oldname, newname string) Error {
	e := syscall.Rename(oldname, newname)
	if e != 0 {
		return &LinkError{"rename", oldname, newname, Errno(e)}
	}
	return nil
}
Ejemplo n.º 6
0
func rename(oldname, newname string) error {
	fi, err := Lstat(newname)
	if err == nil && fi.IsDir() {
		return &LinkError{"rename", oldname, newname, syscall.EEXIST}
	}
	e := syscall.Rename(oldname, newname)
	if e != nil {
		return &LinkError{"rename", oldname, newname, e}
	}
	return nil
}
Ejemplo n.º 7
0
func ObjPutHandler(writer http.ResponseWriter, request *http.Request, vars map[string]string, config ServerConfig) {
	out_headers := writer.Header()
	hash_dir := ObjHashDir(vars, config)

	if os.MkdirAll(hash_dir, 0770) != nil || os.MkdirAll(ObjTempDir(vars, config), 0770) != nil {
		ErrorResponse(writer, 500)
		return
	}
	file_name := fmt.Sprintf("%s/%s.data", hash_dir, request.Header.Get("X-Timestamp"))
	temp_file, err := ioutil.TempFile(ObjTempDir(vars, config), "PUT")
	if err != nil {
		ErrorResponse(writer, 500)
		return
	}
	defer temp_file.Close()
	metadata := make(map[string]interface{})
	metadata["name"] = fmt.Sprintf("/%s/%s/%s", vars["account"], vars["container"], vars["obj"])
	metadata["X-Timestamp"] = request.Header.Get("X-Timestamp")
	metadata["Content-Type"] = request.Header.Get("Content-Type")
	var chunk [65536]byte
	total_size := uint64(0)
	hash := md5.New()
	for {
		read_len, err := request.Body.Read(chunk[0:len(chunk)])
		if err != nil || read_len <= 0 {
			break
		}
		total_size += uint64(read_len)
		hash.Write(chunk[0:read_len])
		temp_file.Write(chunk[0:read_len])
	}
	metadata["Content-Length"] = strconv.FormatUint(total_size, 10)
	metadata["ETag"] = fmt.Sprintf("%x", hash.Sum(nil))
	request_etag := request.Header.Get("ETag")
	if request_etag != "" && request_etag != metadata["ETag"].(string) {
		ErrorResponse(writer, 422)
		return
	}
	for key := range request.Header {
		if strings.HasPrefix(key, "X-Object-") {
			metadata[key] = request.Header.Get(key)
		}
	}
	out_headers.Set("ETag", metadata["ETag"].(string))
	WriteMetadata(int(temp_file.Fd()), metadata)

	syscall.Fsync(int(temp_file.Fd()))
	syscall.Rename(temp_file.Name(), file_name)
	UpdateContainer("PUT", metadata, request, vars)
	go CleanupHashDir(hash_dir)
	go InvalidateHash(hash_dir)
	ErrorResponse(writer, 201)
}
Ejemplo n.º 8
0
// Create and rename a file
func testRename(t *testing.T, plainDir string) {
	file1 := plainDir + "rename1"
	file2 := plainDir + "rename2"
	err := ioutil.WriteFile(file1, []byte("content"), 0777)
	if err != nil {
		t.Fatal(err)
	}
	err = syscall.Rename(file1, file2)
	if err != nil {
		t.Fatal(err)
	}
	syscall.Unlink(file2)
}
Ejemplo n.º 9
0
func (c *Host) updateWinHost() string {
	new := c.createNewHost()
	path := os.Getenv("SystemRoot")
	old := path + `\System32\drivers\etc\hosts`

	newFile := utf16.Encode([]rune(new + "\x00"))
	oldFile := utf16.Encode([]rune(old + "\x00"))

	syscall.Rename(old, old+time.Now().Format("-2006-01-02-15-04-05")+".bak")
	err := syscall.MoveFile(&newFile[0], &oldFile[0])
	fmt.Println(err)
	time.Sleep(time.Second * 10)

	return ""
}
Ejemplo n.º 10
0
// Import imports the source file into diskv under the destination key. If the
// destination key already exists, it's overwritten. If move is true, the
// source file is removed after a successful import.
func (d *Diskv) Import(srcFilename, dstKey string, move bool) (err error) {
	if dstKey == "" {
		return errEmptyKey
	}

	if fi, err := os.Stat(srcFilename); err != nil {
		return err
	} else if fi.IsDir() {
		return errImportDirectory
	}

	d.mu.Lock()
	defer d.mu.Unlock()

	if err := d.ensurePathWithLock(dstKey); err != nil {
		return fmt.Errorf("ensure path: %s", err)
	}

	if move {
		if err := syscall.Rename(srcFilename, d.completeFilename(dstKey)); err == nil {
			d.bustCacheWithLock(dstKey)
			return nil
		} else if err != syscall.EXDEV {
			// If it failed due to being on a different device, fall back to copying
			return err
		}
	}

	f, err := os.Open(srcFilename)
	if err != nil {
		return err
	}
	defer f.Close()
	err = d.writeStreamWithLock(dstKey, f, false)
	if err == nil && move {
		err = os.Remove(srcFilename)
	}
	return err
}
Ejemplo n.º 11
0
func WriteFileAtomic(filename string, data []byte, perm os.FileMode) error {
	partDir := filepath.Dir(filename)
	tmpFile, err := ioutil.TempFile(partDir, ".tmp-o-file")
	if err != nil {
		return err
	}
	defer tmpFile.Close()
	defer os.RemoveAll(tmpFile.Name())
	if err = tmpFile.Chmod(perm); err != nil {
		return err
	}
	if _, err = tmpFile.Write(data); err != nil {
		return err
	}
	if err = tmpFile.Sync(); err != nil {
		return err
	}
	if err = syscall.Rename(tmpFile.Name(), filename); err != nil {
		return err
	}
	return nil
}
Ejemplo n.º 12
0
func (file *File) rename(
	fs *Fs,
	orig_path string,
	new_path string) error {

	fs.filesLock.Lock()
	defer fs.filesLock.Unlock()

	other_file, ok := fs.files[new_path]
	if ok && other_file.exists() {
		return Eexist
	}

	// Drop the original reference.
	// (We've not replaced it atomically).
	if other_file != nil {
		defer other_file.DecRef(fs, "")
	}

	if file.write_exists && file.write_deleted {
		// Is it just marked deleted?
		err := file.unlink()
		if err != nil {
			return err
		}
	}

	// Try the rename.
	orig_read_path := file.read_path
	orig_write_path := file.write_path
	file.findPaths(fs, new_path)
	err := syscall.Rename(orig_write_path, file.write_path)
	if err != nil {
		if err == syscall.EXDEV {
			// TODO: The file cannot be renamed across file system.
			// This is a simple matter of copying the file across when
			// this happens. For now, we just return not implemented.
			err = Enotimpl
		}

		file.read_path = orig_read_path
		file.write_path = orig_write_path
		return err
	}

	// We've moved this file.
	// It didn't exist a moment ago, but it does now.
	file.write_exists = true
	file.write_deleted = false

	// Update our fids.
	// This is a bit messy, but since we are
	// holding a writeLock on this file, this
	// atomic should be reasonably atomic.
	for _, fid := range fs.Pool {
		if fid.file == file {
			fid.Path = new_path
		} else if other_file != nil && fid.file == other_file {
			// Since we hold at least one reference
			// to other_file, this should never trigger
			// a full cleanup of other_file. It's safe
			// to call DecRef here while locking the lock.
			file.IncRef(fs)
			fid.file = file
			other_file.DecRef(fs, "")
		}
	}

	// Perform the swaperoo.
	fs.files[new_path] = file
	delete(fs.files, orig_path)

	// Ensure the original file is deleted.
	// This is done at the very end, since there's
	// really nothing we can do at this point. We
	// even explicitly ignore the result. Ugh.
	setdelattr(orig_write_path)

	return nil
}
Ejemplo n.º 13
0
func Handler(c http.ResponseWriter, r *http.Request) {

	c.Header().Set("Content-Type", "application/json")

	api_key := r.FormValue("api_key")
	//base_url := r.FormValue("base_url")

	if api_key != Cfg.ApiKey {
		write(c, jsonError("failed", "Invalid api key"))
		return
	}

	requested_url := r.FormValue("u")
	if requested_url == "" {

		r.ParseForm()
		file_name := r.FormValue("file_name")

		if file_name == "" {
			write(c, jsonError("failed", "no `file_name` parameter"))
			return
		}

		fmt.Printf("file_name: %v\n", file_name)

		file, err := r.MultipartReader()
		if err != nil {
			write(c, jsonError("failed", "cannot get multipart reader"))
			return
		}

		part, err := file.NextPart()
		if err != nil {
			write(c, jsonError("failed", "no `u` nor `file`"))
			return
		}
		var data [1000]byte
		var i int = 0
		var data_size int64 = 0
		md5ed := hmac.NewMD5([]byte("cdnized-2194"))
		abs_path := "/tmp/" + RandStrings(100)
		dst_file, err := os.OpenFile(abs_path, os.O_WRONLY|os.O_CREATE, 0755)
		if err != nil {
			anlog.Error("Cannot create file `%s`. error: %s\n", abs_path, err.String())
			write(c, jsonError("failed", fmt.Sprintf("cannot create temporary data. %v\n", err)))
			return
		}

		for data_size < r.ContentLength {
			i, err = part.Read(data[0:999])
			if err != nil {
				break
			}

			_, err := md5ed.Write(data[0:i])
			if err != nil {
				anlog.Error("Cannot calculate MD5 hash")
				write(c, jsonError("failed", "cannot calculate checksum"))
				break
			}

			_, err = dst_file.Write(data[0:i])
			if err != nil {
				anlog.Error("Cannot write %d bytes data in file `%s`. error: %s\n", data_size, abs_path, err.String())
			}

			data_size += int64(i)
		}

		dst_file.Close()

		//fmt.Printf("content-length: %v, file: %v, file-length: %v, i: %v\n", r.ContentLength, string(data[0:]), i, i)

		hash := fmt.Sprintf("%x", md5ed.Sum())
		file_ext := path.Ext(file_name)
		file_name = hash + RandStrings(9) + file_ext
		new_path, err := os.Getwd()

		new_path = path.Join(new_path, Cfg.StoreDir[2:], Cfg.ApiStorePrefix, file_name)

		if err != nil {
			anlog.Error("Cannot getwd\n")
			write(c, jsonError("failed", "internal error"))
			return
		}

		//fmt.Printf("abs_path: %v, new_path: %v\n", abs_path, new_path)
		if err := syscall.Rename(abs_path, new_path); err != 0 {
			anlog.Error("Cannot move from file `%s` to `%s`. %v.\n", abs_path, new_path, err)
			write(c, jsonError("failed", "internal error"))
			return
		}

		cdnized_url := fmt.Sprintf("http://%s/%s/%s/%s", Cfg.CdnServerName, Cfg.StoreDir[2:], Cfg.ApiStorePrefix, file_name)

		anlog.Info("cdnized_url: %s\n", cdnized_url)

		os.Remove(abs_path)

		type success struct {
			Status      string
			Size        int64
			Cdnized_url string
		}

		write(c, Jsonize(&success{"ok", data_size, cdnized_url}))
		return
	}

	//write(c, fmt.Sprintf("{Status: 'ok', url_path: '%s', gen: '%s'}", requested_url, x))

	file_ext := path.Ext(requested_url)
	abs_path, _ := os.Getwd()
	abs_path = path.Join(abs_path, Cfg.StoreDir[2:], Cfg.ApiStorePrefix, RandStrings(64)+file_ext)

	fmt.Printf("abs_path: %s\n", abs_path)

	var data []byte
	rv, lm, tsize := downloader.Download(requested_url, abs_path, true, &data)
	if rv != true {
		write(c, jsonError("failed", "Cannot fetch from source url"))
		return
	}

	md5ed := hmac.NewMD5([]byte("cdnized-2194"))
	for {
		brw, err := md5ed.Write(data)
		if err != nil {
			anlog.Error("Cannot calculate MD5 hash")
			write(c, jsonError("failed", "Internal error"))
			return
		}
		if brw >= tsize {
			break
		}
	}

	hash := fmt.Sprintf("%x", md5ed.Sum())
	dir, _ := path.Split(abs_path)
	file_name := hash + RandStrings(8) + file_ext
	new_path := path.Join(dir, file_name)

	if err := syscall.Rename(abs_path, new_path); err != 0 {
		anlog.Error("Cannot rename from file `%s` to `%s`", abs_path, new_path)
		write(c, jsonError("failed", "Internal error"))
		return
	}

	cdnized_url := fmt.Sprintf("http://%s/%s/%s/%s", Cfg.CdnServerName, Cfg.StoreDir[2:], Cfg.ApiStorePrefix, file_name)

	anlog.Info("cdnized_url: %s", cdnized_url)

	type success struct {
		Status      string
		Lm          string
		Size        int
		Original    string
		Cdnized_url string
	}

	write(c, Jsonize(&success{"ok", lm, tsize, requested_url, cdnized_url}))
}
Ejemplo n.º 14
0
Archivo: ufs.go Proyecto: wwaites/go9p
func (u *Ufs) Wstat(req *SrvReq) {
	fid := req.Fid.Aux.(*ufsFid)
	err := fid.stat()
	if err != nil {
		req.RespondError(err)
		return
	}

	dir := &req.Tc.Dir
	if dir.Mode != 0xFFFFFFFF {
		mode := dir.Mode & 0777
		if req.Conn.Dotu {
			if dir.Mode&DMSETUID > 0 {
				mode |= syscall.S_ISUID
			}
			if dir.Mode&DMSETGID > 0 {
				mode |= syscall.S_ISGID
			}
		}
		e := os.Chmod(fid.path, os.FileMode(mode))
		if e != nil {
			req.RespondError(toError(e))
			return
		}
	}

	uid, gid := NOUID, NOUID
	if req.Conn.Dotu {
		uid = dir.Uidnum
		gid = dir.Gidnum
	}

	// Try to find local uid, gid by name.
	if (dir.Uid != "" || dir.Gid != "") && !req.Conn.Dotu {
		uid, err = lookup(dir.Uid, false)
		if err != nil {
			req.RespondError(err)
			return
		}

		// BUG(akumar): Lookup will never find gids
		// corresponding to group names, because
		// it only operates on user names.
		gid, err = lookup(dir.Gid, true)
		if err != nil {
			req.RespondError(err)
			return
		}
	}

	if uid != NOUID || gid != NOUID {
		e := os.Chown(fid.path, int(uid), int(gid))
		if e != nil {
			req.RespondError(toError(e))
			return
		}
	}

	if dir.Name != "" {
		fmt.Printf("Rename %s to %s\n", fid.path, dir.Name)
		// if first char is / it is relative to root, else relative to
		// cwd.
		var destpath string
		if dir.Name[0] == '/' {
			destpath = path.Join(u.Root, dir.Name)
			fmt.Printf("/ results in %s\n", destpath)
		} else {
			fiddir, _ := path.Split(fid.path)
			destpath = path.Join(fiddir, dir.Name)
			fmt.Printf("rel  results in %s\n", destpath)
		}
		err := syscall.Rename(fid.path, destpath)
		fmt.Printf("rename %s to %s gets %v\n", fid.path, destpath, err)
		if err != nil {
			req.RespondError(toError(err))
			return
		}
		fid.path = destpath
	}

	if dir.Length != 0xFFFFFFFFFFFFFFFF {
		e := os.Truncate(fid.path, int64(dir.Length))
		if e != nil {
			req.RespondError(toError(e))
			return
		}
	}

	// If either mtime or atime need to be changed, then
	// we must change both.
	if dir.Mtime != ^uint32(0) || dir.Atime != ^uint32(0) {
		mt, at := time.Unix(int64(dir.Mtime), 0), time.Unix(int64(dir.Atime), 0)
		if cmt, cat := (dir.Mtime == ^uint32(0)), (dir.Atime == ^uint32(0)); cmt || cat {
			st, e := os.Stat(fid.path)
			if e != nil {
				req.RespondError(toError(e))
				return
			}
			switch cmt {
			case true:
				mt = st.ModTime()
			default:
				//at = time.Time(0)//atime(st.Sys().(*syscall.Stat_t))
			}
		}
		e := os.Chtimes(fid.path, at, mt)
		if e != nil {
			req.RespondError(toError(e))
			return
		}
	}

	req.RespondRwstat()
}
Ejemplo n.º 15
0
func TestRotatableFileWriter(t *testing.T) {
	dirs := make([]string, 0, 10)

	defer func() {
		if !t.Failed() {
			for _, dir := range dirs {
				os.RemoveAll(dir)
			}
		}
	}()

	for _, test := range rotateTests {
		dir, err := ioutil.TempDir("/tmp", "rfw")
		if err != nil {
			t.Fatal(err)
		}

		t.Logf("Test directory: %s\n", dir)

		dirs = append(dirs, dir)
		rotates := 0
		path := filepath.Join(dir, "log_test.log")
		rfw, err := NewRotatableFileWriter(path, os.O_CREATE|os.O_RDWR|os.O_APPEND, os.FileMode(0644), test.checkFreq)
		if err != nil {
			t.Error(err)
			continue
		}

		files := make(map[string][]string)
		files[path] = make([]string, 0, 10)
		ignoreLines := false

	TEST_LOOP:
		for _, event := range test.events {
			switch event.eventType {
			case logEventType:
				t.Logf("Writing: %s", event.message)
				_, err = rfw.Write([]byte(event.message + "\n"))
				if err != nil {
					if err == NilFileHandleErr {
						t.Log(err)
					} else {
						t.Error(err)
						break TEST_LOOP
					}
				}
				if !ignoreLines {
					files[path] = append(files[path], event.message)
				}
			case rotateEventType:
				t.Log("rotating")
				movePath := fmt.Sprintf("%s.%d", path, rotates)
				err = syscall.Rename(path, movePath)
				files[movePath] = files[path]
				files[path] = make([]string, 0, 10)
				ignoreLines = false
				rotates++
			case nilHandleType:
				t.Log("niling handle")
				rfw.fileHandle.Close()
				ignoreLines = true
				rfw.fileHandle = nil
			}

			time.Sleep(event.delay)
		}

		actualFiles, err := ioutil.ReadDir(dir)
		if err != nil {
			t.Error(err)
			continue
		}

		for _, fi := range actualFiles {
			if filepath.Base(fi.Name()) == "." || filepath.Base(fi.Name()) == ".." {
				continue
			}
			t.Logf("File: %s", fi.Name())
			file := filepath.Join(dir, fi.Name())
			var fileLines []string
			if d, ok := files[file]; ok {
				fileLines = d
			} else {
				t.Error("unexpected file", file)
			}
			fh, err := os.Open(file)
			if err != nil {
				t.Error(err)
				continue
			}
			data, err := ioutil.ReadAll(fh)
			if err != nil {
				t.Error(err)
				continue
			}
			lines := strings.Split(string(data), "\n")
			lines = lines[0 : len(lines)-1]

			if len(lines) != len(fileLines) {
				t.Errorf("Expected line count to match: %d != %d", len(lines), len(fileLines))
			}

			for i, line := range lines {
				if i >= len(fileLines) {
					break
				}

				if line != fileLines[i] {
					t.Errorf("Expected '%s' == '%s'", line, fileLines[i])
				}
			}
		}
	}
}
Ejemplo n.º 16
0
func (u *Ufs) Wstat(req *srv.Req) {
	var changed bool
	fid := req.Fid.Aux.(*Fid)
	err := fid.stat()
	if err != nil {
		req.RespondError(err)
		return
	}

	dir := &req.Tc.Dir
	if dir.Mode != 0xFFFFFFFF {
		changed = true
		mode := dir.Mode & 0777
		if req.Conn.Dotu {
			if dir.Mode&ninep.DMSETUID > 0 {
				mode |= syscall.S_ISUID
			}
			if dir.Mode&ninep.DMSETGID > 0 {
				mode |= syscall.S_ISGID
			}
		}
		e := os.Chmod(fid.path, os.FileMode(mode))
		if e != nil {
			req.RespondError(toError(e))
			return
		}
	}

	uid, gid := ninep.NOUID, ninep.NOUID
	if req.Conn.Dotu {
		uid = dir.Uidnum
		gid = dir.Gidnum
	}

	// Try to find local uid, gid by name.
	if (dir.Uid != "" || dir.Gid != "") && !req.Conn.Dotu {
		changed = true
		uid, err = lookup(dir.Uid, false)
		if err != nil {
			req.RespondError(err)
			return
		}

		// BUG(akumar): Lookup will never find gids
		// corresponding to group names, because
		// it only operates on user names.
		gid, err = lookup(dir.Gid, true)
		if err != nil {
			req.RespondError(err)
			return
		}
	}

	if uid != ninep.NOUID || gid != ninep.NOUID {
		changed = true
		e := os.Chown(fid.path, int(uid), int(gid))
		if e != nil {
			req.RespondError(toError(e))
			return
		}
	}

	if dir.Name != "" {
		changed = true
		// If we path.Join dir.Name to / before adding it to
		// the fid path, that ensures nobody gets to walk out of the
		// root of this server.
		newname := path.Join(path.Dir(fid.path), path.Join("/", dir.Name))

		// absolute renaming. Ufs can do this, so let's support it.
		// We'll allow an absolute path in the Name and, if it is,
		// we will make it relative to root. This is a gigantic performance
		// improvement in systems that allow it.
		if filepath.IsAbs(dir.Name) {
			newname = path.Join(u.Root, dir.Name)
		}

		err := syscall.Rename(fid.path, newname)
		if err != nil {
			req.RespondError(toError(err))
			return
		}
		fid.path = newname
	}

	if dir.Length != 0xFFFFFFFFFFFFFFFF {
		changed = true
		e := os.Truncate(fid.path, int64(dir.Length))
		if e != nil {
			req.RespondError(toError(e))
			return
		}
	}

	// If either mtime or atime need to be changed, then
	// we must change both.
	if dir.Mtime != ^uint32(0) || dir.Atime != ^uint32(0) {
		changed = true
		mt, at := time.Unix(int64(dir.Mtime), 0), time.Unix(int64(dir.Atime), 0)
		if cmt, cat := (dir.Mtime == ^uint32(0)), (dir.Atime == ^uint32(0)); cmt || cat {
			st, e := os.Stat(fid.path)
			if e != nil {
				req.RespondError(toError(e))
				return
			}
			switch cmt {
			case true:
				mt = st.ModTime()
			default:
				at = atime(st.Sys().(*syscall.Stat_t))
			}
		}
		e := os.Chtimes(fid.path, at, mt)
		if e != nil {
			req.RespondError(toError(e))
			return
		}
	}

	if !changed && fid.file != nil {
		fid.file.Sync()
	}
	req.RespondRwstat()
}
Ejemplo n.º 17
0
Archivo: vufs.go Proyecto: postfix/vufs
func (u *VuFs) Wstat(req *srv.Req) {
	fid := req.Fid.Aux.(*Fid)
	_, err := os.Stat(fid.path)
	if err != nil {
		req.RespondError(toError(err))
		return
	}

	dir := &req.Tc.Dir
	if dir.Mode != 0xFFFFFFFF {
		mode := dir.Mode & 0777
		e := os.Chmod(fid.path, os.FileMode(mode))
		if e != nil {
			req.RespondError(toError(e))
			return
		}
	}

	/*
		// BUG(mbucc) implement chown
		uid, gid := p.NOUID, p.NOUID

		uid, err = lookup(dir.Uid, false)
		if err != nil {
			req.RespondError(err)
			return
		}

		gid, err = lookup(dir.Gid, true)
		if err != nil {
			req.RespondError(err)
			return
		}

		if uid != p.NOUID || gid != p.NOUID {
			e := os.Chown(fid.path, int(uid), int(gid))
			if e != nil {
				req.RespondError(toError(e))
				return
			}
		}
	*/
	if dir.Name != "" {
		// If we path.Join dir.Name to / before adding it to
		// the fid path, that ensures nobody gets to walk out of the
		// root of this server.
		newname := path.Join(path.Dir(fid.path), path.Join("/", dir.Name))

		// absolute renaming. VuFs can do this, so let's support it.
		// We'll allow an absolute path in the Name and, if it is,
		// we will make it relative to root. This is a gigantic performance
		// improvement in systems that allow it.
		if filepath.IsAbs(dir.Name) {
			newname = path.Join(fid.path, dir.Name)
		}

		err := syscall.Rename(fid.path, newname)
		if err != nil {
			req.RespondError(toError(err))
			return
		}
		fid.path = newname
	}

	if dir.Length != 0xFFFFFFFFFFFFFFFF {
		e := os.Truncate(fid.path, int64(dir.Length))
		if e != nil {
			req.RespondError(toError(e))
			return
		}
	}

	// If either mtime or atime need to be changed, then
	// we must change both.
	if dir.Mtime != ^uint32(0) || dir.Atime != ^uint32(0) {
		mt, at := time.Unix(int64(dir.Mtime), 0), time.Unix(int64(dir.Atime), 0)
		if cmt, cat := (dir.Mtime == ^uint32(0)), (dir.Atime == ^uint32(0)); cmt || cat {
			st, e := os.Stat(fid.path)
			if e != nil {
				req.RespondError(toError(e))
				return
			}
			switch cmt {
			case true:
				mt = st.ModTime()
			default:
				at = atime(st.Sys().(*syscall.Stat_t))
			}
		}
		e := os.Chtimes(fid.path, at, mt)
		if e != nil {
			req.RespondError(toError(e))
			return
		}
	}

	req.RespondRwstat()
}
Ejemplo n.º 18
0
func (*Ufs) Wstat(req *srv.Req) {
	fid := req.Fid.Aux.(*Fid)
	err := fid.stat()
	if err != nil {
		req.RespondError(err)
		return
	}

	dir := &req.Tc.Dir
	if dir.Mode != 0xFFFFFFFF {
		mode := dir.Mode & 0777
		if req.Conn.Dotu {
			if dir.Mode&p.DMSETUID > 0 {
				mode |= syscall.S_ISUID
			}
			if dir.Mode&p.DMSETGID > 0 {
				mode |= syscall.S_ISGID
			}
		}
		e := os.Chmod(fid.path, os.FileMode(mode))
		if e != nil {
			req.RespondError(toError(e))
			return
		}
	}

	uid, gid := p.NOUID, p.NOUID
	if req.Conn.Dotu {
		uid = dir.Uidnum
		gid = dir.Gidnum
	}

	// Try to find local uid, gid by name.
	if (dir.Uid != "" || dir.Gid != "") && !req.Conn.Dotu {
		uid, err = lookup(dir.Uid, false)
		if err != nil {
			req.RespondError(err)
			return
		}

		// BUG(akumar): Lookup will never find gids
		// corresponding to group names, because
		// it only operates on user names.
		gid, err = lookup(dir.Gid, true)
		if err != nil {
			req.RespondError(err)
			return
		}
	}

	if uid != p.NOUID || gid != p.NOUID {
		e := os.Chown(fid.path, int(uid), int(gid))
		if e != nil {
			req.RespondError(toError(e))
			return
		}
	}

	if dir.Name != "" {
		path := fid.path[0:strings.LastIndex(fid.path, "/")+1] + "/" + dir.Name
		err := syscall.Rename(fid.path, path)
		if err != nil {
			req.RespondError(toError(err))
			return
		}
		fid.path = path
	}

	if dir.Length != 0xFFFFFFFFFFFFFFFF {
		e := os.Truncate(fid.path, int64(dir.Length))
		if e != nil {
			req.RespondError(toError(e))
			return
		}
	}

	// If either mtime or atime need to be changed, then
	// we must change both.
	if dir.Mtime != ^uint32(0) || dir.Atime != ^uint32(0) {
		mt, at := time.Unix(int64(dir.Mtime), 0), time.Unix(int64(dir.Atime), 0)
		if cmt, cat := (dir.Mtime == ^uint32(0)), (dir.Atime == ^uint32(0)); cmt || cat {
			st, e := os.Stat(fid.path)
			if e != nil {
				req.RespondError(toError(e))
				return
			}
			switch cmt {
			case true:
				mt = st.ModTime()
			default:
				at = atime(st.Sys().(*syscall.Stat_t))
			}
		}
		e := os.Chtimes(fid.path, at, mt)
		if e != nil {
			req.RespondError(toError(e))
			return
		}
	}

	req.RespondRwstat()
}
Ejemplo n.º 19
0
func (constor *Constor) Rename(input *fuse.RenameIn, oldName string, newName string) (code fuse.Status) {
	var unhashDentry *Dentry
	oldParent := input.NodeId
	newParent := input.Newdir

	oldpath, err := constor.dentrymap.getPathName(oldParent, oldName)
	if err != nil {
		constor.error("%s", err)
		return fuse.ToStatus(err)
	}
	newpath, err := constor.dentrymap.getPathName(newParent, newName)
	if err != nil {
		constor.error("%s", err)
		return fuse.ToStatus(err)
	}
	// newdirpath, err := constor.dentrymap.getPath(newParent)
	// if err != nil {
	// 	constor.error("%s", err)
	// 	return fuse.ToStatus(err)
	// }

	// remove dst file
	oldli := constor.getLayer(oldpath)

	if oldli == -1 {
		constor.error("oldli == -1")
		return fuse.ENOENT
	}

	oldstat := syscall.Stat_t{}
	newstat := syscall.Stat_t{}

	err = constor.Lstat(oldpath, &oldstat)
	if err != nil {
		constor.error("%s", err)
		return fuse.ToStatus(err)
	}
	if oldstat.Mode&syscall.S_IFDIR != 0 {
		allow := true
		for i, l := range constor.layers {
			if i == 0 {
				continue
			}
			pathl := Path.Join(l, oldpath)
			if constor.isdeleted(pathl) {
				break
			}
			if _, err := os.Lstat(pathl); err == nil {
				allow = false
				break
			}
		}
		if !allow {
			// FIXME: allow renaming of directories
			constor.error("rename of directory %s %d %d %d", oldpath, oldstat.Ino, oldstat.Mode, oldstat.Mode|syscall.S_IFDIR)
			return fuse.EIO
		}
	}

	err = constor.Lstat(newpath, &newstat)
	if err == nil {
		unhashDentry, _ = constor.dentrymap.findDentry(newParent, newstat.Ino)
	}

	oldpathl := Path.Join(constor.layers[0], oldpath)
	newpathl := Path.Join(constor.layers[0], newpath)

	if oldli == 0 {
		err = syscall.Rename(oldpathl, newpathl)
		if err != nil {
			constor.error("%s", err)
			return fuse.ToStatus(err)
		}
		lowerli := constor.getLayer(oldpath)
		if lowerli != -1 {
			constor.setdeleted(oldpathl)
		}
	} else if oldli > 0 {
		inode, err := constor.inodemap.findInode(oldstat.Ino)
		if err != nil {
			constor.error("%s", err)
			return fuse.ToStatus(err)
		}
		err = constor.copyup(inode)
		if err != nil {
			constor.error("%s", err)
			return fuse.ToStatus(err)
		}
		err = syscall.Rename(oldpathl, newpathl)
		if err != nil {
			constor.error("%s", err)
			return fuse.ToStatus(err)
		}
		constor.setdeleted(oldpathl)
	}
	if unhashDentry != nil {
		constor.dentrymap.unhashDentry(unhashDentry)
	}

	err = constor.dentrymap.dentryChangeparent(oldstat.Ino, oldParent, newParent, oldName, newName)
	if err != nil {
		constor.error("%s", err)
		return fuse.ToStatus(err)
	}
	return fuse.OK
}
Ejemplo n.º 20
0
// sad news. If I concat the Go cpio with the other cpios, for reasons I don't understand,
// the kernel can't unpack it. Don't know why, don't care. Need to create one giant cpio and unpack that.
// It's not size related: if the go archive is first or in the middle it still fails.
func main() {
	flag.BoolVar(&config.Debug, "d", false, "Debugging")
	flag.BoolVar(&config.TestChroot, "test", false, "test the directory by chrooting to it")
	flag.BoolVar(&config.UseExistingInit, "useinit", false, "If there is an existing init, don't replace it")
	flag.BoolVar(&config.RemoveDir, "removedir", true, "remove the directory when done -- cleared if test fails")
	flag.StringVar(&config.InitialCpio, "cpio", "", "An initial cpio image to build on")
	flag.StringVar(&config.TempDir, "tmpdir", "", "tmpdir to use instead of ioutil.TempDir")
	flag.Parse()
	if config.Debug {
		debug = log.Printf
	}

	var err error
	Dirs = make(map[string]bool)
	Deps = make(map[string]bool)
	GorootFiles = make(map[string]bool)
	UrootFiles = make(map[string]bool)
	guessgoarch()
	config.Go = ""
	config.Goos = "linux"
	guessgoroot()
	guessgopath()
	if config.Fail {
		log.Fatal("Setup failed")
	}

	if err := addGoFiles(); err != nil {
		log.Fatalf("%v", err)
	}

	if config.TempDir == "" {
		config.TempDir, err = ioutil.TempDir("", "u-root")
		if err != nil {
			log.Fatalf("%v", err)
		}
	}

	defer func() {
		if config.RemoveDir {
			log.Printf("Removing %v\n", config.TempDir)
			// Wow, this one is *scary*
			cmd := exec.Command("sudo", "rm", "-rf", config.TempDir)
			cmd.Stderr, cmd.Stdout = os.Stderr, os.Stdout
			err = cmd.Run()
			if err != nil {
				log.Fatalf("%v", err)
			}
		}
	}()

	buildToolChain()

	if config.InitialCpio != "" {
		f, err := ioutil.ReadFile(config.InitialCpio)
		if err != nil {
			log.Fatalf("%v", err)
		}

		cmd := exec.Command("sudo", "cpio", "-i", "-v")
		cmd.Dir = config.TempDir
		// Note: if you print Cmd out with %v after assigning cmd.Stdin, it will print
		// the whole cpio; so don't do that.
		if config.Debug {
			cmd.Stdout = os.Stdout
		}
		debug("Run %v @ %v", cmd, cmd.Dir)

		// There's a bit of a tough problem here. There's lots of stuff owned by root in
		// these directories. They probably have to stay that way. But how do we create init
		// and do other things? For now, we're going to set the modes of select places to
		// 666 and remove a few things we know need to be removed.
		// It's hard to say what else to do.
		cmd.Stdin = bytes.NewBuffer(f)
		cmd.Stderr = os.Stderr
		err = cmd.Run()
		if err != nil {
			log.Printf("Unpacking %v: %v", config.InitialCpio, err)
		}
	}

	if !config.UseExistingInit {
		init := path.Join(config.TempDir, "init")
		// Must move config.TempDir/init to inito if one is not there.
		inito := path.Join(config.TempDir, "inito")
		if _, err := os.Stat(inito); err != nil {
			// WTF? did Ron forget about rename? Yuck!
			if err := syscall.Rename(init, inito); err != nil {
				log.Printf("%v", err)
			}
		} else {
			log.Printf("Not replacing %v because there is already one there.", inito)
		}

		// Build init
		cmd := exec.Command("go", "build", "-x", "-a", "-installsuffix", "cgo", "-ldflags", "'-s'", "-o", init, ".")
		cmd.Stderr = os.Stderr
		cmd.Stdout = os.Stdout
		cmd.Dir = path.Join(config.Urootpath, "cmds/init")

		err = cmd.Run()
		if err != nil {
			log.Fatalf("%v\n", err)
		}
	}

	// These produce arrays of strings, the first element being the
	// directory to walk from.
	cpio := []string{
		goList,
		urootList,
	}

	for _, c := range cpio {
		if err := cpiop(c); err != nil {
			log.Printf("Things went south. TempDir is %v", config.TempDir)
			log.Fatalf("Bailing out near line 666")
		}
	}

	debug("Done all cpio operations")

	r, w, err := os.Pipe()
	if err != nil {
		log.Fatalf("%v\n", err)
	}

	// First create the archive and put the device cpio in it.
	dev, err := ioutil.ReadFile(path.Join(config.Urootpath, devcpio))
	if err != nil {
		log.Fatalf("%v %v\n", dev, err)
	}

	debug("Creating initramf file")

	oname := fmt.Sprintf("/tmp/initramfs.%v_%v.cpio", config.Goos, config.Arch)
	if err := ioutil.WriteFile(oname, dev, 0600); err != nil {
		log.Fatalf("%v\n", err)
	}

	// Now use the append option for cpio to append to it.
	// That way we get one cpio.
	// We need sudo as there may be files created from an initramfs that
	// can only be read by root.
	cmd := exec.Command("sudo", "cpio", "-H", "newc", "-o", "-A", "-F", oname)
	cmd.Dir = config.TempDir
	cmd.Stdin = r
	cmd.Stderr = os.Stderr
	cmd.Stdout = os.Stdout
	debug("Run %v @ %v", cmd, cmd.Dir)
	err = cmd.Start()
	if err != nil {
		log.Fatalf("%v\n", err)
	}
	if err := lsr(config.TempDir, w); err != nil {
		log.Fatalf("%v\n", err)
	}
	w.Close()
	debug("Finished sending file list for initramfs cpio")
	err = cmd.Wait()
	if err != nil {
		log.Printf("%v\n", err)
	}
	debug("cpio for initramfs is done")
	defer func() {
		log.Printf("Output file is in %v\n", oname)
	}()

	if !config.TestChroot {
		return
	}

	// We need to populate the temp directory with dev.cpio. It's a chicken and egg thing;
	// we can't run init without, e.g., /dev/console and /dev/null.
	cmd = exec.Command("sudo", "cpio", "-i")
	cmd.Dir = config.TempDir
	// We have it in memory. Get a better way to do this!
	r, err = os.Open(path.Join(config.Urootpath, devcpio))
	if err != nil {
		log.Fatalf("%v", err)
	}

	// OK, at this point, we know we can run as root. And, we're going to create things
	// we can only remove as root. So, we'll have to remove the directory with
	// extreme measures.
	reallyRemoveDir := config.RemoveDir
	config.RemoveDir = false
	cmd.Stdin, cmd.Stderr, cmd.Stdout = r, os.Stderr, os.Stdout
	debug("Run %v @ %v", cmd, cmd.Dir)
	err = cmd.Run()
	if err != nil {
		log.Fatalf("%v", err)
	}
	// Arrange to start init in the directory in a new namespace.
	// That should make all mounts go away when we're done.
	// On real kernels you can unshare without being root. Not on Linux.
	cmd = exec.Command("sudo", "unshare", "-m", "chroot", config.TempDir, "/init")
	cmd.Dir = config.TempDir
	cmd.Stdin, cmd.Stderr, cmd.Stdout = os.Stdin, os.Stderr, os.Stdout
	debug("Run %v @ %v", cmd, cmd.Dir)
	err = cmd.Run()
	if err != nil {
		log.Fatalf("Test failed, not removing %v: %v", config.TempDir, err)
		config.RemoveDir = false
	}
	config.RemoveDir = reallyRemoveDir
}
Ejemplo n.º 21
0
Archivo: p9.go Proyecto: flynn/bake
// Wstat updates file info.
func (fs *fileSystem) Wstat(req *go9p.SrvReq) {
	aux := req.Fid.Aux.(*Aux)
	if err := aux.stat(); err != nil {
		req.RespondError(err)
		return
	}

	// Add to writeset.
	fs.addToWriteset(aux.rootID, aux.path)

	dir := &req.Tc.Dir
	if dir.Mode != 0xFFFFFFFF {
		mode := dir.Mode & 0777
		if req.Conn.Dotu {
			if dir.Mode&go9p.DMSETUID > 0 {
				mode |= syscall.S_ISUID
			}
			if dir.Mode&go9p.DMSETGID > 0 {
				mode |= syscall.S_ISGID
			}
		}

		err := os.Chmod(aux.path, os.FileMode(mode))
		if err != nil {
			req.RespondError(toError(err))
			return
		}
	}

	uid, gid := go9p.NOUID, go9p.NOUID
	if req.Conn.Dotu {
		uid = dir.Uidnum
		gid = dir.Gidnum
	}

	// Try to find local uid, gid by name.
	if (dir.Uid != "" || dir.Gid != "") && !req.Conn.Dotu {
		var err error
		uid, err = lookupUser(dir.Uid)
		if err != nil {
			req.RespondError(err)
			return
		}

		gid, err = lookupGroup(dir.Gid)
		if err != nil {
			req.RespondError(err)
			return
		}
	}

	if uid != go9p.NOUID || gid != go9p.NOUID {
		err := os.Chown(aux.path, int(uid), int(gid))
		if err != nil {
			req.RespondError(toError(err))
			return
		}
	}

	if dir.Name != "" {
		// if first char is / it is relative to root, else relative to cwd.
		var destpath string
		if dir.Name[0] == '/' {
			destpath = path.Join(fs.path, dir.Name)
			fmt.Printf("/ results in %s\n", destpath)
		} else {
			auxdir, _ := path.Split(aux.path)
			destpath = path.Join(auxdir, dir.Name)
			fmt.Printf("rel  results in %s\n", destpath)
		}
		err := syscall.Rename(aux.path, destpath)
		fmt.Printf("rename %s to %s gets %v\n", aux.path, destpath, err)
		if err != nil {
			req.RespondError(toError(err))
			return
		}
		aux.path = destpath
	}

	// Set file size, if specified.
	if dir.Length != 0xFFFFFFFFFFFFFFFF {
		if err := os.Truncate(aux.path, int64(dir.Length)); err != nil {
			req.RespondError(toError(err))
			return
		}
	}

	// If either mtime or atime need to be changed, then we must change both.
	if dir.Mtime != ^uint32(0) || dir.Atime != ^uint32(0) {
		mtime := time.Unix(int64(dir.Mtime), 0)
		atime := time.Unix(int64(dir.Atime), 0)

		mtimeChanged := (dir.Mtime == ^uint32(0))
		atimeChanged := (dir.Atime == ^uint32(0))
		if mtimeChanged || atimeChanged {
			st, err := os.Stat(aux.path)
			if err != nil {
				req.RespondError(toError(err))
				return
			} else if mtimeChanged {
				mtime = st.ModTime()
			}
		}
		if err := os.Chtimes(aux.path, atime, mtime); err != nil {
			req.RespondError(toError(err))
			return
		}
	}

	req.RespondRwstat()
}