diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 528e753f1..6c73c0ccf 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,26 @@ +2007-01-17 Corinna Vinschen + + * Makefile.in (DLL_OFILES): Add fhandler_procnet.o. + * autoload.cc (GetAdaptersAddresses): Define. + * devices.h (FH_PROCNET): Define new device. + * devices.in (dev_procnet_storage): Add "/proc/net" entry. + * devices.cc: Regenerate. + * dir.cc (readdir_worker): Use isproc_dev macro. + * dtable.cc (build_fh_pc): Add FH_PROCNET. + * fhandler.h (class fhandler_procnet): New class. + * fhandler_proc.cc: Add "net" subdirectory handling. + * fhandler_procnet.cc: New file handling "/proc/net" directory. + * path.cc (isvirtual_dev): Move to path.h. + * path.h (isproc_dev): New macro to identify /proc files by device. + (isvirtual_dev): Moved here. Define using isproc_dev. + * syscalls.cc (unlink): Use isproc_dev macro. + * wincap.h (wincapc::has_gaa_prefixes): New element. + (wincapc::has_gaa_on_link_prefix): New element. + * wincap.cc: Implement above elements throughout. + (wincapc::init): Check XP for service pack and set has_gaa_prefixes + appropriately. + * include/cygwin/in6.h: Include asm/byteorder.h. + 2007-01-17 Corinna Vinschen * include/asm/socket.h (SIOGIFINDEX): Define. diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in index c8ef03e63..0d1c0c07c 100644 --- a/winsup/cygwin/Makefile.in +++ b/winsup/cygwin/Makefile.in @@ -1,5 +1,6 @@ # Makefile.in for Cygwin. -# Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc. +# Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2007 Red Hat, Inc. # # This file is part of Cygwin. # @@ -129,19 +130,19 @@ DLL_OFILES:=assert.o autoload.o bsdlib.o ctype.o cxx.o cygheap.o cygthread.o \ fhandler.o fhandler_clipboard.o fhandler_console.o fhandler_disk_file.o \ fhandler_dsp.o fhandler_fifo.o fhandler_floppy.o fhandler_mailslot.o \ fhandler_mem.o fhandler_netdrive.o fhandler_nodevice.o fhandler_proc.o \ - fhandler_process.o fhandler_random.o fhandler_raw.o fhandler_registry.o \ - fhandler_serial.o fhandler_socket.o fhandler_tape.o fhandler_termios.o \ - fhandler_tty.o fhandler_virtual.o fhandler_windows.o fhandler_zero.o \ - flock.o fnmatch.o fork.o fts.o ftw.o getopt.o glob.o grp.o heap.o \ - hookapi.o inet_addr.o inet_network.o init.o ioctl.o ipc.o localtime.o \ - lsearch.o malloc_wrapper.o memmem.o minires-os-if.o minires.o \ - miscfuncs.o mktemp.o mmap.o msg.o net.o netdb.o nftw.o ntea.o passwd.o \ - path.o pinfo.o pipe.o poll.o pthread.o regcomp.o regerror.o regexec.o \ - regfree.o registry.o resource.o rexec.o rcmd.o scandir.o sched.o \ - sec_acl.o sec_helper.o security.o select.o sem.o shared.o shm.o sigfe.o \ - signal.o sigproc.o smallprint.o spawn.o strace.o strptime.o strsep.o \ - strsig.o sync.o syscalls.o sysconf.o syslog.o termios.o thread.o \ - timelocal.o timer.o times.o tty.o uinfo.o uname.o v8_regexp.o \ + fhandler_process.o fhandler_procnet.o fhandler_random.o fhandler_raw.o \ + fhandler_registry.o fhandler_serial.o fhandler_socket.o fhandler_tape.o \ + fhandler_termios.o fhandler_tty.o fhandler_virtual.o fhandler_windows.o \ + fhandler_zero.o flock.o fnmatch.o fork.o fts.o ftw.o getopt.o glob.o \ + grp.o heap.o hookapi.o inet_addr.o inet_network.o init.o ioctl.o ipc.o \ + localtime.o lsearch.o malloc_wrapper.o memmem.o minires-os-if.o \ + minires.o miscfuncs.o mktemp.o mmap.o msg.o net.o netdb.o nftw.o ntea.o \ + passwd.o path.o pinfo.o pipe.o poll.o pthread.o regcomp.o regerror.o \ + regexec.o regfree.o registry.o resource.o rexec.o rcmd.o scandir.o \ + sched.o sec_acl.o sec_helper.o security.o select.o sem.o shared.o shm.o \ + sigfe.o signal.o sigproc.o smallprint.o spawn.o strace.o strptime.o \ + strsep.o strsig.o sync.o syscalls.o sysconf.o syslog.o termios.o \ + thread.o timelocal.o timer.o times.o tty.o uinfo.o uname.o v8_regexp.o \ v8_regerror.o v8_regsub.o wait.o wincap.o window.o winf.o \ $(EXTRA_DLL_OFILES) $(EXTRA_OFILES) $(MALLOC_OFILES) $(MT_SAFE_OBJECTS) diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 4a8d1d1d9..bd8e73371 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -1,6 +1,6 @@ /* autoload.cc: all dynamic load stuff. - Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc. + Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Red Hat, Inc. This file is part of Cygwin. @@ -495,6 +495,7 @@ LoadDLLfunc (WSASetLastError, 4, ws2_32) LoadDLLfunc (WSAWaitForMultipleEvents, 20, ws2_32) // 50 = ERROR_NOT_SUPPORTED. Returned if OS doesn't supprot iphlpapi funcs +LoadDLLfuncEx2 (GetAdaptersAddresses, 20, iphlpapi, 1, 50) LoadDLLfuncEx2 (GetIfEntry, 4, iphlpapi, 1, 50) LoadDLLfuncEx2 (GetIpAddrTable, 12, iphlpapi, 1, 50) LoadDLLfuncEx2 (GetNetworkParams, 8, iphlpapi, 1, 50) diff --git a/winsup/cygwin/devices.cc b/winsup/cygwin/devices.cc index 652eb77eb..58b21a456 100644 --- a/winsup/cygwin/devices.cc +++ b/winsup/cygwin/devices.cc @@ -25,6 +25,9 @@ const device dev_fs_storage = const device dev_proc_storage = {"", {FH_PROC}, ""}; +const device dev_procnet_storage = + {"", {FH_PROCNET}, ""}; + const device dev_netdrive_storage = {"", {FH_NETDRIVE}, ""}; diff --git a/winsup/cygwin/devices.h b/winsup/cygwin/devices.h index 2d2da89d5..9c8efa325 100644 --- a/winsup/cygwin/devices.h +++ b/winsup/cygwin/devices.h @@ -51,6 +51,7 @@ enum fh_devices FH_NETDRIVE= FHDEV (0, 246), FH_DEV = FHDEV (0, 245), + FH_PROCNET = FHDEV (0, 244), DEV_FLOPPY_MAJOR = 2, FH_FLOPPY = FHDEV (DEV_FLOPPY_MAJOR, 0), diff --git a/winsup/cygwin/devices.in b/winsup/cygwin/devices.in index 87c64f2af..22de0c2ee 100644 --- a/winsup/cygwin/devices.in +++ b/winsup/cygwin/devices.in @@ -21,6 +21,9 @@ const device dev_fs_storage = const device dev_proc_storage = {"", {FH_PROC}, ""}; +const device dev_procnet_storage = + {"", {FH_PROCNET}, ""}; + const device dev_netdrive_storage = {"", {FH_NETDRIVE}, ""}; diff --git a/winsup/cygwin/dir.cc b/winsup/cygwin/dir.cc index c3b22c66d..1b4e93a45 100644 --- a/winsup/cygwin/dir.cc +++ b/winsup/cygwin/dir.cc @@ -1,6 +1,6 @@ /* dir.cc: Posix directory-related routines - Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2006 Red Hat, Inc. + Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2006, 2007 Red Hat, Inc. This file is part of Cygwin. @@ -133,7 +133,7 @@ readdir_worker (DIR *dir, dirent *de) const char *w32name = ((fhandler_base *) dir->__fh)->get_win32_name (); DWORD devn = ((fhandler_base *) dir->__fh)->get_device (); /* Paths below /proc don't have a Win32 pendant. */ - if (devn == FH_PROC || devn == FH_PROCESS || devn == FH_REGISTRY) + if (isproc_dev (devn)) de->d_ino = hash_path_name (de->d_ino, "/"); /* A drive's root dir has a trailing backslash already. */ else if (w32name[1] != ':' || w32name[2] != '\\' || w32name[3]) diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc index b436c88c6..17efacb69 100644 --- a/winsup/cygwin/dtable.cc +++ b/winsup/cygwin/dtable.cc @@ -1,7 +1,7 @@ /* dtable.cc: file descriptor support. Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, - 2005, 2006 Red Hat, Inc. + 2005, 2006, 2007 Red Hat, Inc. This file is part of Cygwin. @@ -461,6 +461,9 @@ build_fh_pc (path_conv& pc) case FH_PROCESS: fh = cnew (fhandler_process) (); break; + case FH_PROCNET: + fh = cnew (fhandler_procnet) (); + break; case FH_NETDRIVE: fh = cnew (fhandler_netdrive) (); break; diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 5a294f30a..5fce7a1d6 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -1308,6 +1308,19 @@ class fhandler_process: public fhandler_proc bool fill_filebuf (); }; +class fhandler_procnet: public fhandler_proc +{ + pid_t pid; + public: + fhandler_procnet (); + int exists(); + DIR *opendir (); + int readdir (DIR *, dirent *) __attribute__ ((regparm (3))); + int open (int flags, mode_t mode = 0); + int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); + bool fill_filebuf (); +}; + struct fhandler_nodevice: public fhandler_base { fhandler_nodevice (); diff --git a/winsup/cygwin/fhandler_proc.cc b/winsup/cygwin/fhandler_proc.cc index e1bc4d1f3..d4ea8b762 100644 --- a/winsup/cygwin/fhandler_proc.cc +++ b/winsup/cygwin/fhandler_proc.cc @@ -1,6 +1,6 @@ /* fhandler_proc.cc: fhandler for /proc virtual filesystem - Copyright 2002, 2003, 2004, 2005, 2006 Red Hat, Inc. + Copyright 2002, 2003, 2004, 2005, 2006, 2007 Red Hat, Inc. This file is part of Cygwin. @@ -44,6 +44,7 @@ static const int PROC_PARTITIONS = 9; // /proc/partitions static const int PROC_SELF = 10; // /proc/self static const int PROC_REGISTRY32 = 11; // /proc/registry32 static const int PROC_REGISTRY64 = 12; // /proc/registry64 +static const int PROC_NET = 13; // /proc/net /* names of objects in /proc */ static const char *proc_listing[] = { @@ -60,6 +61,7 @@ static const char *proc_listing[] = { "self", "registry32", "registry64", + "net", NULL }; @@ -82,6 +84,7 @@ static const DWORD proc_fhandlers[PROC_LINK_COUNT] = { FH_PROC, FH_REGISTRY, FH_REGISTRY, + FH_PROCNET, }; /* name of the /proc filesystem */ diff --git a/winsup/cygwin/fhandler_procnet.cc b/winsup/cygwin/fhandler_procnet.cc new file mode 100644 index 000000000..e5026ef88 --- /dev/null +++ b/winsup/cygwin/fhandler_procnet.cc @@ -0,0 +1,442 @@ +/* fhandler_procnet.cc: fhandler for /proc/net virtual filesystem + + Copyright 2007 Red Hat, Inc. + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#define __INSIDE_CYGWIN_NET__ + +#include "winsup.h" +#include "cygerrno.h" +#include "security.h" +#include "path.h" +#include "fhandler.h" +#include "dtable.h" +#include "cygheap.h" + +#include +#define USE_SYS_TYPES_FD_SET +#include +#include +#include "cygwin/in6.h" + +#define _COMPILING_NEWLIB +#include +#include +#include +#include + +#ifndef GAA_FLAG_INCLUDE_ALL_INTERFACES +#define GAA_FLAG_INCLUDE_ALL_INTERFACES 0x0100 +#endif + +static const int PROCNET_IFINET6 = 2; + +static const char * const process_listing[] = +{ + ".", + "..", + "if_inet6", + NULL +}; + +static const int PROCESS_LINK_COUNT = + (sizeof (process_listing) / sizeof (const char *)) - 1; + +static _off64_t format_procnet_ifinet6 (char *&filebuf); + +/* Returns 0 if path doesn't exist, >0 if path is a directory, + * -1 if path is a file, -2 if path is a symlink, -3 if path is a pipe, + * -4 if path is a socket. + */ +int +fhandler_procnet::exists () +{ + const char *path = get_name (); + debug_printf ("exists (%s)", path); + path += proc_len + 1; + while (*path != 0 && !isdirsep (*path)) + path++; + if (*path == 0) + return 1; + + for (int i = 0; process_listing[i]; i++) + if (pathmatch (path + 1, process_listing[i])) + { + if (i == PROCNET_IFINET6) + { + ULONG size; + if (GetAdaptersAddresses (AF_INET6, + GAA_FLAG_INCLUDE_PREFIX + | GAA_FLAG_INCLUDE_ALL_INTERFACES, + NULL, NULL, &size) + != ERROR_BUFFER_OVERFLOW) + return 0; + } + fileid = i; + return -1; + } + return 0; +} + +fhandler_procnet::fhandler_procnet (): + fhandler_proc () +{ +} + +int +fhandler_procnet::fstat (struct __stat64 *buf) +{ + fhandler_base::fstat (buf); + buf->st_mode &= ~_IFMT & NO_W; + int file_type = exists (); + switch (file_type) + { + case 0: + set_errno (ENOENT); + return -1; + case 1: + case 2: + buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH; + buf->st_nlink = 2; + return 0; + case -1: + default: + buf->st_mode |= S_IFREG | S_IRUSR | S_IRGRP | S_IROTH; + return 0; + } +} + +DIR * +fhandler_procnet::opendir () +{ + DIR *dir = fhandler_virtual::opendir (); + if (dir) + dir->__flags = 0; + return dir; +} + +int +fhandler_procnet::readdir (DIR *dir, dirent *de) +{ + int res = ENMFILE; + if (dir->__d_position >= PROCESS_LINK_COUNT) + goto out; + if (dir->__d_position == PROCNET_IFINET6) + { + ULONG size; + if (GetAdaptersAddresses (AF_INET6, + GAA_FLAG_INCLUDE_PREFIX + | GAA_FLAG_INCLUDE_ALL_INTERFACES, + NULL, NULL, &size) + != ERROR_BUFFER_OVERFLOW) + goto out; + } + strcpy (de->d_name, process_listing[dir->__d_position++]); + dir->__flags |= dirent_saw_dot | dirent_saw_dot_dot; + res = 0; +out: + syscall_printf ("%d = readdir (%p, %p) (%s)", res, dir, de, de->d_name); + return res; +} + +int +fhandler_procnet::open (int flags, mode_t mode) +{ + int process_file_no = -1; + + int res = fhandler_virtual::open (flags, mode); + if (!res) + goto out; + + nohandle (true); + + const char *path; + path = get_name () + proc_len + 1; + while (*path != 0 && !isdirsep (*path)) + path++; + + if (*path == 0) + { + if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) + { + set_errno (EEXIST); + res = 0; + goto out; + } + else if (flags & O_WRONLY) + { + set_errno (EISDIR); + res = 0; + goto out; + } + else + { + flags |= O_DIROPEN; + goto success; + } + } + + process_file_no = -1; + for (int i = 0; process_listing[i]; i++) + { + if (path_prefix_p + (process_listing[i], path + 1, strlen (process_listing[i]))) + process_file_no = i; + } + if (process_file_no == -1) + { + if (flags & O_CREAT) + { + set_errno (EROFS); + res = 0; + goto out; + } + else + { + set_errno (ENOENT); + res = 0; + goto out; + } + } + if (flags & O_WRONLY) + { + set_errno (EROFS); + res = 0; + goto out; + } + + fileid = process_file_no; + if (!fill_filebuf ()) + { + res = 0; + goto out; + } + + if (flags & O_APPEND) + position = filesize; + else + position = 0; + +success: + res = 1; + set_flags ((flags & ~O_TEXT) | O_BINARY); + set_open_status (); +out: + syscall_printf ("%d = fhandler_proc::open (%p, %d)", res, flags, mode); + return res; +} + +bool +fhandler_procnet::fill_filebuf () +{ + switch (fileid) + { + case PROCNET_IFINET6: + { + bufalloc = filesize = format_procnet_ifinet6 (filebuf); + break; + } + } + + return true; +} + +static int in6_are_prefix_equal(struct in6_addr *, struct in6_addr *, int); + +/* Vista: unicast address has additional OnLinkPrefixLength member. */ +typedef struct _IP_ADAPTER_UNICAST_ADDRESS_VISTA { + _ANONYMOUS_UNION union { + ULONGLONG Alignment; + _ANONYMOUS_UNION struct { + ULONG Length; + DWORD Flags; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; + struct _IP_ADAPTER_UNICAST_ADDRESS_VISTA *Next; + SOCKET_ADDRESS Address; + + IP_PREFIX_ORIGIN PrefixOrigin; + IP_SUFFIX_ORIGIN SuffixOrigin; + IP_DAD_STATE DadState; + + ULONG ValidLifetime; + ULONG PreferredLifetime; + ULONG LeaseLifetime; + unsigned char OnLinkPrefixLength; +} IP_ADAPTER_UNICAST_ADDRESS_VISTA, *PIP_ADAPTER_UNICAST_ADDRESS_VISTA; + +int +prefix (PIP_ADAPTER_UNICAST_ADDRESS pua, PIP_ADAPTER_PREFIX pap) +{ + if (wincap.has_gaa_on_link_prefix ()) + return (int) ((PIP_ADAPTER_UNICAST_ADDRESS_VISTA) pua)->OnLinkPrefixLength; + /* Prior to Vista, the loopback prefix is erroneously set to 0 instead + of to 128. So just fake it here... */ + if (IN6_IS_ADDR_LOOPBACK (&((struct sockaddr_in6 *) + pua->Address.lpSockaddr)->sin6_addr)) + return 128; + /* XP prior to service pack 1 has no prefixes linked list. Let's fake. */ + if (!wincap.has_gaa_prefixes ()) + return 64; + for ( ; pap; pap = pap->Next) + if (in6_are_prefix_equal ( + &((struct sockaddr_in6 *) pua->Address.lpSockaddr)->sin6_addr, + &((struct sockaddr_in6 *) pap->Address.lpSockaddr)->sin6_addr, + pap->PrefixLength)) + return pap->PrefixLength; + return 0; +} + +static _off64_t +format_procnet_ifinet6 (char *&filebuf) +{ + PIP_ADAPTER_ADDRESSES pa0 = NULL, pap; + PIP_ADAPTER_UNICAST_ADDRESS pua; + ULONG ret, size = 0, alloclen; + + _off64_t filesize = 0; + do + { + ret = GetAdaptersAddresses (AF_INET6, GAA_FLAG_INCLUDE_PREFIX + | GAA_FLAG_INCLUDE_ALL_INTERFACES, + NULL, pa0, &size); + if (ret == ERROR_BUFFER_OVERFLOW) + { + if (pa0) + free (pa0); + pa0 = (PIP_ADAPTER_ADDRESSES) malloc (size); + } + } + while (ret == ERROR_BUFFER_OVERFLOW); + if (ret != ERROR_SUCCESS) + { + if (pa0) + free (pa0); + return 0; + } + alloclen = 0; + for (pap = pa0; pap; pap = pap->Next) + { + ULONG namelen = wcslen (pap->FriendlyName); + for (pua = pap->FirstUnicastAddress; pua; pua = pua->Next) + alloclen += 60 + namelen; + } + filebuf = (char *) crealloc (filebuf, alloclen); + filesize = 0; + for (pap = pa0; pap; pap = pap->Next) + for (pua = pap->FirstUnicastAddress; pua; pua = pua->Next) + { + ULONG namelen = wcslen (pap->FriendlyName); + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) + pua->Address.lpSockaddr; + for (int i = 0; i < 8; ++i) + /* __small_sprintf generates upper-case hex. */ + filesize += sprintf (filebuf + filesize, "%04x", + ntohs (sin6->sin6_addr.s6_addr16[i])); + filebuf[filesize++] = ' '; + filesize += __small_sprintf (filebuf + filesize, + "%02x %02x %02x %02x ", + pap->Ipv6IfIndex, + prefix (pua, pap->FirstPrefix), + ((struct sockaddr_in6 *) + pua->Address.lpSockaddr)->sin6_scope_id, + pua->DadState); + filesize += sys_wcstombs (filebuf + filesize, alloclen - filesize, + pap->FriendlyName, namelen); + filebuf[filesize++] = '\n'; + } + if (!filesize) + filebuf[filesize++] = '\n'; + return filesize; +} + +/* The below function has been taken from OpenBSD's src/sys/netinet6/in6.c. */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1982, 1986, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)in.c 8.2 (Berkeley) 11/15/93 + */ + +static int +in6_are_prefix_equal(struct in6_addr *p1, struct in6_addr *p2, int len) +{ + int bytelen, bitlen; + + /* sanity check */ + if (0 > len || len > 128) + return 0; + + bytelen = len / 8; + bitlen = len % 8; + + if (memcmp (&p1->s6_addr, &p2->s6_addr, bytelen)) + return 0; + /* len == 128 is ok because bitlen == 0 then */ + if (bitlen != 0 && + p1->s6_addr[bytelen] >> (8 - bitlen) != + p2->s6_addr[bytelen] >> (8 - bitlen)) + return 0; + + return 1; +} + diff --git a/winsup/cygwin/include/cygwin/in6.h b/winsup/cygwin/include/cygwin/in6.h index bdb812c99..febd8dc73 100644 --- a/winsup/cygwin/include/cygwin/in6.h +++ b/winsup/cygwin/include/cygwin/in6.h @@ -13,6 +13,8 @@ details. */ #ifndef _CYGWIN_IN6_H #define _CYGWIN_IN6_H +#include + #define INET6_ADDRSTRLEN 46 #define IN6_ARE_ADDR_EQUAL(a, b) \ diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 287c6f69b..2673a9462 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -1,6 +1,7 @@ /* path.cc: path support. - Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc. + Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + 2006, 2007 Red Hat, Inc. This file is part of Cygwin. @@ -159,10 +160,6 @@ struct win_shortcut_hdr #define isproc(path) \ (path_prefix_p (proc, (path), proc_len)) -#define isvirtual_dev(devn) \ - (devn == FH_CYGDRIVE || devn == FH_PROC || devn == FH_REGISTRY \ - || devn == FH_PROCESS || devn == FH_NETDRIVE ) - /* Return non-zero if PATH1 is a prefix of PATH2. Both are assumed to be of the same path style and / vs \ usage. Neither may be "". diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index 9b4c85ea2..336353a4b 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -1,7 +1,7 @@ /* path.h: path data structures Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, - 2006 Red Hat, Inc. + 2006, 2007 Red Hat, Inc. This file is part of Cygwin. @@ -15,6 +15,13 @@ details. */ #include #include +#define isproc_dev(devn) \ + (devn == FH_PROC || devn == FH_REGISTRY || devn == FH_PROCESS || \ + devn == FH_PROCNET) + +#define isvirtual_dev(devn) \ + (isproc_dev (devn) || devn == FH_CYGDRIVE || devn == FH_NETDRIVE) + extern PUNICODE_STRING get_nt_native_path (const char *, UNICODE_STRING &); inline bool diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 982e19589..85a43818d 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -343,8 +343,8 @@ unlink (const char *ourname) goto done; } - if ((devn = win32_name.get_devn ()) == FH_PROC || devn == FH_REGISTRY - || devn == FH_PROCESS) + devn = win32_name.get_devn (); + if (isproc_dev (devn)) { set_errno (EROFS); goto done; diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc index 730263415..d9aa59093 100644 --- a/winsup/cygwin/wincap.cc +++ b/winsup/cygwin/wincap.cc @@ -1,7 +1,7 @@ /* wincap.cc -- figure out on which OS we're running. Set the capability class to the appropriate values. - Copyright 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc. + Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 Red Hat, Inc. This file is part of Cygwin. @@ -72,6 +72,8 @@ static NO_COPY wincaps wincap_unknown = { needs_logon_sid_in_sid_list:false, needs_count_in_si_lpres2:false, has_recycle_dot_bin:false, + has_gaa_prefixes:false, + has_gaa_on_link_prefix:false, }; static NO_COPY wincaps wincap_95 = { @@ -135,6 +137,8 @@ static NO_COPY wincaps wincap_95 = { needs_logon_sid_in_sid_list:false, needs_count_in_si_lpres2:false, has_recycle_dot_bin:false, + has_gaa_prefixes:false, + has_gaa_on_link_prefix:false, }; static NO_COPY wincaps wincap_95osr2 = { @@ -198,6 +202,8 @@ static NO_COPY wincaps wincap_95osr2 = { needs_logon_sid_in_sid_list:false, needs_count_in_si_lpres2:false, has_recycle_dot_bin:false, + has_gaa_prefixes:false, + has_gaa_on_link_prefix:false, }; static NO_COPY wincaps wincap_98 = { @@ -261,6 +267,8 @@ static NO_COPY wincaps wincap_98 = { needs_logon_sid_in_sid_list:false, needs_count_in_si_lpres2:false, has_recycle_dot_bin:false, + has_gaa_prefixes:false, + has_gaa_on_link_prefix:false, }; static NO_COPY wincaps wincap_98se = { @@ -324,6 +332,8 @@ static NO_COPY wincaps wincap_98se = { needs_logon_sid_in_sid_list:false, needs_count_in_si_lpres2:false, has_recycle_dot_bin:false, + has_gaa_prefixes:false, + has_gaa_on_link_prefix:false, }; static NO_COPY wincaps wincap_me = { @@ -387,6 +397,8 @@ static NO_COPY wincaps wincap_me = { needs_logon_sid_in_sid_list:false, needs_count_in_si_lpres2:false, has_recycle_dot_bin:false, + has_gaa_prefixes:false, + has_gaa_on_link_prefix:false, }; static NO_COPY wincaps wincap_nt3 = { @@ -450,6 +462,8 @@ static NO_COPY wincaps wincap_nt3 = { needs_logon_sid_in_sid_list:true, needs_count_in_si_lpres2:false, has_recycle_dot_bin:false, + has_gaa_prefixes:false, + has_gaa_on_link_prefix:false, }; static NO_COPY wincaps wincap_nt4 = { @@ -513,6 +527,8 @@ static NO_COPY wincaps wincap_nt4 = { needs_logon_sid_in_sid_list:true, needs_count_in_si_lpres2:false, has_recycle_dot_bin:false, + has_gaa_prefixes:false, + has_gaa_on_link_prefix:false, }; static NO_COPY wincaps wincap_nt4sp4 = { @@ -576,6 +592,8 @@ static NO_COPY wincaps wincap_nt4sp4 = { needs_logon_sid_in_sid_list:true, needs_count_in_si_lpres2:false, has_recycle_dot_bin:false, + has_gaa_prefixes:false, + has_gaa_on_link_prefix:false, }; static NO_COPY wincaps wincap_2000 = { @@ -639,6 +657,8 @@ static NO_COPY wincaps wincap_2000 = { needs_logon_sid_in_sid_list:true, needs_count_in_si_lpres2:false, has_recycle_dot_bin:false, + has_gaa_prefixes:false, + has_gaa_on_link_prefix:false, }; static NO_COPY wincaps wincap_xp = { @@ -702,6 +722,8 @@ static NO_COPY wincaps wincap_xp = { needs_logon_sid_in_sid_list:false, needs_count_in_si_lpres2:false, has_recycle_dot_bin:false, + has_gaa_prefixes:false, + has_gaa_on_link_prefix:false, }; static NO_COPY wincaps wincap_2003 = { @@ -765,6 +787,8 @@ static NO_COPY wincaps wincap_2003 = { needs_logon_sid_in_sid_list:false, needs_count_in_si_lpres2:false, has_recycle_dot_bin:false, + has_gaa_prefixes:true, + has_gaa_on_link_prefix:false, }; static NO_COPY wincaps wincap_vista = { @@ -773,7 +797,7 @@ static NO_COPY wincaps wincap_vista = { heapslop:0x4, shared:FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, is_winnt:true, - is_server:true, + is_server:false, access_denied_on_delete:false, has_delete_on_close:true, has_page_guard:true, @@ -828,6 +852,8 @@ static NO_COPY wincaps wincap_vista = { needs_logon_sid_in_sid_list:false, needs_count_in_si_lpres2:true, has_recycle_dot_bin:true, + has_gaa_prefixes:true, + has_gaa_on_link_prefix:true, }; wincapc wincap __attribute__((section (".cygwin_dll_common"), shared)); @@ -877,6 +903,8 @@ wincapc::init () case 1: caps = &wincap_xp; + if (strcmp (version.szCSDVersion, "Service Pack 1") >= 0) + ((wincaps *)this->caps)->has_gaa_prefixes = true; break; default: diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h index 896f61109..de5d9a8d4 100644 --- a/winsup/cygwin/wincap.h +++ b/winsup/cygwin/wincap.h @@ -1,6 +1,6 @@ /* wincap.h: Header for OS capability class. - Copyright 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc. + Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 Red Hat, Inc. This file is part of Cygwin. @@ -73,6 +73,8 @@ struct wincaps unsigned needs_logon_sid_in_sid_list : 1; unsigned needs_count_in_si_lpres2 : 1; unsigned has_recycle_dot_bin : 1; + unsigned has_gaa_prefixes : 1; + unsigned has_gaa_on_link_prefix : 1; }; class wincapc @@ -152,6 +154,8 @@ public: bool IMPLEMENT (needs_logon_sid_in_sid_list) bool IMPLEMENT (needs_count_in_si_lpres2) bool IMPLEMENT (has_recycle_dot_bin) + bool IMPLEMENT (has_gaa_prefixes) + bool IMPLEMENT (has_gaa_on_link_prefix) #undef IMPLEMENT };