Re: [gtk-vnc-devel] PATCH: Portability to compile under MinGW for Windows
- From: "Daniel P. Berrange" <berrange redhat com>
- To: "Richard W.M. Jones" <rjones redhat com>
- Cc: gtk-vnc-devel <gtk-vnc-devel lists sourceforge net>
- Subject: Re: [gtk-vnc-devel] PATCH: Portability to compile under MinGW for Windows
- Date: Thu, 9 Oct 2008 15:16:25 +0100
On Thu, Oct 09, 2008 at 02:06:11PM +0100, Daniel P. Berrange wrote:
> On Thu, Oct 09, 2008 at 01:03:11PM +0100, Richard W.M. Jones wrote:
> > On Wed, Oct 08, 2008 at 07:52:50PM +0100, Daniel P. Berrange wrote:
> > > +modules='
> > > +getaddrinfo
> > > +vc-list-files
> > > +'
> >
> > This didn't quite work for me. I'm not sure if it's because we're
> > using different versions of gnulib (I'm using the absolute latest
> > version). But I also needed the following modules to be added to the
> > above list:
> >
> > recv
> > send
> > socket
> > connect
>
> That shouldn't be needed - they're all provided by winsock, and
> the neccessary header is included by sockcompat.h. So I thing
> something else must have gone wrong. libvirt doesn't use those
> modules either
Turns out the bootstrap script wasn't actually pulling latest files
from gnulib. Now I've properly updated I see same thing. It appears
that gnulib now provides recv/socket/send/etc wrappers for Windows.
In addition their wrappers ensure that you can still use regular
read/write calls on sockets, and makes errno work properly. So this
reduces the diff for gvnc.c code. Attached is an update
Daniel
--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
diff -r f1d5c8fae2e9 .hgignore
--- a/.hgignore Fri Sep 05 13:32:03 2008 +0100
+++ b/.hgignore Thu Oct 09 09:41:14 2008 -0400
@@ -24,7 +24,7 @@
^build
^examples/\.deps/
^examples/\.libs/
-^examples/gvncviewer$
+^examples/gvncviewer(\.exe)?$
^missing$
^INSTALL$
^depcomp$
@@ -36,9 +36,9 @@
^plugin/gtk-vnc-plugin.la$
^plugin/gtk_vnc_plugin_la-.*
^plugin/gtk-vnc-plugin.so
-
-syntax: glob
-examples/*.o
-src/*.defs
-src/*.orig
-*.spec
+.gnulib
+examples/.*\.o
+src/.*\.defs
+src/.*\.orig
+.*\.spec
+.*\.tar\.gz$
diff -r f1d5c8fae2e9 Makefile.am
--- a/Makefile.am Fri Sep 05 13:32:03 2008 +0100
+++ b/Makefile.am Thu Oct 09 09:41:14 2008 -0400
@@ -1,5 +1,9 @@
-SUBDIRS = src examples plugin
+SUBDIRS = gnulib/lib src examples plugin gnulib/tests
+
+ACLOCAL_AMFLAGS = -I gnulib/m4
+
+
pkgconfig_DATA = @PACKAGE -1 0 pc
pkgconfigdir = $(libdir)/pkgconfig
diff -r f1d5c8fae2e9 autogen.sh
--- a/autogen.sh Fri Sep 05 13:32:03 2008 +0100
+++ b/autogen.sh Thu Oct 09 09:41:14 2008 -0400
@@ -45,7 +45,7 @@
fi
libtoolize --copy --force
-aclocal
+aclocal -I gnulib/m4
autoheader
automake --add-missing --copy
autoconf
diff -r f1d5c8fae2e9 bootstrap
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bootstrap Thu Oct 09 09:41:14 2008 -0400
@@ -0,0 +1,89 @@
+#!/bin/sh
+# Run this after autogen.sh, to pull in all of the gnulib-related bits.
+# It's important to run *after* autogen.sh, since it updates some of
+# the same files autogen.sh does, yet those from gnulib are newer,
+# and match the tests. So if a gnulib bug has been fixed since the
+# snapshot taken for whatever gettext release you're using, yet you
+# run "make check" against the wrong version, the corresponding unit
+# test in gl-tests/ may well fail.
+
+usage() {
+ echo >&2 "\
+Usage: $0 [OPTION]...
+Bootstrap this package from the checked-out sources.
+
+Options:
+ --gnulib-srcdir=DIRNAME Specify the local directory where gnulib
+ sources reside. Use this if you already
+ have gnulib sources on your machine, and
+ do not want to waste your bandwidth downloading
+ them again.
+
+If the file bootstrap.conf exists in the current working directory, its
+contents are read as shell variables to configure the bootstrap.
+
+Running without arguments will suffice in most cases.
+"
+}
+
+for option
+do
+ case $option in
+ --help)
+ usage
+ exit;;
+ --gnulib-srcdir=*)
+ GNULIB_SRCDIR=`expr "$option" : '--gnulib-srcdir=\(.*\)'`;;
+ *)
+ echo >&2 "$0: $option: unknown option"
+ exit 1;;
+ esac
+done
+
+cleanup_gnulib() {
+ st=$?
+ rm -fr .gnulib
+ exit $st
+}
+
+case ${GNULIB_SRCDIR--} in
+-)
+ if [ ! -d .gnulib ]; then
+ echo "$0: getting gnulib files..."
+
+ trap cleanup_gnulib 1 2 13 15
+
+ git clone --depth 1 git://git.sv.gnu.org/gnulib .gnulib ||
+ cleanup_gnulib
+
+ trap - 1 2 13 15
+ fi
+ GNULIB_SRCDIR=.gnulib
+esac
+
+gnulib_tool=$GNULIB_SRCDIR/gnulib-tool
+<$gnulib_tool || exit
+
+modules='
+getaddrinfo
+socket
+recv
+send
+connect
+malloc
+vc-list-files
+'
+
+# Tell gnulib to:
+# require LGPLv2+
+# put *.m4 files in new gnulib/m4/ dir
+# put *.[ch] files in new gnulib/lib/ dir.
+
+$gnulib_tool \
+ --lgpl=2 \
+ --with-tests \
+ --m4-base=gnulib/m4 \
+ --source-base=gnulib/lib \
+ --tests-base=gnulib/tests \
+ --import $modules
+
diff -r f1d5c8fae2e9 configure.ac
--- a/configure.ac Fri Sep 05 13:32:03 2008 +0100
+++ b/configure.ac Thu Oct 09 09:41:14 2008 -0400
@@ -23,14 +23,28 @@
AC_CONFIG_HEADERS([config.h:config.hin])
-
AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE(gtk-vnc, 0.3.7)
+
+dnl gl_INIT uses m4_foreach_w, yet that is not defined in autoconf-2.59.
+dnl In order to accommodate developers with such old tools, here's a
+dnl replacement definition.
+m4_ifndef([m4_foreach_w],
+ [m4_define([m4_foreach_w],
+ [m4_foreach([$1], m4_split(m4_normalize([$2]), [ ]), [$3])])])
+
+gl_EARLY
+gl_INIT
+
AC_PROG_CC_STDC
AM_PROG_CC_C_O
+AC_LIBTOOL_WIN32_DLL
+
AC_PROG_LIBTOOL
+
+AC_CHECK_HEADERS([pwd.h winsock2.h])
AC_ARG_WITH(python,
[ --with-python build python bindings],
@@ -234,6 +248,8 @@
AC_CONFIG_FILES(
Makefile
+ gnulib/lib/Makefile
+ gnulib/tests/Makefile
src/Makefile
examples/Makefile
plugin/Makefile
diff -r f1d5c8fae2e9 src/Makefile.am
--- a/src/Makefile.am Fri Sep 05 13:32:03 2008 +0100
+++ b/src/Makefile.am Thu Oct 09 09:41:14 2008 -0400
@@ -4,13 +4,15 @@
lib_LTLIBRARIES = libgtk-vnc-1.0.la
libgtk_vnc_1_0_la_LIBADD = @GTK_LIBS@ @GTKGLEXT_LIBS@ @GNUTLS_LIBS@ \
- @GTHREAD_LIBS@
+ @GTHREAD_LIBS@ \
+ ../gnulib/lib/libgnu.la
libgtk_vnc_1_0_la_CFLAGS = @GTK_CFLAGS@ @GTKGLEXT_CFLAGS@ @GNUTLS_CFLAGS@ \
@GTHREAD_CFLAGS@ @WARNING_CFLAGS@ \
-DSYSCONFDIR=\""$(sysconfdir)"\" \
- -DG_LOG_DOMAIN=\"gtk-vnc\"
+ -DG_LOG_DOMAIN=\"gtk-vnc\" \
+ -I$(top_srcdir)gnulib/lib -I../gnulib/lib
libgtk_vnc_1_0_la_LDFLAGS = -Wl, @LD_VERSION_SCRIPT_SUPPORT@ \
- -version-info 0:1:0
+ -version-info 0:1:0 -no-undefined
gtk_vnc_includedir = $(includedir)/gtk-vnc-1.0/
gtk_vnc_include_HEADERS = vncdisplay.h
diff -r f1d5c8fae2e9 src/continuation.c
--- a/src/continuation.c Fri Sep 05 13:32:03 2008 +0100
+++ b/src/continuation.c Thu Oct 09 09:41:14 2008 -0400
@@ -7,6 +7,8 @@
*
* GTK VNC Widget
*/
+
+#include <config.h>
#include "continuation.h"
diff -r f1d5c8fae2e9 src/coroutine_gthread.c
--- a/src/coroutine_gthread.c Fri Sep 05 13:32:03 2008 +0100
+++ b/src/coroutine_gthread.c Thu Oct 09 09:41:14 2008 -0400
@@ -8,6 +8,8 @@
* GTK VNC Widget
*/
+#include <config.h>
+
#include "coroutine.h"
#include <stdio.h>
#include <stdlib.h>
@@ -17,13 +19,24 @@
static struct coroutine *current;
static struct coroutine leader;
+#if 0
+#define CO_DEBUG(OP) fprintf(stderr, "%s %p %s %d\n", OP, g_thread_self(), __FUNCTION__, __LINE__)
+#else
+#define CO_DEBUG(OP)
+#endif
+
static void coroutine_system_init(void)
{
- if (!g_thread_supported())
+ if (!g_thread_supported()) {
+ CO_DEBUG("INIT");
g_thread_init(NULL);
+ }
+
run_cond = g_cond_new();
run_lock = g_mutex_new();
+ CO_DEBUG("LOCK");
+ g_mutex_lock(run_lock);
/* The thread that creates the first coroutine is the system coroutine
* so let's fill out a structure for it */
@@ -42,17 +55,22 @@
static gpointer coroutine_thread(gpointer opaque)
{
struct coroutine *co = opaque;
+ CO_DEBUG("LOCK");
+ g_mutex_lock(run_lock);
+ while (!co->runnable) {
+ CO_DEBUG("WAIT");
+ g_cond_wait(run_cond, run_lock);
+ }
- g_mutex_lock(run_lock);
- while (!co->runnable)
- g_cond_wait(run_cond, run_lock);
-
+ CO_DEBUG("RUNNABLE");
current = co;
co->data = co->entry(co->data);
co->exited = 1;
co->caller->runnable = TRUE;
+ CO_DEBUG("BROADCAST");
g_cond_broadcast(run_cond);
+ CO_DEBUG("UNLOCK");
g_mutex_unlock(run_lock);
return NULL;
@@ -62,7 +80,8 @@
{
if (run_cond == NULL)
coroutine_system_init();
-
+
+ CO_DEBUG("NEW");
co->thread = g_thread_create_full(coroutine_thread, co, co->stack_size,
FALSE, TRUE,
G_THREAD_PRIORITY_NORMAL,
@@ -88,15 +107,19 @@
to->runnable = TRUE;
to->data = arg;
to->caller = from;
+ CO_DEBUG("BROADCAST");
g_cond_broadcast(run_cond);
+ CO_DEBUG("UNLOCK");
g_mutex_unlock(run_lock);
-
+ CO_DEBUG("LOCK");
g_mutex_lock(run_lock);
- while (!from->runnable)
+ while (!from->runnable) {
+ CO_DEBUG("WAIT");
g_cond_wait(run_cond, run_lock);
-
+ }
current = from;
+ CO_DEBUG("SWAPPED");
return from->data;
}
@@ -111,6 +134,7 @@
fprintf(stderr, "Co-routine is re-entering itself\n");
abort();
}
+ CO_DEBUG("SWAP");
return coroutine_swap(coroutine_self(), to, arg);
}
@@ -121,6 +145,8 @@
fprintf(stderr, "Co-routine is yielding to no one\n");
abort();
}
+
+ CO_DEBUG("SWAP");
coroutine_self()->caller = NULL;
return coroutine_swap(coroutine_self(), to, arg);
}
diff -r f1d5c8fae2e9 src/coroutine_ucontext.c
--- a/src/coroutine_ucontext.c Fri Sep 05 13:32:03 2008 +0100
+++ b/src/coroutine_ucontext.c Thu Oct 09 09:41:14 2008 -0400
@@ -7,6 +7,8 @@
*
* GTK VNC Widget
*/
+
+#include <config.h>
#include <sys/types.h>
#include <sys/mman.h>
diff -r f1d5c8fae2e9 src/gvnc.c
--- a/src/gvnc.c Fri Sep 05 13:32:03 2008 +0100
+++ b/src/gvnc.c Thu Oct 09 09:41:14 2008 -0400
@@ -8,13 +8,14 @@
* GTK VNC Widget
*/
+#include <config.h>
+
#include "gvnc.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
-#include <netdb.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
@@ -40,6 +41,14 @@
#include <gdk/gdkkeysyms.h>
#include "vnc_keycodes.h"
+#include "getaddrinfo.h"
+
+/* AI_ADDRCONFIG is missing on some systems and gnulib won't provide it
+ even if its emulated getaddrinfo() for us . */
+#ifndef AI_ADDRCONFIG
+# define AI_ADDRCONFIG 0
+#endif
+
struct wait_queue
{
@@ -185,7 +194,6 @@
g_io_add_watch(channel, cond | G_IO_HUP | G_IO_ERR | G_IO_NVAL, g_io_wait_helper, coroutine_self());
ret = coroutine_yield(NULL);
-
return *ret;
}
@@ -344,7 +352,7 @@
size_t offset = 0;
if (gvnc->has_error) return -EINVAL;
-
+
while (offset < len) {
size_t tmp;
@@ -376,7 +384,7 @@
if (ret == -1) {
switch (errno) {
- case EAGAIN:
+ case EWOULDBLOCK:
if (gvnc->wait_interruptable) {
if (!g_io_wait_interruptable(&gvnc->wait,
gvnc->channel, G_IO_IN))
@@ -386,7 +394,7 @@
case EINTR:
continue;
default:
- GVNC_DEBUG("Closing the connection: gvnc_read() - ret=-1\n");
+ GVNC_DEBUG("Closing the connection: gvnc_read() - errno=%d\n", errno);
gvnc->has_error = TRUE;
return -errno;
}
@@ -436,12 +444,12 @@
gvnc->write_offset-offset);
if (ret == -1) {
switch (errno) {
- case EAGAIN:
+ case EWOULDBLOCK:
g_io_wait(gvnc->channel, G_IO_OUT);
case EINTR:
continue;
default:
- GVNC_DEBUG("Closing the connection: gvnc_flush\n");
+ GVNC_DEBUG("Closing the connection: gvnc_flush %d\n", errno);
gvnc->has_error = TRUE;
return;
}
@@ -1341,12 +1349,12 @@
static int gvnc_read_zrle_rl(struct gvnc *gvnc)
{
int rl = 1;
- uint8_t byte;
+ uint8_t b;
do {
- byte = gvnc_read_u8(gvnc);
- rl += byte;
- } while (!gvnc_has_error(gvnc) && byte == 255);
+ b = gvnc_read_u8(gvnc);
+ rl += b;
+ } while (!gvnc_has_error(gvnc) && b == 255);
return rl;
}
@@ -2802,12 +2810,12 @@
if (gvnc_has_error(gvnc))
return FALSE;
- if (!gvnc->fmt.true_color_flag && gvnc->ops.get_preferred_pixel_format)
+ if (!gvnc->fmt.true_color_flag && gvnc->ops.get_preferred_pixel_format) {
if (gvnc->ops.get_preferred_pixel_format(gvnc->ops_data, &gvnc->fmt))
gvnc_set_pixel_format(gvnc, &gvnc->fmt);
else
goto fail;
-
+ }
memset(&gvnc->strm, 0, sizeof(gvnc->strm));
/* FIXME what level? */
for (i = 0; i < 5; i++)
@@ -2822,15 +2830,16 @@
return !gvnc_has_error(gvnc);
}
-gboolean gvnc_open_fd(struct gvnc *gvnc, int fd)
+static gboolean gvnc_set_nonblock(int fd)
{
- int flags;
- if (gvnc_is_open(gvnc)) {
- GVNC_DEBUG ("Error: already connected?\n");
+#ifdef __MINGW32__
+ unsigned long flags = 1;
+ if (ioctlsocket(fd, FIONBIO, &flags) < 0) {
+ GVNC_DEBUG ("Failed to set nonblocking flag\n");
return FALSE;
}
-
- GVNC_DEBUG("Connecting to FD %d\n", fd);
+#else
+ int flags;
if ((flags = fcntl(fd, F_GETFL)) < 0) {
GVNC_DEBUG ("Failed to fcntl()\n");
return FALSE;
@@ -2840,6 +2849,21 @@
GVNC_DEBUG ("Failed to fcntl()\n");
return FALSE;
}
+#endif
+ return TRUE;
+}
+
+gboolean gvnc_open_fd(struct gvnc *gvnc, int fd)
+{
+ if (gvnc_is_open(gvnc)) {
+ GVNC_DEBUG ("Error: already connected?\n");
+ return FALSE;
+ }
+
+ GVNC_DEBUG("Connecting to FD %d\n", fd);
+
+ if (!gvnc_set_nonblock(fd))
+ return FALSE;
if (!(gvnc->channel = g_io_channel_unix_new(fd))) {
GVNC_DEBUG ("Failed to g_io_channel_unix_new()\n");
@@ -2873,7 +2897,7 @@
runp = ai;
while (runp != NULL) {
- int flags, fd;
+ int fd;
GIOChannel *chan;
if ((fd = socket(runp->ai_family, runp->ai_socktype,
@@ -2883,17 +2907,8 @@
}
GVNC_DEBUG("Trying socket %d\n", fd);
- if ((flags = fcntl(fd, F_GETFL)) < 0) {
- close(fd);
- GVNC_DEBUG ("Failed to fcntl()\n");
- break;
- }
- flags |= O_NONBLOCK;
- if (fcntl(fd, F_SETFL, flags) < 0) {
- close(fd);
- GVNC_DEBUG ("Failed to fcntl()\n");
- break;
- }
+ if (!gvnc_set_nonblock(fd))
+ break;
if (!(chan = g_io_channel_unix_new(fd))) {
close(fd);
@@ -2904,14 +2919,15 @@
reconnect:
/* FIXME: Better handle EINPROGRESS/EISCONN return values,
as explained in connect(2) man page */
- if ( (connect(fd, runp->ai_addr, runp->ai_addrlen) == 0) || errno == EISCONN) {
+ if ((connect(fd, runp->ai_addr, runp->ai_addrlen) == 0) ||
+ errno == EISCONN) {
gvnc->channel = chan;
gvnc->fd = fd;
freeaddrinfo(ai);
return !gvnc_has_error(gvnc);
}
-
- if (errno == EINPROGRESS) {
+ if (errno == EINPROGRESS ||
+ errno == EWOULDBLOCK) {
g_io_wait(chan, G_IO_OUT|G_IO_ERR|G_IO_HUP);
goto reconnect;
} else if (errno != ECONNREFUSED &&
diff -r f1d5c8fae2e9 src/vncdisplay.c
--- a/src/vncdisplay.c Fri Sep 05 13:32:03 2008 +0100
+++ b/src/vncdisplay.c Thu Oct 09 09:41:14 2008 -0400
@@ -7,6 +7,8 @@
*
* GTK VNC Widget
*/
+
+#include <config.h>
#include "vncdisplay.h"
#include "coroutine.h"
@@ -24,7 +26,9 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
+#ifdef HAVE_PWD_H
#include <pwd.h>
+#endif
#if WITH_GTKGLEXT
#include <gtk/gtkgl.h>
@@ -2192,33 +2196,44 @@
static int vnc_display_set_x509_credential(VncDisplay *obj, const char *name)
{
- char sysdir[PATH_MAX], userdir[PATH_MAX];
+ char file[PATH_MAX];
+ char sysdir[PATH_MAX];
+#ifndef __MINGW32__
+ char userdir[PATH_MAX];
struct passwd *pw;
- char file[PATH_MAX];
char *dirs[] = { sysdir, userdir };
+#else
+ char *dirs[] = { sysdir };
+#endif
strncpy(sysdir, SYSCONFDIR "/pki", PATH_MAX-1);
sysdir[PATH_MAX-1] = '\0';
+#ifndef __MINGW32__
if (!(pw = getpwuid(getuid())))
return TRUE;
snprintf(userdir, PATH_MAX-1, "%s/.pki", pw->pw_dir);
userdir[PATH_MAX-1] = '\0';
+#endif
- if (vnc_display_best_path(file, PATH_MAX, "CA", "cacert.pem", dirs, 2) < 0)
+ if (vnc_display_best_path(file, PATH_MAX, "CA", "cacert.pem",
+ dirs, sizeof(dirs)/sizeof(dirs[0])) < 0)
return TRUE;
gvnc_set_credential_x509_cacert(obj->priv->gvnc, file);
/* Don't mind failures of CRL */
- if (vnc_display_best_path(file, PATH_MAX, "CA", "cacrl.pem", dirs, 2) == 0)
+ if (vnc_display_best_path(file, PATH_MAX, "CA", "cacrl.pem",
+ dirs, sizeof(dirs)/sizeof(dirs[0])) == 0)
gvnc_set_credential_x509_cacert(obj->priv->gvnc, file);
/* Set client key & cert if we have them. Server will reject auth
* if it decides it requires them*/
- if (vnc_display_best_path(file, PATH_MAX, name, "private/clientkey.pem", dirs, 2) == 0)
+ if (vnc_display_best_path(file, PATH_MAX, name, "private/clientkey.pem",
+ dirs, sizeof(dirs)/sizeof(dirs[0])) == 0)
gvnc_set_credential_x509_key(obj->priv->gvnc, file);
- if (vnc_display_best_path(file, PATH_MAX, name, "clientcert.pem", dirs, 2) == 0)
+ if (vnc_display_best_path(file, PATH_MAX, name, "clientcert.pem",
+ dirs, sizeof(dirs)/sizeof(dirs[0])) == 0)
gvnc_set_credential_x509_cert(obj->priv->gvnc, file);
return FALSE;
diff -r f1d5c8fae2e9 vc-list-files
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vc-list-files Thu Oct 09 09:41:14 2008 -0400
@@ -0,0 +1,107 @@
+#!/bin/sh
+# List version-controlled file names.
+
+# Print a version string.
+scriptversion=2008-07-11.19
+
+# Copyright (C) 2006-2008 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+# List the specified version-controlled files.
+# With no argument, list them all. With a single DIRECTORY argument,
+# list the version-controlled files in that directory.
+
+# If there's an argument, it must be a single, "."-relative directory name.
+# cvsu is part of the cvsutils package: http://www.red-bean.com/cvsutils/
+
+postprocess=
+case $1 in
+ --help) cat <<EOF
+Usage: $0 [-C SRCDIR] [DIR]
+
+Output a list of version-controlled files in DIR (default .), relative to
+SRCDIR (default .). SRCDIR must be the top directory of a checkout.
+
+Options:
+ --help print this help, then exit
+ --version print version number, then exit
+ -C SRCDIR change directory to SRCDIR before generating list
+
+Report bugs and patches to <bug-gnulib gnu org>.
+EOF
+ exit ;;
+
+ --version)
+ year=`echo "$scriptversion" | sed 's/[^0-9].*//'`
+ cat <<EOF
+vc-list-files $scriptversion
+Copyright (C) $year Free Software Foundation, Inc,
+License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
+EOF
+ exit ;;
+
+ -C)
+ test "$2" = . || postprocess="| sed 's|^|$2/|'"
+ cd "$2" || exit 1
+ shift; shift ;;
+esac
+
+dir=
+case $# in
+ 0) ;;
+ 1) dir=$1 ;;
+ *) echo "$0: too many arguments" 1>&2
+ echo "Usage: $0 [-C srcdir] [DIR]" 1>&2; exit 1;;
+esac
+
+test "x$dir" = x && dir=.
+
+if test -d .git; then
+ eval exec git ls-files '"$dir"' $postprocess
+elif test -d .hg; then
+ eval exec hg locate '"$dir/*"' $postprocess
+elif test -d .bzr; then
+ test "$postprocess" = '' && postprocess="| sed 's|^\./||'"
+ eval exec bzr ls --versioned '"$dir"' $postprocess
+elif test -d CVS; then
+ test "$postprocess" = '' && postprocess="| sed 's|^\./||'"
+ if test -x build-aux/cvsu; then
+ eval build-aux/cvsu --find --types=AFGM '"$dir"' $postprocess
+ elif (cvsu --help) >/dev/null 2>&1; then
+ eval cvsu --find --types=AFGM '"$dir"' $postprocess
+ else
+ eval awk -F/ \''{ \
+ if (!$1 && $3 !~ /^-/) { \
+ f=FILENAME; \
+ if (f ~ /CVS\/Entries$/) \
+ f = substr(f, 0, length(f)-11); \
+ print f $2; \
+ }}'\'' \
+ `find "$dir" -name Entries -print` /dev/null' $postprocess
+ fi
+else
+ echo "$0: Failed to determine type of version control used in `pwd`" 1>&2
+ exit 1
+fi
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]