home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 1999 May / pcp151c.iso / misc / src / install / modutils / util / sys_cm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-06  |  2.9 KB  |  89 lines

  1. /* Functions for the Linux module syscall interface.
  2.    Copyright 1996, 1997 Linux International.
  3.    Contributed by Richard Henderson <rth@tamu.edu>
  4.  
  5.    This file is part of the Linux modutils.
  6.  
  7.    This program is free software; you can redistribute it and/or modify it
  8.    under the terms of the GNU General Public License as published by the
  9.    Free Software Foundation; either version 2 of the License, or (at your
  10.    option) any later version.
  11.  
  12.    This program is distributed in the hope that it will be useful, but
  13.    WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.    General Public License for more details.
  16.  
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software Foundation,
  19.    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
  20.  
  21. #ident "$Id: sys_cm.c,v 1.1.1.1 1998/01/06 20:51:08 ewt Exp $"
  22.  
  23. #include <stdlib.h>
  24. #include <errno.h>
  25.  
  26. #include "module.h"
  27.  
  28. /* Kernel headers before 2.1.mumble need this on the Alpha to get
  29.    _syscall* defined.  */
  30. #define __LIBRARY__
  31.  
  32. #include <asm/unistd.h>
  33.  
  34.  
  35. /*======================================================================*/
  36.  
  37. #if defined(__i386__) || defined(__m68k__)
  38.  
  39. #define __NR__create_module  __NR_create_module
  40. static inline _syscall2(long, _create_module, const char *, name, size_t, size)
  41.  
  42. unsigned long create_module(const char *name, size_t size)
  43. {
  44.   /* Why all this fuss?
  45.  
  46.      In linux 2.1, the address returned by create module point in
  47.      kernel space which is now mapped at the top of user space (at
  48.      0xc0000000 on i386). This looks like a negative number for a
  49.      long. The normal syscall macro of linux 2.0 (and all libc compile
  50.      with linux 2.0 or below) consider that the return value is a
  51.      negative number and consider it is an error number (A kernel
  52.      convention, return value are positive or negative, indicating the
  53.      error number).
  54.  
  55.      By checking the value of errno, we know if we have been fooled by
  56.      the syscall2 macro and we fix it.  */
  57.  
  58.   long ret = _create_module(name, size);
  59.   if (ret == -1 && errno > 125)
  60.     {
  61.       ret = -errno;
  62.       errno = 0;
  63.     }
  64.   return ret;
  65. }
  66.  
  67. #elif defined(__alpha__)
  68.  
  69. /* Alpha doesn't have the same problem, exactly, but a bug in older
  70.    kernels fails to clear the error flag.  Clear it here explicitly.  */
  71.  
  72. #define __NR__create_module  __NR_create_module
  73. static inline _syscall4(unsigned long, _create_module, const char *, name,
  74.             size_t, size, size_t, dummy, size_t, err);
  75.  
  76. unsigned long create_module(const char *name, size_t size)
  77. {
  78.   return _create_module(name, size, 0, 0);
  79. }
  80.  
  81. #else
  82.  
  83. /* Sparc, MIPS, (and Alpha, but that's another problem) don't mistake
  84.    return values for errors due to the nature of the system call.  */
  85.  
  86. _syscall2(unsigned long, create_module, const char *, name, size_t, size)
  87.  
  88. #endif
  89.