Subrata Modak <[EMAIL PROTECTED]> wrote:
> My observations/comments:
> 1) Get the latest source for the next patch. Some gave hunk failures,
> 2) Build, Install and Run is handled properly across all architectures
> and kernel versions. Go ahead and send the updated patch. I will merge
> them in increments. You can then go ahead and add more in the same
> category.

Hi Subrata,
thanks for the inputs. Here is the updated patch. 

Changelog:

   * Added basic testcases for eventfd.

Signed-off-by: Vijay Kumar <[EMAIL PROTECTED]>

 runtest/syscalls                              |    2 +
 testcases/kernel/include/i386.in              |    1 +
 testcases/kernel/include/ia64.in              |    1 +
 testcases/kernel/include/powerpc.in           |    1 +
 testcases/kernel/include/powerpc64.in         |    1 +
 testcases/kernel/include/s390.in              |    1 +
 testcases/kernel/include/s390x.in             |    1 +
 testcases/kernel/include/sparc.in             |    1 +
 testcases/kernel/include/sparc64.in           |    1 +
 testcases/kernel/include/stub-list            |    1 +
 testcases/kernel/include/x86_64.in            |    1 +
 testcases/kernel/syscalls/eventfd/Makefile    |   32 ++
 testcases/kernel/syscalls/eventfd/eventfd01.c |  582 +++++++++++++++++++++++++
 13 files changed, 626 insertions(+), 0 deletions(-)

diff --git a/runtest/syscalls b/runtest/syscalls
index 40a6d36..234027c 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -101,6 +101,8 @@ dup203 dup203
 dup204 dup204
 dup205 dup205
 
+eventfd01 eventfd01
+
 execl01 execl01
 execle01 execle01
 execlp01 execlp01
diff --git a/testcases/kernel/include/i386.in b/testcases/kernel/include/i386.in
index bd61303..df74b6b 100644
--- a/testcases/kernel/include/i386.in
+++ b/testcases/kernel/include/i386.in
@@ -22,6 +22,7 @@ __NR_tee 315
 __NR_vmsplice 316
 __NR_utimensat 320
 __NR_timerfd_create 322
+__NR_eventfd 323
 __NR_fallocate 324
 __NR_timerfd_settime 325
 __NR_timerfd_gettime 326
diff --git a/testcases/kernel/include/ia64.in b/testcases/kernel/include/ia64.in
index ea925b2..54c9910 100644
--- a/testcases/kernel/include/ia64.in
+++ b/testcases/kernel/include/ia64.in
@@ -17,6 +17,7 @@ __NR_tee 1301
 __NR_vmsplice 1302
 __NR_fallocate 1303
 __NR_utimensat 1306
+__NR_eventfd 1309
 __NR_timerfd_create 1310
 __NR_timerfd_settime 1311
 __NR_timerfd_gettime 1312
diff --git a/testcases/kernel/include/powerpc.in 
b/testcases/kernel/include/powerpc.in
index 99055d3..4dbd734 100644
--- a/testcases/kernel/include/powerpc.in
+++ b/testcases/kernel/include/powerpc.in
@@ -20,4 +20,5 @@ __NR_symlinkat (__NR_openat + 9)
 __NR_readlinkat (__NR_openat + 10)
 __NR_fchmodat  (__NR_openat + 11)
 __NR_faccessat (__NR_openat + 12)
+__NR_eventfd 307
 __NR_fallocate 309
diff --git a/testcases/kernel/include/powerpc64.in 
b/testcases/kernel/include/powerpc64.in
index 99055d3..4dbd734 100644
--- a/testcases/kernel/include/powerpc64.in
+++ b/testcases/kernel/include/powerpc64.in
@@ -20,4 +20,5 @@ __NR_symlinkat (__NR_openat + 9)
 __NR_readlinkat (__NR_openat + 10)
 __NR_fchmodat  (__NR_openat + 11)
 __NR_faccessat (__NR_openat + 12)
+__NR_eventfd 307
 __NR_fallocate 309
diff --git a/testcases/kernel/include/s390.in b/testcases/kernel/include/s390.in
index 5eb40e2..ef35cf0 100644
--- a/testcases/kernel/include/s390.in
+++ b/testcases/kernel/include/s390.in
@@ -15,4 +15,5 @@ __NR_faccessat (__NR_openat + 12)
 __NR_splice 306
 __NR_tee 308
 __NR_vmsplice 309
+__NR_eventfd 318
 __NR_fallocate 314
diff --git a/testcases/kernel/include/s390x.in 
b/testcases/kernel/include/s390x.in
index 8040dd5..0a47f6a 100644
--- a/testcases/kernel/include/s390x.in
+++ b/testcases/kernel/include/s390x.in
@@ -12,4 +12,5 @@ __NR_symlinkat (__NR_openat + 9)
 __NR_readlinkat (__NR_openat + 10)
 __NR_fchmodat  (__NR_openat + 11)
 __NR_faccessat (__NR_openat + 12)
+__NR_eventfd 318
 __NR_fallocate 314
diff --git a/testcases/kernel/include/sparc.in 
b/testcases/kernel/include/sparc.in
index ad4e3ff..fc81530 100644
--- a/testcases/kernel/include/sparc.in
+++ b/testcases/kernel/include/sparc.in
@@ -15,4 +15,5 @@ __NR_symlinkat (__NR_openat + 9)
 __NR_readlinkat (__NR_openat + 10)
 __NR_fchmodat  (__NR_openat + 11)
 __NR_faccessat (__NR_openat + 12)
+__NR_eventfd 313
 __NR_fallocate 314
diff --git a/testcases/kernel/include/sparc64.in 
b/testcases/kernel/include/sparc64.in
index ad4e3ff..1ea80fa 100644
--- a/testcases/kernel/include/sparc64.in
+++ b/testcases/kernel/include/sparc64.in
@@ -15,4 +15,5 @@ __NR_symlinkat (__NR_openat + 9)
 __NR_readlinkat (__NR_openat + 10)
 __NR_fchmodat  (__NR_openat + 11)
 __NR_faccessat (__NR_openat + 12)
+__NR_eventd 313
 __NR_fallocate 314
diff --git a/testcases/kernel/include/stub-list 
b/testcases/kernel/include/stub-list
index 4dde44d..a6738a4 100644
--- a/testcases/kernel/include/stub-list
+++ b/testcases/kernel/include/stub-list
@@ -21,3 +21,4 @@ __NR_timer_delete
 __NR_timer_settime
 __NR_unlinkat
 __NR_vmsplice
+__NR_eventfd
\ No newline at end of file
diff --git a/testcases/kernel/include/x86_64.in 
b/testcases/kernel/include/x86_64.in
index 8a326ac..9606c98 100644
--- a/testcases/kernel/include/x86_64.in
+++ b/testcases/kernel/include/x86_64.in
@@ -22,6 +22,7 @@ __NR_tee 276
 __NR_vmsplice 278
 __NR_utimensat 296
 __NR_timerfd_create 283
+__NR_eventfd 284
 __NR_fallocate 285
 __NR_timerfd_settime 286
 __NR_timerfd_gettime 287
diff --git a/testcases/kernel/syscalls/eventfd/Makefile 
b/testcases/kernel/syscalls/eventfd/Makefile
new file mode 100644
index 0000000..e2ebae8
--- /dev/null
+++ b/testcases/kernel/syscalls/eventfd/Makefile
@@ -0,0 +1,32 @@
+#
+#  Copyright (c) International Business Machines  Corp., 2001
+#
+#  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 2 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, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+CFLAGS += -I../../../../include -Wall
+LDLIBS += -L../../../../lib -lltp
+
+SRCS    = $(wildcard *.c)
+TARGETS = $(patsubst %.c, %, $(wildcard *.c))
+
+all: $(TARGETS)
+
+install:
+       @set -e; for i in $(TARGETS); do ln -f $$i ../../../bin/$$i ; done
+
+clean:
+       rm -f $(TARGETS)
+
diff --git a/testcases/kernel/syscalls/eventfd/eventfd01.c 
b/testcases/kernel/syscalls/eventfd/eventfd01.c
new file mode 100644
index 0000000..f099248
--- /dev/null
+++ b/testcases/kernel/syscalls/eventfd/eventfd01.c
@@ -0,0 +1,582 @@
+/*
+ *   Copyright (c) 2008 Vijay Kumar B. <[EMAIL PROTECTED]>
+ *
+ *   Based on testcases/kernel/syscalls/waitpid/waitpid01.c
+ *   Original copyright message:
+ *
+ *   Copyright (c) International Business Machines  Corp., 2001
+ *
+ *   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 2 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, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * NAME
+ *     eventfd01.c
+ *
+ * DESCRIPTION
+ *      Test cases for eventfd syscall.
+ *
+ * USAGE:  <for command-line>
+ *      eventfd01 [-c n] [-i n] [-I x] [-P x] [-t]
+ *      where,  -c n : Run n copies concurrently.
+ *              -i n : Execute test n times.
+ *              -I x : Execute test for x seconds.
+ *              -P x : Pause for x seconds between iterations.
+ *              -t   : Turn on syscall timing.
+ *
+ * History
+ *     07/2008 Vijay Kumar
+ *             Initial Version.
+ *
+ * Restrictions
+ *     None
+ */
+
+#include <sys/select.h>
+#include <sys/signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <test.h>
+#include <usctest.h>
+#include <linux_syscall_numbers.h>
+
+static void setup(void);
+static void cleanup(void);
+
+char *TCID = "eventfd01";
+int TST_TOTAL = 12;
+extern int Tst_count;
+
+static int
+myeventfd(unsigned int initval, int flags)
+{
+       return syscall(__NR_eventfd, initval);
+}
+
+/*
+ * clear_counter() - clears the counter by performing a dummy read
+ * @fd: the eventfd
+ *
+ * RETURNS:
+ * 0 on success, and -1 on failure
+ */
+static int
+clear_counter(int fd)
+{
+       uint64_t dummy;
+       int ret;
+
+       ret = read(fd, &dummy, sizeof(dummy));
+       if (ret == -1) {
+               if (errno != EAGAIN) {
+                       tst_resm(TBROK, "error clearing counter: %s",
+                                strerror(errno));
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * set_counter() - sets the count to specified value
+ * @fd: the eventfd
+ * @val: the value to be set
+ *
+ * Clears the counter and sets the counter to @val.
+ *
+ * RETURNS:
+ * 0 on success, -1 on failure
+ */
+static int
+set_counter(int fd, uint64_t val)
+{
+       int ret;
+
+       ret = clear_counter(fd);
+       if (ret == -1) {
+               return -1;
+       }
+
+       ret = write(fd, &val, sizeof(val));
+       if (ret == -1) {
+               tst_resm(TBROK, "error setting counter value: %s",
+                        strerror(errno));
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+ * Test whether the current value of the counter matches @required.
+ */
+static void
+read_test(int fd, uint64_t required)
+{
+       int ret;
+       uint64_t val;
+
+       ret = read(fd, &val, sizeof(val));
+       if (ret == -1) {
+               tst_resm(TBROK, "error reading eventfd: %s",
+                        strerror(errno));
+               return;
+       }
+
+       if (val == required)
+               tst_resm(TPASS, "counter value matches required");
+       else
+               tst_resm(TFAIL, "counter value mismatch: "
+                        "required: %llu, got: %llu", required, val);
+}
+
+/*
+ * Test whether read returns with error EAGAIN when counter is at 0.
+ */
+static void
+read_eagain_test(int fd)
+{
+       int ret;
+       uint64_t val;
+
+       ret = clear_counter(fd);
+       if (ret == -1)
+               return;
+
+       ret = read(fd, &val, sizeof(val));
+       if (ret == -1) {
+               if (errno == EAGAIN)
+                       tst_resm(TPASS, "read failed with EAGAIN as expected");
+               else
+                       tst_resm(TFAIL, "read failed with unexpected "
+                                "error: %s", strerror(errno));
+       } else {
+               tst_resm(TFAIL, "read returned with %d");
+       }
+}
+
+/*
+ * Test whether writing to counter works.
+ */
+static void
+write_test(int fd)
+{
+       int ret;
+       uint64_t val;
+
+       val = 12;
+
+       ret = set_counter(fd, val);
+       if (ret == -1)
+               return;
+
+       read_test(fd, val);
+}
+
+/*
+ * Test whether write returns with error EAGAIN when counter is at
+ * (UINT64_MAX - 1).
+ */
+static void
+write_eagain_test(int fd)
+{
+       int ret;
+       uint64_t val;
+
+       ret = set_counter(fd, UINT64_MAX - 1);
+       if (ret == -1)
+               return;
+
+       val = 1;
+       ret = write(fd, &val, sizeof(val));
+       if (ret == -1) {
+               if (errno == EAGAIN)
+                       tst_resm(TPASS, "write failed with EAGAIN as "
+                                "expected");
+               else
+                       tst_resm(TFAIL, "write returned with unexpected "
+                                "error: %s", strerror(errno));
+       } else {
+               tst_resm(TFAIL, "write returned with %d", ret);
+       }
+}
+
+/*
+ * Test whether read returns with error EINVAL, if buffer size is less
+ * than 8 bytes.
+ */
+static void
+read_einval_test(int fd)
+{
+       uint32_t invalid;
+       int ret;
+
+       ret = read(fd, &invalid, sizeof(invalid));
+       if (ret == -1) {
+               if (errno == EINVAL) {
+                       tst_resm(TPASS, "read failed with EINVAL as expected");
+               } else {
+                       tst_resm(TFAIL, "read returned with unexpected "
+                                "error: %s", strerror(errno));
+               }
+       } else {
+               tst_resm(TFAIL, "read returned with %d", ret);
+       }
+}
+
+/*
+ * Test whether write returns with error EINVAL, if buffer size is
+ * less than 8 bytes.
+ */
+static void
+write_einval_test(int fd)
+{
+       uint32_t invalid;
+       int ret;
+
+       ret = write(fd, &invalid, sizeof(invalid));
+       if (ret == -1) {
+               if (errno == EINVAL) {
+                       tst_resm(TPASS, "write failed with EINVAL as "
+                                "expected");
+               } else {
+                       tst_resm(TFAIL, "write returned with unexpected "
+                                "error: %s", strerror(errno));
+               }
+       } else {
+               tst_resm(TFAIL, "write returned with %d", ret);
+       }
+}
+
+/*
+ * Test wheter write returns with error EINVAL, when the written value
+ * is 0xFFFFFFFFFFFFFFFF.
+ */
+static void
+write_einval2_test(int fd)
+{
+       int ret;
+       uint64_t val;
+
+       ret = clear_counter(fd);
+       if (ret == -1)
+               return;
+
+       val = 0xffffffffffffffffLL;
+       ret = write(fd, &val, sizeof(val));
+       if (ret == -1) {
+               if (errno == EINVAL)
+                       tst_resm(TPASS, "write failed with EINVAL as "
+                                "expected");
+               else
+                       tst_resm(TFAIL, "write returned with unexpected "
+                               "error: %s", strerror(errno));
+       } else {
+               tst_resm(TFAIL, "write returned with %d", ret);
+       }
+}
+
+/*
+ * Test whether readfd is set by select when counter value is
+ * non-zero.
+ */
+static void
+readfd_set_test(int fd)
+{
+       int ret;
+       fd_set readfds;
+       struct timeval timeout = { 0, 0 };
+       uint64_t non_zero = 10;
+
+       FD_ZERO(&readfds);
+       FD_SET(fd, &readfds);
+
+       ret = set_counter(fd, non_zero);
+       if (ret == -1)
+               return;
+
+       ret = select(fd + 1, &readfds, NULL, NULL, &timeout);
+       if (ret == -1) {
+               /* EINTR cannot occur, since we don't block. */
+               tst_resm(TBROK, "select: error getting fd status: %s",
+                        strerror(errno));
+               return;
+       }
+
+       if (FD_ISSET(fd, &readfds))
+               tst_resm(TPASS, "fd is set in readfds");
+       else
+               tst_resm(TFAIL, "fd is not set in readfds");
+}
+
+/*
+ * Test whether readfd is not set by select when counter value is
+ * zero.
+ */
+static void
+readfd_not_set_test(int fd)
+{
+       int ret;
+       fd_set readfds;
+       struct timeval timeout = { 0, 0 };
+
+       FD_ZERO(&readfds);
+       FD_SET(fd, &readfds);
+
+       ret = clear_counter(fd);
+       if (ret == -1)
+               return;
+
+       ret = select(fd + 1, &readfds, NULL, NULL, &timeout);
+       if (ret == -1) {
+               /* EINTR cannot occur, since we don't block. */
+               tst_resm(TBROK, "select: error getting fd status: %s",
+                        strerror(errno));
+               return;
+       }
+
+       if (!FD_ISSET(fd, &readfds))
+               tst_resm(TPASS, "fd is not set in readfds");
+       else
+               tst_resm(TFAIL, "fd is set in readfds");
+}
+
+/*
+ * Test whether writefd is set by select when counter value is not the
+ * maximum counter value.
+ */
+static void
+writefd_set_test(int fd)
+{
+       int ret;
+       fd_set writefds;
+       struct timeval timeout = { 0, 0 };
+       uint64_t non_max = 10;
+
+       FD_ZERO(&writefds);
+       FD_SET(fd, &writefds);
+
+       ret = set_counter(fd, non_max);
+       if (ret == -1)
+               return;
+
+       ret = select(fd + 1, NULL, &writefds, NULL, &timeout);
+       if (ret == -1) {
+               /* EINTR cannot occur, since we don't block. */
+               tst_resm(TBROK, "select: error getting fd status: %s",
+                        strerror(errno));
+               return;
+       }
+
+       if (FD_ISSET(fd, &writefds))
+               tst_resm(TPASS, "fd is set in writefds");
+       else
+               tst_resm(TFAIL, "fd is not set in writefds");
+}
+
+/*
+ * Test whether writefd is not set by select when counter value is at
+ * (UINT64_MAX - 1).
+ */
+static void
+writefd_not_set_test(int fd)
+{
+       int ret;
+       fd_set writefds;
+       struct timeval timeout = { 0, 0 };
+
+       FD_ZERO(&writefds);
+       FD_SET(fd, &writefds);
+
+       ret = set_counter(fd, UINT64_MAX - 1);
+       if (ret == -1)
+               return;
+
+       ret = select(fd + 1, NULL, &writefds, NULL, &timeout);
+       if (ret == -1) {
+               /* EINTR cannot occur, since we don't block. */
+               tst_resm(TBROK, "select: error getting fd status: %s",
+                        strerror(errno));
+               return;
+       }
+
+       if (!FD_ISSET(fd, &writefds))
+               tst_resm(TPASS, "fd is not set in writefds");
+       else
+               tst_resm(TFAIL, "fd is set in writefds");
+}
+
+/*
+ * Test whether counter update in child is reflected in the parent.
+ */
+static void
+child_inherit_test(int fd)
+{
+       uint64_t val;
+       pid_t cpid;
+       int ret;
+       int status;
+       uint64_t to_parent = 0xdeadbeef;
+       uint64_t dummy;
+
+       cpid = fork();
+       if (cpid == -1)
+               tst_resm(TBROK, "error while forking child: %s",
+                        strerror(errno));
+       if (cpid != 0) {
+               /* Parent */
+               ret = wait(&status);
+               if (ret == -1) {
+                       tst_resm(TBROK, "error getting child exit status");
+                       return;
+               }
+
+               if (WEXITSTATUS(status) == 1) {
+                       tst_resm(TBROK, "counter value write not "
+                                "succesful in child");
+                       return;
+               }
+
+               ret = read(fd, &val, sizeof(val));
+               if (ret == -1) {
+                       tst_resm(TBROK, "error reading eventfd: %s",
+                                strerror(errno));
+                       return;
+               }
+
+               if (val == to_parent)
+                       tst_resm(TPASS, "counter value write from "
+                                "child successful");
+               else
+                       tst_resm(TFAIL, "counter value write in child "
+                                "failed");
+       } else {
+               /* Child */
+               ret = read(fd, &dummy, sizeof(dummy));
+               if (ret == -1 && errno != EAGAIN) {
+                       tst_resm(TWARN, "error clearing counter: %s",
+                                strerror(errno));
+                       exit(1);
+               }
+
+               ret = write(fd, &to_parent, sizeof(to_parent));
+               if (ret == -1) {
+                       tst_resm(TWARN, "error writing eventfd: %s",
+                                strerror(errno));
+                       exit(1);
+               }
+
+               exit(0);
+       }
+}
+
+int
+main(int argc, char **argv)
+{
+       int lc;                         /* loop counter */
+       char *msg;                      /* message returned from parse_opts */
+       int fd;
+
+       /* parse standard options */
+       msg = parse_opts(argc, argv, (option_t *) NULL, NULL);
+       if (msg != NULL) {
+               tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
+               tst_exit();
+               /* NOTREACHED */
+       }
+
+       setup();
+
+       /* check for looping state if -i option is given */
+       for (lc = 0; TEST_LOOPING(lc); lc++) {
+               int ret;
+               uint64_t einit = 10;
+
+               /* reset Tst_count in case we are looping */
+               Tst_count = 0;
+
+               fd = myeventfd(einit, 0);
+               if (fd == -1)
+                       tst_brkm(TBROK, cleanup, "error creating eventfd: %s",
+                                strerror(errno));
+
+               ret = fcntl(fd, F_SETFL, O_NONBLOCK);
+               if (ret == -1)
+                       tst_brkm(TBROK, cleanup,
+                                "error setting non-block mode: %s", strerror);
+
+               read_test(fd, einit);
+               read_eagain_test(fd);
+               write_test(fd);
+               write_eagain_test(fd);
+               read_einval_test(fd);
+               write_einval_test(fd);
+               write_einval2_test(fd);
+               readfd_set_test(fd);
+               readfd_not_set_test(fd);
+               writefd_set_test(fd);
+               writefd_not_set_test(fd);
+               child_inherit_test(fd);
+
+               close(fd);
+       }
+
+       cleanup();
+       /* NOT REACHED */
+
+       return 0;
+}
+
+/*
+ * setup() - performs all ONE TIME setup for this test
+ */
+static void
+setup(void)
+{
+       /* capture signals */
+       tst_sig(FORK, DEF_HANDLER, cleanup);
+
+       if (tst_kvercmp(2, 6, 22) < 0)
+               tst_brkm(TCONF, cleanup, "2.6.22 or greater kernel required");
+
+       /* Pause if that option was specified
+        * TEST_PAUSE contains the code to fork the test with the -c option.
+        */
+       TEST_PAUSE;
+}
+
+/*
+ * cleanup() - performs all ONE TIME cleanup for this test
+ */
+static void
+cleanup(void)
+{
+       /*
+        * print timing stats if that option was specified.
+        * print errno log if that option was specified.
+        */
+       TEST_CLEANUP;
+
+       /* exit with return code appropriate for results */
+       tst_exit();
+       /*NOTREACHED*/
+}

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list

Reply via email to