- 论坛徽章:
- 0
|
给你google来的一个参考
- #ifndef AT_FDCWD
- #define AT_FDCWD -100
- #endif
- #if defined(__i386__)
- #define __NR_revokeat 325
- #else
- #error unsupported arch
- #endif
- int revokeat(int dfd, const char *path)
- {
- return syscall(__NR_revokeat, dfd, path);
- }
- static void panic(const char *s)
- {
- perror(s);
- exit(1);
- }
- /* I test here for __sun for lack of anything better, but I
- * mean Solaris 2.6. The idea of undefining SCM_RIGHTS is
- * to force the headers to behave BSD 4.3 way which I have
- * tested to work.
- *
- * In general, if you have compilation errors, you might consider
- * adding a test for your platform here.
- */
- #if defined(__sun)
- #undef SCM_RIGHTS
- #endif
- #ifdef SCM_RIGHTS
- /* It seems various versions of glibc headers (i.e.
- * /usr/include/socketbits.h) miss one or more of these */
- #ifndef CMSG_DATA
- # define CMSG_DATA(cmsg) ((cmsg)->cmsg_data)
- #endif
- #ifndef CMSG_NXTHDR
- # define CMSG_NXTHDR(mhdr, cmsg) __cmsg_nxthdr (mhdr, cmsg)
- #endif
- #ifndef CMSG_FIRSTHDR
- # define CMSG_FIRSTHDR(mhdr) \
- ((size_t) (mhdr)->msg_controllen >= sizeof (struct cmsghdr) \
- ? (struct cmsghdr *) (mhdr)->msg_control : (struct cmsghdr *) NULL)
- #endif
- #ifndef CMSG_ALIGN
- # define CMSG_ALIGN(len) (((len) + sizeof (size_t) - 1) \
- & ~(sizeof (size_t) - 1))
- #endif
- #ifndef CMSG_SPACE
- # define CMSG_SPACE(len) (CMSG_ALIGN (len) \
- + CMSG_ALIGN (sizeof (struct cmsghdr)))
- #endif
- #ifndef CMSG_LEN
- # define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
- #endif
- union fdmsg {
- struct cmsghdr h;
- char buf[CMSG_SPACE(sizeof(int))];
- };
- #endif
- /* Tested to work on perl 5.005_03
- * Linux-2.2.14 glibc-2.0.7 (libc.so.6) i586 BSD4.4
- * Linux-2.0.38 glibc-2.0.7 (libc.so.6) i586 BSD4.4
- * SunOS-5.6, gcc-2.7.2.3, Sparc BSD4.3
- * see also: linux/net/unix/af_unix.c
- */
- int
- sendfd(sock_fd, send_me_fd)
- int sock_fd;
- int send_me_fd;
- {
- int ret = 0;
- struct iovec iov[1];
- struct msghdr msg;
- iov[0].iov_base = &ret; /* Don't send any data. Note: der Mouse
- * <[email]mouse@Rodents.Montreal.QC.CA[/email]> says
- * that might work better if at least one
- * byte is sent. */
- iov[0].iov_len = 1;
- msg.msg_iov = iov;
- msg.msg_iovlen = 1;
- msg.msg_name = 0;
- msg.msg_namelen = 0;
- {
- #ifdef SCM_RIGHTS
- /* New BSD 4.4 way (ouch, why does this have to be
- * so convoluted). */
- union fdmsg cmsg;
- struct cmsghdr* h;
- msg.msg_control = cmsg.buf;
- msg.msg_controllen = sizeof(union fdmsg);
- msg.msg_flags = 0;
- h = CMSG_FIRSTHDR(&msg);
- h->cmsg_len = CMSG_LEN(sizeof(int));
- h->cmsg_level = SOL_SOCKET;
- h->cmsg_type = SCM_RIGHTS;
- *((int*)CMSG_DATA(h)) = send_me_fd;
- #else
- /* Old BSD 4.3 way. Not tested. */
- msg.msg_accrights = &send_me_fd;
- msg.msg_accrightslen = sizeof(send_me_fd);
- #endif
- if (sendmsg(sock_fd, &msg, 0) < 0) {
- ret = 0;
- } else {
- ret = 1;
- }
- }
- /*fprintf(stderr,"send %d %d %d %d\n",sock_fd, send_me_fd, ret, errno);*/
- return ret;
- }
- int
- recvfd(sock_fd)
- int sock_fd;
- {
- int count;
- int ret = 0;
- struct iovec iov[1];
- struct msghdr msg;
- iov[0].iov_base = &ret; /* don't receive any data */
- iov[0].iov_len = 1;
- msg.msg_iov = iov;
- msg.msg_iovlen = 1;
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- {
- #ifdef SCM_RIGHTS
- union fdmsg cmsg;
- struct cmsghdr* h;
- msg.msg_control = cmsg.buf;
- msg.msg_controllen = sizeof(union fdmsg);
- msg.msg_flags = 0;
- h = CMSG_FIRSTHDR(&msg);
- h->cmsg_len = CMSG_LEN(sizeof(int));
- h->cmsg_level = SOL_SOCKET; /* Linux does not set these */
- h->cmsg_type = SCM_RIGHTS; /* upon return */
- *((int*)CMSG_DATA(h)) = -1;
- if ((count = recvmsg(sock_fd, &msg, 0)) < 0) {
- ret = 0;
- } else {
- h = CMSG_FIRSTHDR(&msg); /* can realloc? */
- if ( h == NULL
- || h->cmsg_len != CMSG_LEN(sizeof(int))
- || h->cmsg_level != SOL_SOCKET
- || h->cmsg_type != SCM_RIGHTS ) {
- /* This should really never happen */
- if (h)
- fprintf(stderr,
- "%s:%d: protocol failure: %d %d %d\n",
- __FILE__, __LINE__,
- h->cmsg_len,
- h->cmsg_level, h->cmsg_type);
- else
- fprintf(stderr,
- "%s:%d: protocol failure: NULL cmsghdr*\n",
- __FILE__, __LINE__);
- ret = 0;
- } else {
- ret = *((int*)CMSG_DATA(h));
- /*fprintf(stderr, "recv ok %d\n", ret);*/
- }
- }
- #else
- int receive_fd;
- msg.msg_accrights = &receive_fd;
- msg.msg_accrightslen = sizeof(receive_fd);
- if (recvmsg(sock_fd, &msg, 0) < 0) {
- panic("recvmsg");
- ret = 0;
- } else {
- ret = receive_fd;
- }
- #endif
- }
- return ret;
- }
- int main(int argc, char *argv[])
- {
- int fd, err, new_fd;
- int sockpair[2];
- char buf[1024];
- fd = open(argv[1], O_RDWR);
- if (fd < 0)
- panic("open");
- err = socketpair(PF_LOCAL, SOCK_DGRAM, 0, sockpair);
- if (err)
- panic("socketpair");
- if (!sendfd(sockpair[0], fd))
- panic("sendfd");
- close(fd);
- err = revokeat(AT_FDCWD, argv[1]);
- if (err)
- panic("revokeat");
- new_fd = recvfd(sockpair[1]);
- if (new_fd <= 0)
- panic("recvfd");
- if (read(new_fd, buf, 1024) != -1 || errno != EBADF) {
- printf("Failed: can read from SCM_RIGHTS descriptor\n");
- exit(1);
- }
- printf("Test OK.\n");
- return 0;
- }
复制代码 |
|