
From: Andi Kleen <ak@suse.de>

Add 32bit->64bit conversion functions for POSIX timers.

I kept timer_create architecture specific, becauseit does signal specific
stuff which is not portable enough for generic compat.

Only lightly tested currently.




 include/linux/compat.h |    5 +
 kernel/compat.c        |  127 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 132 insertions(+)

diff -puN include/linux/compat.h~compat-posix-timers include/linux/compat.h
--- 25/include/linux/compat.h~compat-posix-timers	2003-08-10 14:49:29.000000000 -0700
+++ 25-akpm/include/linux/compat.h	2003-08-10 14:49:29.000000000 -0700
@@ -15,6 +15,11 @@
 #define compat_jiffies_to_clock_t(x)	\
 		(((unsigned long)(x) * COMPAT_USER_HZ) / HZ)
 
+struct compat_itimerspec {
+	struct compat_timespec it_interval;
+	struct compat_timespec it_value;
+};
+
 struct compat_utimbuf {
 	compat_time_t		actime;
 	compat_time_t		modtime;
diff -puN kernel/compat.c~compat-posix-timers kernel/compat.c
--- 25/kernel/compat.c~compat-posix-timers	2003-08-10 14:49:29.000000000 -0700
+++ 25-akpm/kernel/compat.c	2003-08-10 14:49:29.000000000 -0700
@@ -430,3 +430,130 @@ asmlinkage int compat_sys_sched_getaffin
 	return ret;
 }
 
+static int get_compat_itimerspec(struct itimerspec *dst,
+				 struct compat_itimerspec *src)
+{
+	if (get_compat_timespec(&dst->it_interval, &src->it_interval) ||
+	    get_compat_timespec(&dst->it_value, &src->it_value))
+		return -EFAULT;
+	return 0;
+}
+
+static int put_compat_itimerspec(struct compat_itimerspec *dst,
+				 struct itimerspec *src)
+{
+	if (put_compat_timespec(&src->it_interval, &dst->it_interval) ||
+	    put_compat_timespec(&src->it_value, &dst->it_value))
+		return -EFAULT;
+	return 0;
+}
+
+extern asmlinkage long sys_timer_settime(timer_t timer_id, int flags,
+				  struct itimerspec __user *new_setting,
+				 struct itimerspec __user *old_setting);
+extern asmlinkage long sys_timer_gettime(timer_t timer_id,
+					 struct itimerspec __user *setting);
+
+long compat_timer_settime(timer_t timer_id, int flags,
+			  struct compat_itimerspec *new,
+			  struct compat_itimerspec *old)
+{
+	long err;
+	mm_segment_t oldfs;
+	struct itimerspec newts, oldts;
+	if (get_compat_itimerspec(&newts, new))
+		return -EFAULT;
+	oldfs = get_fs();
+	err = sys_timer_settime(timer_id, flags, &newts, &oldts);
+	set_fs(oldfs);
+	if (!err && old && put_compat_itimerspec(old, &oldts))
+		return -EFAULT;
+	return err;
+}
+
+long compat_timer_gettime(timer_t timer_id, struct compat_itimerspec *setting)
+{
+	long err;
+	mm_segment_t oldfs;
+	struct itimerspec ts;
+	oldfs = get_fs();
+	err = sys_timer_gettime(timer_id, &ts);
+	set_fs(oldfs);
+	if (!err && put_compat_itimerspec(setting, &ts))
+		return -EFAULT;
+	return err;
+}
+
+extern asmlinkage long
+sys_clock_settime(clockid_t which_clock, struct timespec __user *tp);
+
+long compat_clock_settime(clockid_t which_clock,  struct compat_timespec *tp)
+{
+	long err;
+	mm_segment_t oldfs;
+	struct timespec ts;
+	if (get_compat_timespec(&ts, tp))
+		return -EFAULT;
+	oldfs = get_fs();
+	err = sys_clock_settime(which_clock, &ts);
+	set_fs(oldfs);
+	return err;
+}
+
+extern asmlinkage long
+sys_clock_gettime(clockid_t which_clock, struct timespec __user *tp);
+
+long compat_clock_gettime(clockid_t which_clock,  struct compat_timespec *tp)
+{
+	long err;
+	mm_segment_t oldfs;
+	struct timespec ts;
+	oldfs = get_fs();
+	err = sys_clock_gettime(which_clock, &ts);
+	set_fs(oldfs);
+	if (!err && put_compat_timespec(&ts, tp))
+		return -EFAULT;
+	return err;
+}
+
+extern asmlinkage long
+sys_clock_getres(clockid_t which_clock, struct timespec __user *tp);
+
+long compat_clock_getres(clockid_t which_clock,  struct compat_timespec *tp)
+{
+	long err;
+	mm_segment_t oldfs;
+	struct timespec ts;
+	oldfs = get_fs();
+	err = sys_clock_getres(which_clock, &ts);
+	set_fs(oldfs);
+	if (!err && put_compat_timespec(&ts, tp))
+		return -EFAULT;
+	return err;
+}
+
+extern asmlinkage long
+sys_clock_nanosleep(clockid_t which_clock, int flags,
+		     struct timespec __user *rqtp,
+		    struct timespec __user *rmtp);
+
+long compat_clock_nanosleep(clockid_t which_clock, int flags,
+			    struct compat_timespec __user *rqtp,
+			    struct compat_timespec __user *rmtp)
+{
+	long err;
+	mm_segment_t oldfs;
+	struct timespec in, out;
+	if (get_compat_timespec(&in, rqtp))
+		return -EFAULT;
+	oldfs = get_fs();
+	err = sys_clock_nanosleep(which_clock, flags, &in, &out);
+	set_fs(oldfs);
+	if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
+	    put_compat_timespec(&out, rmtp))
+		return -EFAULT;
+	return err;
+}
+
+/* timer_create is architecture specific because it needs sigevent conversion */
+

_
