add directory Linux-0.12
This commit is contained in:
BIN
Linux-0.12/sources/system/ega.tar.Z
Normal file
BIN
Linux-0.12/sources/system/ega.tar.Z
Normal file
Binary file not shown.
BIN
Linux-0.12/sources/system/hd.c.Z
Normal file
BIN
Linux-0.12/sources/system/hd.c.Z
Normal file
Binary file not shown.
BIN
Linux-0.12/sources/system/lp.12.tar.Z
Normal file
BIN
Linux-0.12/sources/system/lp.12.tar.Z
Normal file
Binary file not shown.
BIN
Linux-0.12/sources/system/mmap.tar.Z
Normal file
BIN
Linux-0.12/sources/system/mmap.tar.Z
Normal file
Binary file not shown.
186
Linux-0.12/sources/system/reboot-kmem.patch
Normal file
186
Linux-0.12/sources/system/reboot-kmem.patch
Normal file
@@ -0,0 +1,186 @@
|
||||
From: db1@ukc.ac.uk (D.Bolla)
|
||||
Newsgroups: alt.os.linux
|
||||
Subject: Patches to have reboot and /dev/kmem working
|
||||
Summary: How to add a syscall. And various considerations
|
||||
Message-ID: <5375@falcon.ukc.ac.uk>
|
||||
Date: 22 Feb 92 13:50:56 GMT
|
||||
Sender: db1@ukc.ac.uk
|
||||
Organization: Computing Lab, University of Kent at Canterbury, UK.
|
||||
Lines: 174
|
||||
|
||||
|
||||
|
||||
Hello
|
||||
|
||||
This time I have some small solutions :-)
|
||||
|
||||
The first one is the implentation of the reboot syscall.
|
||||
The syscall just does a reboot after having checked that you are root.
|
||||
The old method does not work anymore ( CTRL-ALT-DEL )
|
||||
|
||||
The second is an implementation of the /dev/kmem. Most of the code is
|
||||
done by linux. I just added FEW lines in the right place ( I hope ).
|
||||
The point is that with this /unix and nlist(3) it is possible to get
|
||||
all information we need from the kernel WITHOUT having to add code to the
|
||||
kernel.
|
||||
|
||||
It seems to me that people who complain about "normal users cannot read
|
||||
/dev/kmem" and "A library to read kernel data is not nice" don't have a
|
||||
clear idea about what /dev/kmem is used for.
|
||||
When you look in /dev/kmem you look for VERY special information about
|
||||
the system. I am not sayng that normal user should be denied ps :-)
|
||||
but if you think, normal users use ps just to see what others are doing
|
||||
( The same thing for w )
|
||||
|
||||
Anyway.... under Sun there are three programs that "look" into /dev/kmem
|
||||
ps, w, pstats. The amount of information you can get out of them is very
|
||||
big. The point that I am tryng to make here is:
|
||||
To obtain the same amount of information from syscalls you need a
|
||||
GREAT number of variations and parameters. Is this worth the work ?
|
||||
( Considering the small amount of programs that need that information )
|
||||
Again.....
|
||||
|
||||
Negative points of kernel implementation.
|
||||
1) Extra (Unnecessary) code in the kernel -> Kernel bigger.
|
||||
2) Possible introduction of ERRORS -> Kernel panic.
|
||||
3) Increased number of syscall and paramentrs -> Complexity
|
||||
4) Problems on returning lists of data in user space
|
||||
To me point 2 is already enough NOT to use this method. If you can live
|
||||
with possible kernel panics.......
|
||||
|
||||
Positive points of a library implementation.
|
||||
1) NO extra code in the kernel. -> Save memory
|
||||
2) Impossibility to add ERRORS to the kernel code. -> NO panic
|
||||
3) Easy to update, modify even by average user.
|
||||
4) No problems in allcating memory for the result.
|
||||
|
||||
What it is important is to DEFINE what information we want to
|
||||
extract from /dev/kmem and who can use them. After that is defined it
|
||||
is possible to discuss about implementaion.
|
||||
|
||||
And now to the code :-)
|
||||
|
||||
-----------------------------------------------------------------
|
||||
I decided to put the actual routine that does reboot into
|
||||
kernel/sys.c Probably your sys.c may be different....
|
||||
|
||||
522a523,533
|
||||
> /* This function reboots the system if the current UID is root
|
||||
> * No sync is performed. The optional flag is not used yet
|
||||
> * The called routine is in kernel/chr_drv/keyboard.S
|
||||
> */
|
||||
> int sys_reboot ( int flag )
|
||||
> {
|
||||
> if (!suser())
|
||||
> return (-EPERM);
|
||||
> __asm__("call _hard_reset;" );
|
||||
> return (0);
|
||||
> }
|
||||
|
||||
The next step is to add the syscall code in the file
|
||||
include/unistd.h
|
||||
|
||||
148a149
|
||||
> #define __NR_reboot 87
|
||||
|
||||
And then add the syscall address in the file
|
||||
include/linux/sys.h
|
||||
|
||||
91a92
|
||||
> extern int sys_reboot();
|
||||
108c109
|
||||
< sys_lstat, sys_readlink, sys_uselib };
|
||||
---
|
||||
> sys_lstat, sys_readlink, sys_uselib ,sys_reboot };
|
||||
|
||||
The last bit is to modify the keyboard.S file
|
||||
kernel/chr_drv/keyboard.S
|
||||
This file is different from yours so.... don't just apply the diff
|
||||
Understand what it does and do it by hand.
|
||||
|
||||
25a26
|
||||
> .globl _hard_reset
|
||||
203c204
|
||||
< jne reboot
|
||||
---
|
||||
> jne 1f /* CTRL-ALT-DEL */
|
||||
659c660
|
||||
< reboot:
|
||||
---
|
||||
> _hard_reset:
|
||||
661,662c662,663
|
||||
< movw $0x1234,0x472 /* don't do memory check */
|
||||
< movb $0xfc,%al /* pulse reset and A20 low */
|
||||
---
|
||||
> movw $0x1234,0x472 /* don't do memory check */
|
||||
> movb $0xfc,%al /* pulse reset and A20 low */
|
||||
|
||||
At this point recompile the kernel and all should go together.
|
||||
Unfortunately the work is NOT finished. You have to add the syscall to
|
||||
libc.a To do this you need the source for the library. Usually in
|
||||
/usr/src/lib. Go into the unistd directory and create the file
|
||||
reboot.c with the following content.
|
||||
|
||||
/* This function will reboot the syestem
|
||||
*/
|
||||
#define __LIBRARY__
|
||||
#include <unistd.h>
|
||||
|
||||
_syscall1(int,reboot,int,param)
|
||||
|
||||
And then modify the Makefile as follow.
|
||||
At the end of OBJ=.... list add reboot.o and do a make dep
|
||||
|
||||
Before making the new libary you have to change the standard unistd.h library
|
||||
file to point to the unistd.h file in the linux directory
|
||||
cd /usr/include
|
||||
rm unistd.h
|
||||
ln -s /usr/src/linux/include/unistd.h unistd.h
|
||||
|
||||
At this point you can make the new libc.a
|
||||
Then you can experiment with the new syscall.
|
||||
Eg:
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
main ()
|
||||
{
|
||||
if ( reboot (1) ==(-EPERM) )
|
||||
printf ("Not superuser \n");
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
-------------------------------------------------------------
|
||||
The second part is a patch that gives you access to the kernel memory
|
||||
in particular kernel DATA memory.
|
||||
The following diff applies to the file fs/char_dev.c and in particular
|
||||
to the function rw_kmem .
|
||||
|
||||
52,54c52,67
|
||||
< {
|
||||
< return -EIO;
|
||||
< }
|
||||
---
|
||||
> {
|
||||
> int i = *pos; /* Current position where to read */
|
||||
>
|
||||
> /* i can go from 0 to LOW_MEM (See include/linux/mm.h */
|
||||
> /* I am not shure about it but it doesn't mem fault :-) */
|
||||
> while ( (count-- > 0) && (i <LOW_MEM) )
|
||||
> {
|
||||
> if (rw==READ) put_fs_byte( *(char *)i ,buf++);
|
||||
> else return (-EIO);
|
||||
> i++;
|
||||
> }
|
||||
>
|
||||
> i -= *pos; /* Count how many read or write */
|
||||
> *pos += i; /* Update position */
|
||||
> return (i); /* Return number read */
|
||||
> }
|
||||
|
||||
NOTE: The LOW_MEM value may not be the most appropriate. Linus please
|
||||
confirm if it is the correct one.
|
||||
|
||||
Damiano
|
||||
|
||||
BIN
Linux-0.12/sources/system/reboot.tar.Z
Normal file
BIN
Linux-0.12/sources/system/reboot.tar.Z
Normal file
Binary file not shown.
210
Linux-0.12/sources/system/rename.patch
Normal file
210
Linux-0.12/sources/system/rename.patch
Normal file
@@ -0,0 +1,210 @@
|
||||
From: torvalds@klaava.Helsinki.FI (Linus Benedict Torvalds)
|
||||
Newsgroups: alt.os.linux
|
||||
Subject: patches for sys_rename
|
||||
Summary: patch to 0.12
|
||||
Keywords: rename mvdir
|
||||
Message-ID: <1992Jan23.194334.23058@klaava.Helsinki.FI>
|
||||
Date: 23 Jan 92 19:43:34 GMT
|
||||
Organization: University of Helsinki
|
||||
Lines: 198
|
||||
|
||||
|
||||
Ok, here's the sys_rename patch to "linux/kernel/namei.c". Additionally
|
||||
you need to remove the sys_rename stub function (just returns -ENOSYS)
|
||||
from "linux/kerne|/sys.c". This is not heavily tested: I wrote it today,
|
||||
but it seems to work.
|
||||
|
||||
Patch the file, remove the stub and recompile linux: voila, you have a
|
||||
rename system call that actually works. It's not in the library, so
|
||||
you'll have to explicitly call it by using __asm__'s. A simple
|
||||
/usr/bin/mvdir command is here:
|
||||
|
||||
#define __LIBRARY__
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (argc != 3)
|
||||
return -1;
|
||||
__asm__("int $0x80":"=a" (i):"0" (__NR_rename),
|
||||
"b" ((long) argv[1]),
|
||||
"c" ((long) argv[2]));
|
||||
return i;
|
||||
}
|
||||
|
||||
and with this in place mv seems to be able to move directories without
|
||||
problems. (You can also use mvdir to move non-directories, but who
|
||||
cares). And, yes, I'm interested in bug-reports if it doesn't work.
|
||||
|
||||
Linus
|
||||
|
||||
---- snip snip -----------------------------------------
|
||||
*** linux/fs/namei.c Sun Jan 12 06:09:58 1992
|
||||
--- namei.c Thu Jan 23 23:05:53 1992
|
||||
***************
|
||||
*** 892,894 ****
|
||||
--- 892,1051 ----
|
||||
iput(oldinode);
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+ static int subdir(struct m_inode * new, struct m_inode * old)
|
||||
+ {
|
||||
+ unsigned short fs;
|
||||
+ int ino;
|
||||
+ int result;
|
||||
+
|
||||
+ __asm__("mov %%fs,%0":"=r" (fs));
|
||||
+ __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
|
||||
+ new->i_count++;
|
||||
+ result = 0;
|
||||
+ for (;;) {
|
||||
+ if (new == old) {
|
||||
+ result = 1;
|
||||
+ break;
|
||||
+ }
|
||||
+ if (new->i_dev != old->i_dev)
|
||||
+ break;
|
||||
+ ino = new->i_num;
|
||||
+ new = _namei("..",new,0);
|
||||
+ if (new->i_num == ino)
|
||||
+ break;
|
||||
+ }
|
||||
+ iput(new);
|
||||
+ __asm__("mov %0,%%fs"::"r" (fs));
|
||||
+ return result;
|
||||
+ }
|
||||
+
|
||||
+ #define PARENT_INO(buffer) \
|
||||
+ (((struct dir_entry *) (buffer))[1].inode)
|
||||
+
|
||||
+ #define PARENT_NAME(buffer) \
|
||||
+ (((struct dir_entry *) (buffer))[1].name)
|
||||
+
|
||||
+ /*
|
||||
+ * rename uses the -ERESTARTNOINTR error return to avoid race conditions:
|
||||
+ * it tries to allocate all the blocks, then sanity-checks, and if the sanity-
|
||||
+ * checks fail, it tries to restart itself again. Very practical - no changes
|
||||
+ * are done until we know everything works ok.. and then all the changes can be
|
||||
+ * done in one fell swoop when we have claimed all the buffers needed.
|
||||
+ *
|
||||
+ * Anybody can rename anything that they have access to (and write access to the
|
||||
+ * parents) - except the '.' and '..' directories.
|
||||
+ */
|
||||
+ static int do_rename(const char * oldname, const char * newname)
|
||||
+ {
|
||||
+ struct m_inode * inode;
|
||||
+ struct m_inode * old_dir, * new_dir;
|
||||
+ struct buffer_head * old_bh, * new_bh, * dir_bh;
|
||||
+ struct dir_entry * old_de, * new_de;
|
||||
+ const char * old_base, * new_base;
|
||||
+ int old_len, new_len;
|
||||
+ int retval;
|
||||
+
|
||||
+ inode = old_dir = new_dir = NULL;
|
||||
+ old_bh = new_bh = dir_bh = NULL;
|
||||
+ old_dir = dir_namei(oldname,&old_len,&old_base, NULL);
|
||||
+ retval = -ENOENT;
|
||||
+ if (!old_dir)
|
||||
+ goto end_rename;
|
||||
+ retval = -EPERM;
|
||||
+ if (!old_len || get_fs_byte(old_base) == '.' &&
|
||||
+ (old_len == 1 || get_fs_byte(old_base+1) == '.' &&
|
||||
+ old_len == 2))
|
||||
+ goto end_rename;
|
||||
+ retval = -EACCES;
|
||||
+ if (!permission(old_dir,MAY_WRITE))
|
||||
+ goto end_rename;
|
||||
+ old_bh = find_entry(&old_dir,old_base,old_len,&old_de);
|
||||
+ retval = -ENOENT;
|
||||
+ if (!old_bh)
|
||||
+ goto end_rename;
|
||||
+ inode = iget(old_dir->i_dev, old_de->inode);
|
||||
+ if (!inode)
|
||||
+ goto end_rename;
|
||||
+ new_dir = dir_namei(newname,&new_len,&new_base, NULL);
|
||||
+ if (!new_dir)
|
||||
+ goto end_rename;
|
||||
+ retval = -EPERM;
|
||||
+ if (!new_len || get_fs_byte(new_base) == '.' &&
|
||||
+ (new_len == 1 || get_fs_byte(new_base+1) == '.' &&
|
||||
+ new_len == 2))
|
||||
+ goto end_rename;
|
||||
+ retval = -EACCES;
|
||||
+ if (!permission(new_dir, MAY_WRITE))
|
||||
+ goto end_rename;
|
||||
+ if (new_dir->i_dev != old_dir->i_dev)
|
||||
+ goto end_rename;
|
||||
+ new_bh = find_entry(&new_dir,new_base,new_len,&new_de);
|
||||
+ retval = -EEXIST;
|
||||
+ if (new_bh)
|
||||
+ goto end_rename;
|
||||
+ retval = -EPERM;
|
||||
+ if (S_ISDIR(inode->i_mode)) {
|
||||
+ if (!permission(inode, MAY_WRITE))
|
||||
+ goto end_rename;
|
||||
+ if (subdir(new_dir, inode))
|
||||
+ goto end_rename;
|
||||
+ retval = -EIO;
|
||||
+ if (!inode->i_zone[0])
|
||||
+ goto end_rename;
|
||||
+ if (!(dir_bh = bread(inode->i_dev, inode->i_zone[0])))
|
||||
+ goto end_rename;
|
||||
+ if (PARENT_INO(dir_bh->b_data) != old_dir->i_num)
|
||||
+ goto end_rename;
|
||||
+ }
|
||||
+ new_bh = add_entry(new_dir,new_base,new_len,&new_de);
|
||||
+ retval = -ENOSPC;
|
||||
+ if (!new_bh)
|
||||
+ goto end_rename;
|
||||
+ /* sanity checking before doing the rename - avoid races */
|
||||
+ retval = -ERESTARTNOINTR;
|
||||
+ if (new_de->inode || (old_de->inode != inode->i_num))
|
||||
+ goto end_rename;
|
||||
+ /* ok, that's it */
|
||||
+ old_de->inode = 0;
|
||||
+ new_de->inode = inode->i_num;
|
||||
+ old_bh->b_dirt = 1;
|
||||
+ new_bh->b_dirt = 1;
|
||||
+ if (dir_bh) {
|
||||
+ PARENT_INO(dir_bh->b_data) = new_dir->i_num;
|
||||
+ dir_bh->b_dirt = 1;
|
||||
+ old_dir->i_nlinks--;
|
||||
+ new_dir->i_nlinks++;
|
||||
+ old_dir->i_dirt = 1;
|
||||
+ new_dir->i_dirt = 1;
|
||||
+ }
|
||||
+ retval = 0;
|
||||
+ end_rename:
|
||||
+ brelse(dir_bh);
|
||||
+ brelse(old_bh);
|
||||
+ brelse(new_bh);
|
||||
+ iput(inode);
|
||||
+ iput(old_dir);
|
||||
+ iput(new_dir);
|
||||
+ return retval;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Ok, rename also locks out other renames, as they can change the parent of
|
||||
+ * a directory, and we don't want any races. Other races are checked for by
|
||||
+ * "do_rename()", which restarts if there are inconsistencies.
|
||||
+ */
|
||||
+ int sys_rename(const char * oldname, const char * newname)
|
||||
+ {
|
||||
+ static struct task_struct * wait = NULL;
|
||||
+ static int lock = 0;
|
||||
+ int result;
|
||||
+
|
||||
+ while (lock)
|
||||
+ sleep_on(&wait);
|
||||
+ lock = 1;
|
||||
+ result = do_rename(oldname, newname);
|
||||
+ lock = 0;
|
||||
+ wake_up(&wait);
|
||||
+ return result;
|
||||
+ }
|
||||
|
||||
Reference in New Issue
Block a user