func op(fn string) (fd int, err error) { fdh, err := unix.Open(fn, unix.O_RDWR, 0) if err != nil { return -1, err } // mask := ^unix.S_IXGRP // p := unix.S_ISGID & mask err = unix.Fchmod(int(fdh), unix.S_ISGID|unix.S_IRUSR|unix.S_IWUSR /*| unix.S_IRGRP | unix.S_IWGRP*/) if err != nil { return -1, err } return int(fdh), nil }
func MakeNetworkNS(containerID string) string { namespace := "/var/run/netns/" + containerID err := os.MkdirAll("/var/run/netns", 0600) Expect(err).NotTo(HaveOccurred()) // create an empty file at the mount point mountPointFd, err := os.Create(namespace) Expect(err).NotTo(HaveOccurred()) mountPointFd.Close() var wg sync.WaitGroup wg.Add(1) // do namespace work in a dedicated goroutine, so that we can safely // Lock/Unlock OSThread without upsetting the lock/unlock state of // the caller of this function. See block comment above. go (func() { defer wg.Done() runtime.LockOSThread() defer runtime.UnlockOSThread() defer GinkgoRecover() // capture current thread's original netns currentThreadNetNSPath := getCurrentThreadNetNSPath() originalNetNS, err := unix.Open(currentThreadNetNSPath, unix.O_RDONLY, 0) Expect(err).NotTo(HaveOccurred()) defer unix.Close(originalNetNS) // create a new netns on the current thread err = unix.Unshare(unix.CLONE_NEWNET) Expect(err).NotTo(HaveOccurred()) // bind mount the new netns from the current thread onto the mount point err = unix.Mount(currentThreadNetNSPath, namespace, "none", unix.MS_BIND, "") Expect(err).NotTo(HaveOccurred()) // reset current thread's netns to the original _, _, e1 := unix.Syscall(unix.SYS_SETNS, uintptr(originalNetNS), uintptr(unix.CLONE_NEWNET), 0) Expect(e1).To(BeZero()) })() wg.Wait() return namespace }
// TestFcntlFlock tests whether the file locking structure matches // the calling convention of each kernel. func TestFcntlFlock(t *testing.T) { name := filepath.Join(os.TempDir(), "TestFcntlFlock") fd, err := unix.Open(name, unix.O_CREAT|unix.O_RDWR|unix.O_CLOEXEC, 0) if err != nil { t.Fatalf("Open failed: %v", err) } defer unix.Unlink(name) defer unix.Close(fd) flock := unix.Flock_t{ Type: unix.F_RDLCK, Start: 0, Len: 0, Whence: 1, } if err := unix.FcntlFlock(uintptr(fd), unix.F_GETLK, &flock); err != nil { t.Fatalf("FcntlFlock failed: %v", err) } }
// hackDump returns the value dump as a string. func hackDump(v llvm.Value) (string, error) { // Open temp file. // TODO: Use an in-memory file instead of /tmp/x. fd, err := unix.Open("/tmp/x", unix.O_WRONLY|unix.O_TRUNC|unix.O_CREAT, 0644) if err != nil { return "", errutil.Err(err) } // Store original stderr. stderr, err := unix.Dup(2) if err != nil { return "", errutil.Err(err) } // Capture stderr and redirect its output to the temp file. err = unix.Dup2(fd, 2) if err != nil { return "", errutil.Err(err) } err = unix.Close(fd) if err != nil { return "", errutil.Err(err) } // Dump value. v.Dump() C.fflush_stderr() // Restore stderr. err = unix.Dup2(stderr, 2) if err != nil { return "", errutil.Err(err) } err = unix.Close(stderr) if err != nil { return "", errutil.Err(err) } // Return content of temp file. buf, err := ioutil.ReadFile("/tmp/x") if err != nil { return "", errutil.Err(err) } return string(buf), nil }
func makeNetworkNS(containerID string) string { namespace := "/var/run/netns/" + containerID pid := unix.Getpid() tid := unix.Gettid() err := os.MkdirAll("/var/run/netns", 0600) Expect(err).NotTo(HaveOccurred()) runtime.LockOSThread() defer runtime.UnlockOSThread() go (func() { defer GinkgoRecover() err = unix.Unshare(unix.CLONE_NEWNET) Expect(err).NotTo(HaveOccurred()) fd, err := os.Create(namespace) Expect(err).NotTo(HaveOccurred()) defer fd.Close() err = unix.Mount("/proc/self/ns/net", namespace, "none", unix.MS_BIND, "") Expect(err).NotTo(HaveOccurred()) })() Eventually(namespace).Should(BeAnExistingFile()) fd, err := unix.Open(fmt.Sprintf("/proc/%d/task/%d/ns/net", pid, tid), unix.O_RDONLY, 0) Expect(err).NotTo(HaveOccurred()) defer unix.Close(fd) _, _, e1 := unix.Syscall(unix.SYS_SETNS, uintptr(fd), uintptr(unix.CLONE_NEWNET), 0) Expect(e1).To(BeZero()) return namespace }
// addWatch adds name to the watched file set. // The flags are interpreted as described in kevent(2). // Returns the real path to the file which was added, if any, which may be different from the one passed in the case of symlinks. func (w *Watcher) addWatch(name string, flags uint32) (string, error) { var isDir bool // Make ./name and name equivalent name = filepath.Clean(name) w.mu.Lock() if w.isClosed { w.mu.Unlock() return "", errors.New("kevent instance already closed") } watchfd, alreadyWatching := w.watches[name] // We already have a watch, but we can still override flags. if alreadyWatching { isDir = w.paths[watchfd].isDir } w.mu.Unlock() if !alreadyWatching { fi, err := os.Lstat(name) if err != nil { return "", err } // Don't watch sockets. if fi.Mode()&os.ModeSocket == os.ModeSocket { return "", nil } // Don't watch named pipes. if fi.Mode()&os.ModeNamedPipe == os.ModeNamedPipe { return "", nil } // Follow Symlinks // Unfortunately, Linux can add bogus symlinks to watch list without // issue, and Windows can't do symlinks period (AFAIK). To maintain // consistency, we will act like everything is fine. There will simply // be no file events for broken symlinks. // Hence the returns of nil on errors. if fi.Mode()&os.ModeSymlink == os.ModeSymlink { name, err = filepath.EvalSymlinks(name) if err != nil { return "", nil } w.mu.Lock() _, alreadyWatching = w.watches[name] w.mu.Unlock() if alreadyWatching { return name, nil } fi, err = os.Lstat(name) if err != nil { return "", nil } } watchfd, err = unix.Open(name, openMode, 0700) if watchfd == -1 { return "", err } isDir = fi.IsDir() } const registerAdd = unix.EV_ADD | unix.EV_CLEAR | unix.EV_ENABLE if err := register(w.kq, []int{watchfd}, registerAdd, flags); err != nil { unix.Close(watchfd) return "", err } if !alreadyWatching { w.mu.Lock() w.watches[name] = watchfd w.paths[watchfd] = pathInfo{name: name, isDir: isDir} w.mu.Unlock() } if isDir { // Watch the directory if it has not been watched before, // or if it was watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles) w.mu.Lock() watchDir := (flags&unix.NOTE_WRITE) == unix.NOTE_WRITE && (!alreadyWatching || (w.dirFlags[name]&unix.NOTE_WRITE) != unix.NOTE_WRITE) // Store flags so this watch can be updated later w.dirFlags[name] = flags w.mu.Unlock() if watchDir { if err := w.watchDirectoryFiles(name); err != nil { return "", err } } } return name, nil }
// Copyright (C) 2016 Arista Networks, Inc. // Use of this source code is governed by the Apache License 2.0 // that can be found in the COPYING file. package netns import "golang.org/x/sys/unix" // close closes the file descriptor mapped to a network namespace func (h nsHandle) close() error { return unix.Close(int(h)) } // fd returns the handle as a uintptr func (h nsHandle) fd() int { return int(h) } // getNs returns a file descriptor mapping to the given network namespace var getNs = func(nsName string) (handle, error) { fd, err := unix.Open(nsName, unix.O_RDONLY, 0) return nsHandle(fd), err } // setNs sets the process's network namespace var setNs = func(h handle) error { return unix.Setns(h.fd(), unix.CLONE_NEWNET) }