Compat handlers for the pollable signal operations. Later the0 compat operations
can operate on a per call basis.

Signed-off-by: Davi E. M. Arnaut <[EMAIL PROTECTED]>

---
 fs/pollfs/signal.c |   85 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 85 insertions(+)

Index: linux-2.6/fs/pollfs/signal.c
===================================================================
--- linux-2.6.orig/fs/pollfs/signal.c
+++ linux-2.6/fs/pollfs/signal.c
@@ -16,6 +16,7 @@
 #include <linux/poll.h>
 #include <linux/pollfs_fs.h>
 #include <linux/signal.h>
+#include <linux/compat.h>
 
 struct pfs_signal {
        sigset_t set;
@@ -48,6 +49,24 @@ static ssize_t read(struct pfs_signal *e
        return 0;
 }
 
+#ifdef CONFIG_COMPAT
+static ssize_t compat_read(struct pfs_signal *evs,
+                          struct compat_siginfo __user *infoup)
+{
+       int signo;
+       siginfo_t info;
+
+       signo = dequeue_signal_lock(evs->task, &evs->set, &info);
+       if (!signo)
+               return -EAGAIN;
+
+       if (copy_siginfo_to_user32(infoup, &info))
+               return -EFAULT;
+
+       return 0;
+}
+#endif
+
 static ssize_t write(struct pfs_signal *evs, const sigset_t __user *uset)
 {
        sigset_t set;
@@ -65,6 +84,28 @@ static ssize_t write(struct pfs_signal *
        return 0;
 }
 
+#ifdef CONFIG_COMPAT
+static ssize_t compat_write(struct pfs_signal *evs,
+                           const compat_sigset_t __user *uset)
+{
+       sigset_t set;
+       compat_sigset_t cset;
+
+       if (copy_from_user(&cset, uset, sizeof(compat_sigset_t)))
+               return -EFAULT;
+
+       sigset_from_compat(&set, &cset);
+       sigset_adjust(&set);
+
+       spin_lock_irq(&evs->lock);
+       sigemptyset(&evs->set);
+       sigorsets(&evs->set, &evs->set, &set);
+       spin_unlock_irq(&evs->lock);
+
+       return 0;
+}
+#endif
+
 static int poll(struct pfs_signal *evs)
 {
        int ret = 0;
@@ -142,3 +183,47 @@ asmlinkage long sys_plsignal(const sigse
 
        return error;
 }
+
+#ifdef CONFIG_COMPAT
+static const struct pfs_operations compat_signal_ops = {
+       /* .read        = PFS_READ(compat_read, struct pfs_signal, struct 
compat_siginfo), */
+       .write          = PFS_WRITE(compat_write, struct pfs_signal, 
compat_sigset_t),
+       .poll           = PFS_POLL(poll, struct pfs_signal),
+       .release        = PFS_RELEASE(release, struct pfs_signal),
+       /* .rsize       = sizeof(compat_siginfo_t), */
+       .wsize          = sizeof(sigset_t)
+};
+
+asmlinkage long compat_plsignal(const compat_sigset_t __user *uset)
+{
+       long error;
+       compat_sigset_t cset;
+       struct pfs_signal *evs;
+
+       if (copy_from_user(&cset, uset, sizeof(compat_sigset_t)))
+               return -EFAULT;
+
+       evs = kmalloc(sizeof(*evs), GFP_KERNEL);
+       if (!evs)
+               return -ENOMEM;
+
+       spin_lock_init(&evs->lock);
+
+       evs->task = current;
+       get_task_struct(current);
+
+       sigset_from_compat(&evs->set, &cset);
+       sigset_adjust(&evs->set);
+
+       evs->file.data = evs;
+       evs->file.fops = &compat_signal_ops;
+       evs->file.wait = &evs->task->sigwait;
+
+       error = pfs_open(&evs->file);
+
+       if (error < 0)
+               release(evs);
+
+       return error;
+}
+#endif

--
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to