increase system-wide filename limit to 255
. move mfs-specific struct, constants to mfs/, so mfs-specific, on-disk format structs and consts are fully isolated from generic structs and functions . removes de and readfs utils
This commit is contained in:
parent
e2bdf44720
commit
f984dbba70
48 changed files with 125 additions and 5451 deletions
|
@ -1515,7 +1515,7 @@ static void ls(char *dir)
|
|||
{
|
||||
ino_t ino;
|
||||
struct stat st;
|
||||
char name[NAME_MAX+1];
|
||||
char name[MFS_DIRSIZ+1];
|
||||
|
||||
if (fsok == -1) fsok= r_super(&block_size) != 0;
|
||||
if (!fsok) return;
|
||||
|
|
|
@ -1003,7 +1003,7 @@ ino_t latest_version(char *version, struct stat *stp)
|
|||
* the way up. (One can't use r_stat while reading a directory.)
|
||||
*/
|
||||
{
|
||||
char name[NAME_MAX + 1];
|
||||
char name[MFS_DIRSIZ + 1];
|
||||
ino_t ino, newest;
|
||||
time_t mtime;
|
||||
|
||||
|
@ -1032,7 +1032,7 @@ char *select_image(char *image)
|
|||
ino_t image_ino;
|
||||
struct stat st;
|
||||
|
||||
image= strcpy(malloc((strlen(image) + 1 + NAME_MAX + 1)
|
||||
image= strcpy(malloc((strlen(image) + 1 + MFS_DIRSIZ + 1)
|
||||
* sizeof(char)), image);
|
||||
|
||||
fsok= r_super(&block_size) != 0;
|
||||
|
@ -1059,7 +1059,7 @@ char *select_image(char *image)
|
|||
|
||||
if (!S_ISREG(st.st_mode)) {
|
||||
char *version= image + strlen(image);
|
||||
char dots[NAME_MAX + 1];
|
||||
char dots[MFS_DIRSIZ + 1];
|
||||
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
printf("%s: %s\n", image, unix_err(ENOTDIR));
|
||||
|
|
29
boot/rawfs.c
29
boot/rawfs.c
|
@ -15,10 +15,10 @@
|
|||
#include <minix/type.h>
|
||||
#include <servers/mfs/const.h>
|
||||
#include <servers/mfs/type.h>
|
||||
#include <servers/mfs/buf.h>
|
||||
#include <servers/mfs/super.h>
|
||||
#include <servers/mfs/inode.h>
|
||||
#include "rawfs.h"
|
||||
#include <servers/mfs/buf.h>
|
||||
|
||||
void readblock(off_t blockno, char *buf, int);
|
||||
|
||||
|
@ -36,12 +36,6 @@ static unsigned nr_dzones; /* Fill these in after reading superblock. */
|
|||
static unsigned nr_indirects;
|
||||
static unsigned inodes_per_block;
|
||||
static int block_size;
|
||||
#ifdef FLEX
|
||||
#include <dirent.h>
|
||||
#define direct _v7_direct
|
||||
#else
|
||||
#include <sys/dir.h>
|
||||
#endif
|
||||
|
||||
#if __minix_vmd
|
||||
static struct v12_super_block super; /* Superblock of file system */
|
||||
|
@ -192,24 +186,13 @@ ino_t r_readdir(char *name)
|
|||
|
||||
readblock(r_vir2abs(dirpos / block_size), dirbuf, block_size);
|
||||
}
|
||||
#ifdef FLEX
|
||||
if (super.s_flags & S_FLEX) {
|
||||
struct _fl_direct *dp;
|
||||
|
||||
dp= (struct _fl_direct *) (dirbuf + blkpos);
|
||||
if ((inum= dp->d_ino) != 0) strcpy(name, dp->d_name);
|
||||
|
||||
dirpos+= (1 + dp->d_extent) * FL_DIR_ENTRY_SIZE;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
/* Let dp point to the next entry. */
|
||||
dp= (struct direct *) (dirbuf + blkpos);
|
||||
|
||||
if ((inum= dp->d_ino) != 0) {
|
||||
if ((inum= dp->mfs_d_ino) != 0) {
|
||||
/* This entry is occupied, return name. */
|
||||
strncpy(name, dp->d_name, sizeof(dp->d_name));
|
||||
name[sizeof(dp->d_name)]= 0;
|
||||
strncpy(name, dp->mfs_d_name, sizeof(dp->mfs_d_name));
|
||||
name[sizeof(dp->mfs_d_name)]= 0;
|
||||
}
|
||||
dirpos+= DIR_ENTRY_SIZE;
|
||||
}
|
||||
|
@ -290,7 +273,7 @@ ino_t r_lookup(Ino_t cwd, const char *path)
|
|||
* function, it only needs r_stat and r_readdir.
|
||||
*/
|
||||
{
|
||||
char name[NAME_MAX+1], r_name[NAME_MAX+1];
|
||||
char name[MFS_DIRSIZ+1], r_name[MFS_DIRSIZ+1];
|
||||
char *n;
|
||||
struct stat st;
|
||||
ino_t ino;
|
||||
|
@ -316,7 +299,7 @@ ino_t r_lookup(Ino_t cwd, const char *path)
|
|||
|
||||
n= name;
|
||||
while (*path != 0 && *path != '/')
|
||||
if (n < name + NAME_MAX) *n++ = *path++;
|
||||
if (n < name + MFS_DIRSIZ) *n++ = *path++;
|
||||
*n= 0;
|
||||
|
||||
while ((ino= r_readdir(r_name)) != 0
|
||||
|
|
|
@ -33,6 +33,9 @@
|
|||
#ifndef INC_RAWFS_H
|
||||
#define INC_RAWFS_H
|
||||
|
||||
#include <minix/dirent.h>
|
||||
#include <servers/mfs/mfsdir.h>
|
||||
|
||||
#define ROOT_INO ((ino_t) 1) /* Inode nr of root dir. */
|
||||
|
||||
extern off_t r_super(int *);
|
||||
|
|
|
@ -8,7 +8,7 @@ SUBDIR= aal add_route adduser arp ash at autil awk \
|
|||
cat cawf cd cdprobe checkhier chmem \
|
||||
chmod chown chroot ci cksum cleantmp clear cmp co \
|
||||
comm compress cp crc cron crontab cut date \
|
||||
dd de decomp16 DESCRIBE dev2name devsize df dhcpd \
|
||||
dd decomp16 DESCRIBE dev2name devsize df dhcpd \
|
||||
dhrystone diff dirname dis386 dis88 diskctl du dumpcore \
|
||||
ed eject elle elvis env expand factor file \
|
||||
find finger fingerd fix fold format fortune fsck.mfs \
|
||||
|
@ -23,7 +23,7 @@ SUBDIR= aal add_route adduser arp ash at autil awk \
|
|||
ping postinstall poweroff pr prep printf printroot \
|
||||
profile progressbar proto pr_routes ps pwd pwdauth \
|
||||
ramdisk rarpd rawspeed rcp rdate readall readclock \
|
||||
readfs reboot remsync rev rget rlogin rlogind rmdir \
|
||||
reboot remsync rev rget rlogin rlogind rmdir \
|
||||
rotate rsh rshd sed service setup shar acksize \
|
||||
sleep slip sort spell split srccrc ackstrip \
|
||||
stty su sum svclog swifi sync synctree sysenv \
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
#endif
|
||||
#include <assert.h>
|
||||
|
||||
#include <sys/dir.h>
|
||||
|
||||
/* Copy files in this size chunks: */
|
||||
#if __minix && !__minix_vmd
|
||||
#define CHUNK (8192 * sizeof(char *))
|
||||
|
@ -129,7 +127,7 @@ typedef struct pathname {
|
|||
void path_init(pathname_t *pp)
|
||||
/* Initialize a pathname to the null string. */
|
||||
{
|
||||
pp->path= allocate(nil, pp->lim= DIRSIZ + 2);
|
||||
pp->path= allocate(nil, pp->lim= NAME_MAX + 2);
|
||||
pp->path[pp->idx= 0]= 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
# Makefile for de
|
||||
|
||||
PROG= de
|
||||
SRCS= de.c de_stdin.c de_stdout.c de_diskio.c de_recover.c
|
||||
CPPFLAGS+= -I${MINIXSRCDIR}/servers
|
||||
CPPFLAGS+= -D_POSIX_1_SOURCE=2
|
||||
MAN=
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -1,156 +0,0 @@
|
|||
de - A Minix Disk Editor
|
||||
|
||||
Terrence W. Holm, Jan. 1989
|
||||
|
||||
|
||||
INTRODUCTION
|
||||
|
||||
The de(1) disk editor allows a system administrator to
|
||||
look at and modify a Minix file system device. Commands
|
||||
allow movement throughout a file system device, displaying
|
||||
information in a couple of formats, writing blocks from
|
||||
the device onto another file, and rewriting words on the
|
||||
disk.
|
||||
|
||||
A few changes to the Minix file system aid recovering files.
|
||||
I-node numbers are retained in directory entries now (they
|
||||
get moved to the end). And all the i-node information is not
|
||||
zeroed-out when a file is unlinked. So, after a file is
|
||||
accidently rm(1)'ed, you can find the old i-node, and then
|
||||
manually (or automatically) go to each of the freed blocks
|
||||
and write them to a new file.
|
||||
|
||||
|
||||
USES FOR THE DISK EDITOR
|
||||
|
||||
1) EDUCATION. Students can look at a file system in
|
||||
a painless manner. For example you don't have to
|
||||
use od(1) to look at the zone numbers in i-nodes.
|
||||
|
||||
A simple assignment is to change the size of an un-mounted
|
||||
floppy disk file system from 360 to 300 blocks. (A more
|
||||
difficult assignment is to explain why this works, even
|
||||
though fsck(1) and df(1) do not report the correct number
|
||||
of free blocks. :-)
|
||||
|
||||
2) ADMINISTRATION. You can visually check inconsistencies
|
||||
reported by fsck(1) before letting fsck(1) fix them.
|
||||
You can change any word on the disk, this greatly simplifies
|
||||
editing file system information. For example, changing the
|
||||
size of a block special device is actually fun, no more
|
||||
"blind" writing to your partitions.
|
||||
|
||||
Bit maps can be displayed with 2048 "bits" per screen,
|
||||
(on the IBM/PC console), see how your zones are allocated!
|
||||
|
||||
3) RECOVERING LOST FILES. You can search a disk for an ASCII
|
||||
string, once found, the block can be written out to a file.
|
||||
|
||||
A one line change to fs/path.c allows users to get the i-node
|
||||
number for a file after it has been removed from a directory.
|
||||
|
||||
Another couple lines changed in the file system keep the
|
||||
i-node information available until the i-node is reused
|
||||
(normally this information is zeroed out when an i-node is
|
||||
released.) This allows a de(1) user to go to a released
|
||||
i-node, get all the block numbers, go to these blocks and
|
||||
write them back to a new file.
|
||||
|
||||
The whole recovery process is automated by running "de -r file".
|
||||
So, IF a file is unlink(2)'ed (eg. "rm file"), AND IF no one
|
||||
allocates a new i-node or block in the mean-time, THEN you
|
||||
can recover the file.
|
||||
|
||||
|
||||
RECOVERY SECURITY
|
||||
|
||||
Normally Minix hard disk partitions are r/w only by the super-user,
|
||||
and floppy disks are r/w by anyone. This means that only "root"
|
||||
can look at hard disk partitions, but others can use de(1) to play
|
||||
with their floppy disks.
|
||||
|
||||
When recovering files ("de -r file"), a user requires access to
|
||||
the major file system partitions. This can be done by:
|
||||
|
||||
(a) Give everyone access to the hard disks. DON'T DO THIS, it
|
||||
defeats all the file system protection we already have.
|
||||
|
||||
(b) Make de(1) set-uid "root". This is the way to go, IF you
|
||||
are running a Minix system that has NO ACCESS from the
|
||||
outside. This allows anyone to execute "de -r file", but only
|
||||
root to use "de /dev/hd3". De(1) does some checking when
|
||||
retrieving lost blocks, eg. making sure they really are
|
||||
free blocks and making sure the user owned the i-node.
|
||||
BUT, file system information has been lost when the file
|
||||
was unlink(2)'ed, so de(1) can not be 100% sure that a
|
||||
recovered block really belonged to the user. THIS IS A
|
||||
SECURITY HOLE. [Since the only access to my machine is from
|
||||
observable terminals and their associated humans, I run
|
||||
de(1) as set-uid root.]
|
||||
|
||||
(c) Keep the disks rw-------, and don't set-uid de(1). This
|
||||
means that only the super-user can recover lost files.
|
||||
So, if you accidently "rm", you must tell the system
|
||||
administrator to "su" and recover your file, (be sure to
|
||||
inform the other users to stop whatever they are doing
|
||||
until the file is restored).
|
||||
|
||||
|
||||
INSTALLATION
|
||||
|
||||
- Install de.1 in /usr/man/cat1.
|
||||
|
||||
- Install the files: Makefile, README, de.h, de.c, de_stdin.c,
|
||||
de_stdout.c, de_diskio.c and de_recover.c in commands/de.
|
||||
Add -F and -T. to the Makefile, if necessary.
|
||||
|
||||
- "make" de(1). If a header file is not found, don't worry:
|
||||
You probably have it somewhere, just link it to what de(1)
|
||||
is looking for. This program also requires the subroutine
|
||||
tolower(3), see EFTH MINIX report #50, if you don't have it.
|
||||
|
||||
- Do you really want set-uid root on de?
|
||||
|
||||
- Patch the files fs/path.c, fs/link.c and fs/open.c. If
|
||||
you don't patch the file system then the recover option
|
||||
"-r" and associated commands ('x' and 'X') will not work,
|
||||
but de(1) is still functional and useful.
|
||||
|
||||
- "make" a new fs, using -DRECOVER. Rebuild a boot diskette.
|
||||
|
||||
|
||||
USING DE(1) FOR THE FIRST TIME
|
||||
|
||||
De(1) starts up in "word" mode at block 0 of the specified
|
||||
device. Hit the PGDN (or space bar) a few times, observing
|
||||
all the information on the screen. Each PGUP/PGDN moves to
|
||||
the next 1024 byte block, (de(1) only knows about 1 block per
|
||||
zone file systems). Note that "word" mode only displays 32
|
||||
bytes at a time, so you are only observing the first 32 bytes
|
||||
in the first few blocks when you skip using PGDN.
|
||||
|
||||
Now go back to block 3, (zone bit map), using "g 3 ENTER".
|
||||
Change to "map" mode "v m", and then use the down arrow key
|
||||
to check each 2 Megs in the zone bit map.
|
||||
|
||||
Now change to "block" mode using "v b". And go to some data
|
||||
block, eg. "g 1000 ENTER". Use PGUP/PGDN to see what data
|
||||
is in each nearby block.
|
||||
|
||||
Remember 'h' gives you a help page.
|
||||
|
||||
Try some more commands, for example: 'END', 'I', '/'.
|
||||
(Note: searching through a whole disk under Minix takes a
|
||||
long time: 30-60 seconds per megabyte, depending on your
|
||||
machine, drive and controller, [Minix is embarrassingly slow].)
|
||||
|
||||
Don't worry about looking at a mounted device, you must specify
|
||||
the "-w" option before the 's' command is operational, and
|
||||
this command is the only one which will try to modify the
|
||||
contents of the device.
|
||||
|
||||
|
||||
MINIX-ST
|
||||
|
||||
Please contact me if you are interesting in attempting a port
|
||||
to MINIX-ST.
|
1335
commands/de/de.c
1335
commands/de/de.c
File diff suppressed because it is too large
Load diff
345
commands/de/de.h
345
commands/de/de.h
|
@ -1,345 +0,0 @@
|
|||
/****************************************************************/
|
||||
/* */
|
||||
/* de.h */
|
||||
/* */
|
||||
/* Definitions for the "Disk editor". */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
/* origination 1989-Jan-15 Terrence W. Holm */
|
||||
/****************************************************************/
|
||||
|
||||
|
||||
/****************************************************************/
|
||||
/* */
|
||||
/* de(1) */
|
||||
/* */
|
||||
/* This is the MINIX disk editor. It allows the user to */
|
||||
/* observe and modify a file system. It can also be used */
|
||||
/* to recover unlink(2)'ed files */
|
||||
/* */
|
||||
/* See the de(1) man page. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
|
||||
/****************************************************************/
|
||||
/* */
|
||||
/* de Copyright Terrence W. Holm 1989 */
|
||||
/* */
|
||||
/* This program was written for users of the Minix operating */
|
||||
/* system, and in the spirit of other public domain software */
|
||||
/* written for said system, this source code is made available */
|
||||
/* at no cost to everyone. I assume no responsibility for */
|
||||
/* damage to file systems caused by this program. */
|
||||
/* */
|
||||
/* This program (one .h, five .c's and a "man" page) may be */
|
||||
/* copied and/or modified subject to (1) no charge must be */
|
||||
/* made for distribution, other than for the medium, (2) all */
|
||||
/* modified sources must be clearly marked as such, (3) all */
|
||||
/* sources must carry this copyright. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
|
||||
/****************************************************************/
|
||||
/* */
|
||||
/* files */
|
||||
/* */
|
||||
/* de.h Definitions */
|
||||
/* de.c The main loop */
|
||||
/* de_stdin.c Character input routines */
|
||||
/* de_stdout.c Output routines */
|
||||
/* de_diskio.c File system read/write */
|
||||
/* de_recover.c File restoration routines */
|
||||
/* */
|
||||
/* de.1 "Man" page */
|
||||
/* Makefile For "make" */
|
||||
/* README Installation help */
|
||||
/* */
|
||||
/* */
|
||||
/* fs/path.c was modified to support the 'x' command. */
|
||||
/* fs/link.c and fs/open.c were changed for 'X'. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
#undef printf
|
||||
#include <stdio.h>
|
||||
#include <dirent.h>
|
||||
|
||||
/* General constants */
|
||||
|
||||
#define MAX_STRING 60 /* For all input lines */
|
||||
#define MAX_PREV 8 /* For 'p' command */
|
||||
#define SEARCH_BUFFER (4*K) /* For '/' and 'n' */
|
||||
|
||||
|
||||
/* Files */
|
||||
|
||||
#define TMP "/tmp" /* For "-r" output */
|
||||
#define DEV "/dev" /* Where devices are */
|
||||
|
||||
|
||||
/* a.out header constants (see a.out.h, if you have it) */
|
||||
|
||||
#if (_MINIX_CHIP == _CHIP_INTEL)
|
||||
#define A_OUT 0x0301
|
||||
#define SPLIT 0x0420
|
||||
#else
|
||||
#error only chip == intel is reasonable.
|
||||
#endif
|
||||
|
||||
/* Each buffer is 1k. In WORD mode 16 words (32 bytes) can be */
|
||||
/* displayed at once. In BLOCK mode 1K bytes can be displayed. */
|
||||
/* In MAP mode 2048 bits (256 bytes) are displayed. */
|
||||
|
||||
#define K 1024 /* STD_BLK */
|
||||
#define K_MASK (~(K-1)) /* Round to K boundary */
|
||||
#define K_SHIFT 10 /* Ie. 1<<10 = K */
|
||||
#ifdef __NBSD_LIBC
|
||||
/* Name pollution with more famous macros describing machine's
|
||||
* page size. These defs should be renamed. */
|
||||
#undef PAGE_MASK
|
||||
#undef PAGE_SHIFT
|
||||
#endif /* __NBSD_LIBC */
|
||||
#define PAGE_MASK 0x1f /* Word mode: 32 bytes */
|
||||
#define PAGE_SHIFT 5 /* Ie. 1<<5 = 32 */
|
||||
#define MAP_BITS_PER_BLOCK (8 * K) /* 1k block, 8192 bits */
|
||||
#define MAP_MASK 0xff /* 256 bytes/screen */
|
||||
|
||||
|
||||
|
||||
/* Terminal i/o codes */
|
||||
|
||||
#define CTRL_D '\004' /* ASCII ^D */
|
||||
#define BELL '\007' /* ASCII bell code */
|
||||
#define BS '\010' /* ASCII back space */
|
||||
#define CTRL_U '\025' /* ASCII ^U */
|
||||
#define ESCAPE '\033' /* ASCII escape code */
|
||||
#define DEL '\177' /* ASCII delete code */
|
||||
|
||||
|
||||
/* Input escape codes generated by the Minix console. */
|
||||
/* Format: ESC [ X. */
|
||||
|
||||
#define ESC_HOME ('H' + 0x80)
|
||||
#define ESC_UP ('A' + 0x80)
|
||||
#define ESC_PGUP ('V' + 0x80)
|
||||
#define ESC_LEFT ('D' + 0x80)
|
||||
#define ESC_5 ('G' + 0x80)
|
||||
#define ESC_RIGHT ('C' + 0x80)
|
||||
#define ESC_END ('Y' + 0x80)
|
||||
#define ESC_DOWN ('B' + 0x80)
|
||||
#define ESC_PGDN ('U' + 0x80)
|
||||
#define ESC_PLUS ('T' + 0x80)
|
||||
#define ESC_MINUS ('S' + 0x80)
|
||||
|
||||
|
||||
/* Graphic box codes - only applicable for console display */
|
||||
/* in visual mode "map". */
|
||||
|
||||
#if (CHIP == INTEL)
|
||||
#define BOX_CLR ' ' /* Empty box */
|
||||
#define BOX_ALL '\333' /* Filled box */
|
||||
#define BOX_TOP '\337' /* Filled upper half */
|
||||
#define BOX_BOT '\334' /* Filled lower half */
|
||||
#endif
|
||||
|
||||
/* Move positions for the output display. */
|
||||
|
||||
#define STATUS_COLUMN 2
|
||||
#define STATUS_LINE 0
|
||||
#define BLOCK_COLUMN 4
|
||||
#define BLOCK_LINE 4
|
||||
#define INFO_COLUMN 30
|
||||
#define INFO_LINE BLOCK_LINE
|
||||
#define PROMPT_COLUMN 0
|
||||
#define PROMPT_LINE 23
|
||||
#define WARNING_COLUMN 5
|
||||
#define WARNING_LINE 10
|
||||
|
||||
|
||||
|
||||
/* Values returned by Process() and Get_Filename() */
|
||||
|
||||
#define OK 0 /* No update required */
|
||||
#define REDRAW 1 /* Redraw whole screen */
|
||||
#define REDRAW_POINTERS 2 /* Redraw just ptrs */
|
||||
#define ERROR 3 /* Beep */
|
||||
|
||||
|
||||
/* Visual modes */
|
||||
|
||||
#define WORD 1
|
||||
#define BLOCK 2
|
||||
#define MAP 3
|
||||
|
||||
typedef unsigned short word_t; /* For most user i/o */
|
||||
#if _WORD_SIZE == 2
|
||||
typedef unsigned int Word_t; /* What it should always be */
|
||||
#else
|
||||
typedef int Word_t; /* Unsigned promotion under ANSI C */
|
||||
#endif
|
||||
|
||||
#ifndef I_MAP_SLOTS
|
||||
/* Max number of inode and zone map blocks we can handle. */
|
||||
#define I_MAP_SLOTS 8
|
||||
#define Z_MAP_SLOTS (sizeof(char *) == 2 ? 16 : 128)
|
||||
#endif
|
||||
|
||||
typedef struct de_state /* State of disk ed. */
|
||||
{
|
||||
/* Information from super block */
|
||||
/* The types here are mostly promoted types for simplicity */
|
||||
/* and efficiency. */
|
||||
|
||||
unsigned inodes; /* Number of i-nodes */
|
||||
zone_t zones; /* Total # of blocks */
|
||||
unsigned inode_maps; /* I-node map blocks */
|
||||
unsigned zone_maps; /* Zone map blocks */
|
||||
unsigned inode_blocks; /* I-node blocks */
|
||||
unsigned first_data; /* Total non-data blks */
|
||||
int magic; /* Magic number */
|
||||
|
||||
/* Numbers derived from the magic number */
|
||||
|
||||
unsigned char is_fs; /* Nonzero for good fs */
|
||||
unsigned char v1; /* Nonzero for V1 fs */
|
||||
unsigned inode_size; /* Size of disk inode */
|
||||
unsigned nr_indirects; /* # indirect blocks */
|
||||
unsigned zone_num_size; /* Size of disk z num */
|
||||
int block_size; /* FS block size */
|
||||
|
||||
/* Other derived numbers */
|
||||
|
||||
bit_t inodes_in_map; /* Bits in i-node map */
|
||||
bit_t zones_in_map; /* Bits in zone map */
|
||||
int ndzones; /* # direct zones in an inode */
|
||||
|
||||
/* Information from map blocks */
|
||||
|
||||
bitchunk_t inode_map[ I_MAP_SLOTS * K / sizeof (bitchunk_t) ];
|
||||
bitchunk_t zone_map[ Z_MAP_SLOTS * K / sizeof (bitchunk_t) ];
|
||||
|
||||
/* Information for current block */
|
||||
|
||||
off_t address; /* Current address */
|
||||
off_t last_addr; /* For erasing ptrs */
|
||||
zone_t block; /* Current block (1K) */
|
||||
unsigned offset; /* Offset within block */
|
||||
|
||||
char buffer[ _MAX_BLOCK_SIZE ];
|
||||
|
||||
/* Display state */
|
||||
|
||||
int mode; /* WORD, BLOCK or MAP */
|
||||
int output_base; /* 2, 8, 10, or 16 */
|
||||
|
||||
/* Search information */
|
||||
|
||||
char search_string[ MAX_STRING + 1 ]; /* For '/' and 'n' */
|
||||
off_t prev_addr[ MAX_PREV ]; /* For 'p' command */
|
||||
int prev_mode[ MAX_PREV ];
|
||||
|
||||
/* File information */
|
||||
|
||||
char *device_name; /* From command line */
|
||||
int device_d;
|
||||
int device_mode; /* O_RDONLY or O_RDWR */
|
||||
zone_t device_size; /* Number of blocks */
|
||||
|
||||
char file_name[ MAX_STRING + 1 ]; /* For 'w' and 'W' */
|
||||
FILE *file_f;
|
||||
int file_written; /* Flag if written to */
|
||||
|
||||
} de_state;
|
||||
|
||||
|
||||
|
||||
/* Forward references for external routines */
|
||||
|
||||
/* de.c */
|
||||
|
||||
_PROTOTYPE(int main , (int argc , char *argv []));
|
||||
_PROTOTYPE(int Process , (de_state *s , int c ));
|
||||
|
||||
#if __STDC__
|
||||
void Error( const char *text, ... );
|
||||
#else
|
||||
void Error();
|
||||
#endif
|
||||
|
||||
_PROTOTYPE(int In_Use , (bit_t bit , bitchunk_t *map ));
|
||||
_PROTOTYPE(ino_t Find_Inode , (de_state *s , char *filename ));
|
||||
|
||||
|
||||
/* de_stdin.c */
|
||||
|
||||
_PROTOTYPE(void Save_Term , (void));
|
||||
_PROTOTYPE(void Set_Term , (void));
|
||||
_PROTOTYPE(void Reset_Term , (void));
|
||||
_PROTOTYPE(int Get_Char , (void));
|
||||
_PROTOTYPE(char *Get_Line , (void));
|
||||
_PROTOTYPE(int Arrow_Esc , (int c ));
|
||||
|
||||
/* de_stdout.c */
|
||||
|
||||
_PROTOTYPE(int Init_Termcap , (void));
|
||||
_PROTOTYPE(void Draw_Help_Screen , (de_state *s ));
|
||||
_PROTOTYPE(void Wait_For_Key , (void));
|
||||
_PROTOTYPE(void Draw_Prompt , (char *string ));
|
||||
_PROTOTYPE(void Erase_Prompt , (void));
|
||||
|
||||
_PROTOTYPE(void Draw_Screen , (de_state *s ));
|
||||
_PROTOTYPE(void Draw_Strings , (de_state *s ));
|
||||
_PROTOTYPE(void Draw_Pointers , (de_state *s ));
|
||||
_PROTOTYPE(void Print_Ascii , (int c ));
|
||||
|
||||
_PROTOTYPE(void Goto , (int column , int line ));
|
||||
_PROTOTYPE(void Block_Type , (de_state *s ));
|
||||
_PROTOTYPE(void Draw_Words , (de_state *s ));
|
||||
_PROTOTYPE(void Draw_Info , (de_state *s ));
|
||||
_PROTOTYPE(void Draw_Block , (char *block ));
|
||||
_PROTOTYPE(void Draw_Map , (char *block , int max_bits ));
|
||||
_PROTOTYPE(void Draw_Offset , (de_state *s ));
|
||||
_PROTOTYPE(void Word_Pointers , (off_t old_addr , off_t new_addr ));
|
||||
_PROTOTYPE(void Block_Pointers , (off_t old_addr , off_t new_addr ));
|
||||
_PROTOTYPE(void Map_Pointers , (off_t old_addr , off_t new_addr ));
|
||||
_PROTOTYPE(void Print_Number , (Word_t number , int output_base ));
|
||||
_PROTOTYPE(void Draw_Zone_Numbers , (de_state *s , struct inode *inode ,
|
||||
int zindex , int zrow ));
|
||||
|
||||
#if __STDC__
|
||||
void Warning( const char *text, ... );
|
||||
#else
|
||||
void Warning();
|
||||
#endif
|
||||
|
||||
|
||||
/* de_diskio.c */
|
||||
|
||||
_PROTOTYPE(void Read_Disk , (de_state *s , off_t block_addr , char *buffer ));
|
||||
_PROTOTYPE(void Read_Block , (de_state *s , char *buffer ));
|
||||
_PROTOTYPE(void Read_Super_Block , (de_state *s ));
|
||||
_PROTOTYPE(void Read_Bit_Maps , (de_state *s ));
|
||||
_PROTOTYPE(off_t Search , (de_state *s , char *string ));
|
||||
_PROTOTYPE(void Write_Word , (de_state *s , Word_t word ));
|
||||
|
||||
|
||||
/* de_recover.c */
|
||||
|
||||
_PROTOTYPE(int Path_Dir_File , (char *path_name , char **dir_name ,
|
||||
char **file_name ));
|
||||
_PROTOTYPE(char *File_Device , (char *file_name ));
|
||||
_PROTOTYPE(ino_t Find_Deleted_Entry , (de_state *s , char *path_name ));
|
||||
_PROTOTYPE(off_t Recover_Blocks , (de_state *s ));
|
||||
|
||||
|
||||
#undef printf /* Because fs/const.h */
|
||||
/* defines it. */
|
||||
|
||||
|
||||
/* Static functions are all pre-declared FORWARD but none are */
|
||||
/* declared static yet - this can wait until all functions are */
|
||||
/* declared with prototypes. */
|
||||
|
||||
#undef FORWARD
|
||||
#define FORWARD /* static */
|
|
@ -1,353 +0,0 @@
|
|||
/****************************************************************/
|
||||
/* */
|
||||
/* de_diskio.c */
|
||||
/* */
|
||||
/* Reading and writing to a file system device. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
/* origination 1989-Jan-15 Terrence W. Holm */
|
||||
/****************************************************************/
|
||||
|
||||
|
||||
#include <minix/config.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include <minix/const.h>
|
||||
#include <minix/type.h>
|
||||
#include "mfs/const.h"
|
||||
#include "mfs/type.h"
|
||||
#include "mfs/super.h"
|
||||
#include "mfs/inode.h"
|
||||
#include <minix/fslib.h>
|
||||
|
||||
#include "de.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************/
|
||||
/* */
|
||||
/* Read_Disk( state, block_addr, buffer ) */
|
||||
/* */
|
||||
/* Reads a 1k block at "block_addr" into "buffer". */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
|
||||
void Read_Disk( s, block_addr, buffer )
|
||||
de_state *s;
|
||||
off_t block_addr;
|
||||
char *buffer;
|
||||
|
||||
{
|
||||
if ( lseek( s->device_d, block_addr, SEEK_SET ) == -1 )
|
||||
Error( "Error seeking %s", s->device_name );
|
||||
|
||||
if ( read( s->device_d, buffer, s->block_size ) != s->block_size )
|
||||
Error( "Error reading %s", s->device_name );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************/
|
||||
/* */
|
||||
/* Read_Block( state, buffer ) */
|
||||
/* */
|
||||
/* Reads a 1k block from "state->address" into */
|
||||
/* "buffer". Checks "address", and updates */
|
||||
/* "block" and "offset". */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
|
||||
void Read_Block( s, buffer )
|
||||
de_state *s;
|
||||
char *buffer;
|
||||
|
||||
{
|
||||
off_t end_addr;
|
||||
off_t block_addr;
|
||||
end_addr = (long) s->device_size * s->block_size - 1;
|
||||
|
||||
if ( s->address < 0 )
|
||||
s->address = 0L;
|
||||
|
||||
if ( s->address > end_addr )
|
||||
s->address = end_addr;
|
||||
|
||||
/* The address must be rounded off for */
|
||||
/* certain visual display modes. */
|
||||
|
||||
if ( s->mode == WORD )
|
||||
s->address &= ~1L;
|
||||
else if ( s->mode == MAP )
|
||||
s->address &= ~3L;
|
||||
|
||||
|
||||
block_addr = s->address & K_MASK;
|
||||
|
||||
s->block = (zone_t) (block_addr >> K_SHIFT);
|
||||
s->offset = (unsigned) (s->address - block_addr);
|
||||
|
||||
Read_Disk( s, block_addr, buffer );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************/
|
||||
/* */
|
||||
/* Read_Super_Block( state ) */
|
||||
/* */
|
||||
/* Read and check the super block. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
|
||||
void Read_Super_Block( s )
|
||||
de_state *s;
|
||||
|
||||
{
|
||||
struct super_block *super = (struct super_block *) s->buffer;
|
||||
unsigned inodes_per_block;
|
||||
off_t size;
|
||||
|
||||
s->block_size = K;
|
||||
Read_Disk( s, (long) SUPER_BLOCK_BYTES, s->buffer );
|
||||
|
||||
s->magic = super->s_magic;
|
||||
if ( s->magic == SUPER_MAGIC )
|
||||
{
|
||||
s->is_fs = TRUE;
|
||||
s->v1 = TRUE;
|
||||
s->inode_size = V1_INODE_SIZE;
|
||||
inodes_per_block = V1_INODES_PER_BLOCK;
|
||||
s->nr_indirects = V1_INDIRECTS;
|
||||
s->zone_num_size = V1_ZONE_NUM_SIZE;
|
||||
s->zones = super->s_nzones;
|
||||
s->ndzones = V1_NR_DZONES;
|
||||
s->block_size = _STATIC_BLOCK_SIZE;
|
||||
}
|
||||
else if ( s->magic == SUPER_V2 || s->magic == SUPER_V3)
|
||||
{
|
||||
if(s->magic == SUPER_V3)
|
||||
s->block_size = super->s_block_size;
|
||||
else
|
||||
s->block_size = _STATIC_BLOCK_SIZE;
|
||||
s->is_fs = TRUE;
|
||||
s->v1 = FALSE;
|
||||
s->inode_size = V2_INODE_SIZE;
|
||||
inodes_per_block = V2_INODES_PER_BLOCK(s->block_size);
|
||||
s->nr_indirects = V2_INDIRECTS(s->block_size);
|
||||
s->zone_num_size = V2_ZONE_NUM_SIZE;
|
||||
s->zones = super->s_zones;
|
||||
s->ndzones = V2_NR_DZONES;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( super->s_magic == SUPER_REV )
|
||||
Warning( "V1-bytes-swapped file system (?)" );
|
||||
else if ( super->s_magic == SUPER_V2_REV )
|
||||
Warning( "V2-bytes-swapped file system (?)" );
|
||||
else
|
||||
Warning( "Not a Minix file system" );
|
||||
Warning( "The file system features will not be available" );
|
||||
s->zones = 100000L;
|
||||
return;
|
||||
}
|
||||
|
||||
s->inodes = super->s_ninodes;
|
||||
s->inode_maps = bitmapsize( (bit_t) s->inodes + 1 , s->block_size);
|
||||
if ( s->inode_maps != super->s_imap_blocks )
|
||||
{
|
||||
if ( s->inode_maps > super->s_imap_blocks )
|
||||
Error( "Corrupted inode map count or inode count in super block" );
|
||||
else
|
||||
Warning( "Count of inode map blocks in super block suspiciously high" );
|
||||
s->inode_maps = super->s_imap_blocks;
|
||||
}
|
||||
|
||||
s->zone_maps = bitmapsize( (bit_t) s->zones , s->block_size);
|
||||
if ( s->zone_maps != super->s_zmap_blocks )
|
||||
{
|
||||
if ( s->zone_maps > super->s_zmap_blocks )
|
||||
Error( "Corrupted zone map count or zone count in super block" );
|
||||
else
|
||||
Warning( "Count of zone map blocks in super block suspiciously high" );
|
||||
s->zone_maps = super->s_zmap_blocks;
|
||||
}
|
||||
|
||||
s->inode_blocks = (s->inodes + inodes_per_block - 1) / inodes_per_block;
|
||||
s->first_data = 2 + s->inode_maps + s->zone_maps + s->inode_blocks;
|
||||
if ( super->s_firstdatazone_old != 0 &&
|
||||
s->first_data != super->s_firstdatazone_old )
|
||||
{
|
||||
if ( s->first_data > super->s_firstdatazone_old )
|
||||
Error( "Corrupted first data zone offset or inode count in super block" );
|
||||
else
|
||||
Warning( "First data zone in super block suspiciously high" );
|
||||
s->first_data = super->s_firstdatazone_old;
|
||||
}
|
||||
|
||||
s->inodes_in_map = s->inodes + 1;
|
||||
s->zones_in_map = s->zones + 1 - s->first_data;
|
||||
|
||||
/*
|
||||
if ( s->zones != s->device_size )
|
||||
Warning( "Zone count does not equal device size" );
|
||||
*/
|
||||
|
||||
s->device_size = s->zones;
|
||||
|
||||
if ( super->s_log_zone_size != 0 )
|
||||
Error( "Can not handle multiple blocks per zone" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************/
|
||||
/* */
|
||||
/* Read_Bit_Maps( state ) */
|
||||
/* */
|
||||
/* Read in the i-node and zone bit maps from the */
|
||||
/* specified file system device. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
|
||||
void Read_Bit_Maps( s )
|
||||
de_state *s;
|
||||
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( s->inode_maps > I_MAP_SLOTS || s->zone_maps > Z_MAP_SLOTS )
|
||||
{
|
||||
Warning( "Super block specifies too many bit map blocks" );
|
||||
return;
|
||||
}
|
||||
|
||||
for ( i = 0; i < s->inode_maps; ++i )
|
||||
{
|
||||
Read_Disk( s, (long) (2 + i) * K,
|
||||
(char *) &s->inode_map[ i * K / sizeof (bitchunk_t ) ] );
|
||||
}
|
||||
|
||||
for ( i = 0; i < s->zone_maps; ++i )
|
||||
{
|
||||
Read_Disk( s, (long) (2 + s->inode_maps + i) * K,
|
||||
(char *) &s->zone_map[ i * K / sizeof (bitchunk_t ) ] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************/
|
||||
/* */
|
||||
/* Search( state, string ) */
|
||||
/* */
|
||||
/* Search from the current address for the ASCII */
|
||||
/* "string" on the device. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
|
||||
off_t Search( s, string )
|
||||
de_state *s;
|
||||
char *string;
|
||||
|
||||
{
|
||||
off_t address = s->address + 1;
|
||||
off_t last_addr = address;
|
||||
char buffer[ SEARCH_BUFFER ];
|
||||
int offset;
|
||||
int tail_length = strlen( string ) - 1;
|
||||
int count = SEARCH_BUFFER;
|
||||
int last_offset;
|
||||
|
||||
|
||||
for ( ; count == SEARCH_BUFFER; address += SEARCH_BUFFER - tail_length )
|
||||
{
|
||||
if ( lseek( s->device_d, address, SEEK_SET ) == -1 )
|
||||
Error( "Error seeking %s", s->device_name );
|
||||
|
||||
if ( (count = read( s->device_d, buffer, SEARCH_BUFFER)) == -1 )
|
||||
Error( "Error reading %s", s->device_name );
|
||||
|
||||
|
||||
if ( address - last_addr >= 500L * K )
|
||||
{
|
||||
putchar( '.' );
|
||||
fflush( stdout );
|
||||
|
||||
last_addr += 500L * K;
|
||||
}
|
||||
|
||||
|
||||
last_offset = count - tail_length;
|
||||
|
||||
for ( offset = 0; offset < last_offset; ++offset )
|
||||
{
|
||||
register char c = buffer[ offset ];
|
||||
|
||||
if ( c == *string )
|
||||
{
|
||||
char *tail_buffer = &buffer[ offset + 1 ];
|
||||
char *tail_string = string + 1;
|
||||
|
||||
do
|
||||
{
|
||||
if ( *tail_string == '\0' )
|
||||
return( address + offset );
|
||||
}
|
||||
while ( *tail_buffer++ == *tail_string++ );
|
||||
}
|
||||
} /* end for ( offset ) */
|
||||
} /* end for ( address ) */
|
||||
|
||||
return( -1L );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************/
|
||||
/* */
|
||||
/* Write_Word( state, word ) */
|
||||
/* */
|
||||
/* Write a word at address. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
|
||||
void Write_Word( s, word )
|
||||
de_state *s;
|
||||
word_t word;
|
||||
|
||||
{
|
||||
if ( s->address & 01 )
|
||||
Error( "Internal fault (unaligned address)" );
|
||||
|
||||
if ( lseek( s->device_d, s->address, SEEK_SET ) == -1 )
|
||||
Error( "Error seeking %s", s->device_name );
|
||||
|
||||
if ( write( s->device_d, (char *) &word, sizeof word ) != sizeof word )
|
||||
Error( "Error writing %s", s->device_name );
|
||||
}
|
|
@ -1,612 +0,0 @@
|
|||
/****************************************************************/
|
||||
/* */
|
||||
/* de_recover.c */
|
||||
/* */
|
||||
/* File restoration routines. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
/* origination 1989-Jan-21 Terrence W. Holm */
|
||||
/* handle "holes" 1989-Jan-28 Terrence W. Holm */
|
||||
/****************************************************************/
|
||||
|
||||
|
||||
#include <minix/config.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/dir.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <pwd.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include <minix/const.h>
|
||||
#include <minix/type.h>
|
||||
#include "mfs/const.h"
|
||||
#include "mfs/type.h"
|
||||
#include "mfs/inode.h"
|
||||
#include <minix/fslib.h>
|
||||
|
||||
#include "de.h"
|
||||
|
||||
_PROTOTYPE(int Indirect, (de_state *s, zone_t block, off_t *size, int dblind));
|
||||
_PROTOTYPE(int Data_Block, (de_state *s, zone_t block, off_t *file_size ));
|
||||
_PROTOTYPE(int Free_Block, (de_state *s, zone_t block ));
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************/
|
||||
/* */
|
||||
/* Path_Dir_File( path_name, dir_name, file_name ) */
|
||||
/* */
|
||||
/* Split "path_name" into a directory name and */
|
||||
/* a file name. */
|
||||
/* */
|
||||
/* Zero is returned on error conditions. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
|
||||
int Path_Dir_File( path_name, dir_name, file_name )
|
||||
char *path_name;
|
||||
char **dir_name;
|
||||
char **file_name;
|
||||
|
||||
{
|
||||
char *p;
|
||||
static char directory[ MAX_STRING + 1 ];
|
||||
static char filename[ MAX_STRING + 1 ];
|
||||
|
||||
|
||||
if ( (p = strrchr( path_name, '/' )) == NULL )
|
||||
{
|
||||
strcpy( directory, "." );
|
||||
strcpy( filename, path_name );
|
||||
}
|
||||
else
|
||||
{
|
||||
*directory = '\0';
|
||||
strncat( directory, path_name, p - path_name );
|
||||
strcpy( filename, p + 1 );
|
||||
}
|
||||
|
||||
if ( *directory == '\0' )
|
||||
strcpy( directory, "/" );
|
||||
|
||||
if ( *filename == '\0' )
|
||||
{
|
||||
Warning( "A file name must follow the directory name" );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
*dir_name = directory;
|
||||
*file_name = filename;
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************/
|
||||
/* */
|
||||
/* File_Device( file_name ) */
|
||||
/* */
|
||||
/* Return the name of the file system device */
|
||||
/* containing the file "file_name". */
|
||||
/* */
|
||||
/* This is used if the "-r" option was specified. */
|
||||
/* In this case we have only been given a file */
|
||||
/* name, and must determine which file system */
|
||||
/* device to open. */
|
||||
/* */
|
||||
/* NULL is returned on error conditions. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
|
||||
|
||||
char *File_Device( file_name )
|
||||
char *file_name;
|
||||
|
||||
{
|
||||
struct stat file_stat;
|
||||
struct stat device_stat;
|
||||
int dev_d;
|
||||
struct direct entry;
|
||||
static char device_name[ NAME_MAX + 1 ];
|
||||
|
||||
|
||||
if ( access( file_name, R_OK ) != 0 )
|
||||
{
|
||||
Warning( "Can not find %s", file_name );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
|
||||
if ( stat( file_name, &file_stat ) == -1 )
|
||||
{
|
||||
Warning( "Can not stat(2) %s", file_name );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
|
||||
/* Open /dev for reading */
|
||||
|
||||
if ( (dev_d = open( DEV, O_RDONLY )) == -1 )
|
||||
{
|
||||
Warning( "Can not read %s", DEV );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
|
||||
while ( read( dev_d, (char *) &entry, sizeof(struct direct) )
|
||||
== sizeof(struct direct) )
|
||||
{
|
||||
if ( entry.d_ino == 0 )
|
||||
continue;
|
||||
|
||||
strcpy( device_name, DEV );
|
||||
strcat( device_name, "/" );
|
||||
strncat( device_name, entry.d_name, NAME_MAX );
|
||||
|
||||
if ( stat( device_name, &device_stat ) == -1 )
|
||||
continue;
|
||||
|
||||
if ( (device_stat.st_mode & S_IFMT) != S_IFBLK )
|
||||
continue;
|
||||
|
||||
if ( file_stat.st_dev == device_stat.st_rdev )
|
||||
{
|
||||
close( dev_d );
|
||||
return( device_name );
|
||||
}
|
||||
}
|
||||
|
||||
close( dev_d );
|
||||
|
||||
Warning( "The device containing file %s is not in %s", file_name, DEV );
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************/
|
||||
/* */
|
||||
/* Find_Deleted_Entry( state, path_name ) */
|
||||
/* */
|
||||
/* Split "path_name" into a directory name and */
|
||||
/* a file name. Then search the directory for */
|
||||
/* an entry that would match the deleted file */
|
||||
/* name. (Deleted entries have a zero i-node */
|
||||
/* number, but the original i-node number is */
|
||||
/* placed at the end of the file name.) */
|
||||
/* */
|
||||
/* If successful an i-node number is returned, */
|
||||
/* else zero is returned. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
|
||||
ino_t Find_Deleted_Entry( s, path_name )
|
||||
de_state *s;
|
||||
char *path_name;
|
||||
|
||||
{
|
||||
char *dir_name;
|
||||
char *file_name;
|
||||
|
||||
|
||||
/* Check if the file exists */
|
||||
|
||||
if ( access( path_name, F_OK ) == 0 )
|
||||
{
|
||||
Warning( "File has not been deleted" );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
/* Split the path name into a directory and a file name */
|
||||
|
||||
if ( ! Path_Dir_File( path_name, &dir_name, &file_name ) )
|
||||
return( 0 );
|
||||
|
||||
|
||||
/* Check to make sure the user has read permission on */
|
||||
/* the directory. */
|
||||
|
||||
if ( access( dir_name, R_OK ) != 0 )
|
||||
{
|
||||
Warning( "Can not find %s", dir_name );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
/* Make sure "dir_name" is really a directory. */
|
||||
{
|
||||
struct stat dir_stat;
|
||||
|
||||
if ( stat( dir_name, &dir_stat ) == -1 ||
|
||||
(dir_stat.st_mode & S_IFMT) != S_IFDIR )
|
||||
{
|
||||
Warning( "Can not find directory %s", dir_name );
|
||||
return( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Make sure the directory is on the current */
|
||||
/* file system device. */
|
||||
|
||||
if ( Find_Inode( s, dir_name ) == 0 )
|
||||
return( 0 );
|
||||
|
||||
|
||||
/* Open the directory and search for the lost file name. */
|
||||
{
|
||||
int dir_d;
|
||||
int count;
|
||||
struct direct entry;
|
||||
|
||||
if ( (dir_d = open( dir_name, O_RDONLY )) == -1 )
|
||||
{
|
||||
Warning( "Can not read directory %s", dir_name );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
while ( (count = read( dir_d, (char *) &entry, sizeof(struct direct) ))
|
||||
== sizeof(struct direct) )
|
||||
{
|
||||
if ( entry.d_ino == 0 &&
|
||||
strncmp( file_name, entry.d_name, NAME_MAX - sizeof(ino_t) ) == 0 )
|
||||
{
|
||||
ino_t inode = *( (ino_t *) &entry.d_name[ NAME_MAX - sizeof(ino_t) ] );
|
||||
|
||||
close( dir_d );
|
||||
|
||||
if ( inode < 1 || inode > s->inodes )
|
||||
{
|
||||
Warning( "Illegal i-node number" );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
return( inode );
|
||||
}
|
||||
}
|
||||
|
||||
close( dir_d );
|
||||
|
||||
if ( count == 0 )
|
||||
Warning( "Can not find a deleted entry for %s", file_name );
|
||||
else
|
||||
Warning( "Problem reading directory %s", dir_name );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************/
|
||||
/* */
|
||||
/* Recover_Blocks( state ) */
|
||||
/* */
|
||||
/* Try to recover all the blocks for the i-node */
|
||||
/* currently pointed to by "s->address". The */
|
||||
/* i-node and all of the blocks must be marked */
|
||||
/* as FREE in the bit maps. The owner of the */
|
||||
/* i-node must match the current real user name. */
|
||||
/* */
|
||||
/* "Holes" in the original file are maintained. */
|
||||
/* This allows moving sparse files from one device */
|
||||
/* to another. */
|
||||
/* */
|
||||
/* On any error -1L is returned, otherwise the */
|
||||
/* size of the recovered file is returned. */
|
||||
/* */
|
||||
/* */
|
||||
/* NOTE: Once a user has read access to a device, */
|
||||
/* there is a security hole, as we lose the */
|
||||
/* normal file system protection. For convenience, */
|
||||
/* de(1) is sometimes set-uid root, this allows */
|
||||
/* anyone to use the "-r" option. When recovering, */
|
||||
/* Recover_Blocks() can only superficially check */
|
||||
/* the validity of a request. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
|
||||
off_t Recover_Blocks( s )
|
||||
de_state *s;
|
||||
|
||||
{
|
||||
struct inode core_inode;
|
||||
d1_inode *dip1;
|
||||
d2_inode *dip2;
|
||||
struct inode *inode = &core_inode;
|
||||
bit_t node = (s->address - (s->first_data - s->inode_blocks) * K) /
|
||||
s->inode_size + 1;
|
||||
|
||||
dip1 = (d1_inode *) &s->buffer[ s->offset & ~ PAGE_MASK ];
|
||||
dip2 = (d2_inode *) &s->buffer[ s->offset & ~ PAGE_MASK
|
||||
& ~ (V2_INODE_SIZE-1) ];
|
||||
conv_inode( inode, dip1, dip2, READING, s->magic );
|
||||
|
||||
if ( s->block < s->first_data - s->inode_blocks ||
|
||||
s->block >= s->first_data )
|
||||
{
|
||||
Warning( "Not in an inode block" );
|
||||
return( -1L );
|
||||
}
|
||||
|
||||
|
||||
/* Is this a valid, but free i-node? */
|
||||
|
||||
if ( node > s->inodes )
|
||||
{
|
||||
Warning( "Not an inode" );
|
||||
return( -1L );
|
||||
}
|
||||
|
||||
if ( In_Use(node, s->inode_map) )
|
||||
{
|
||||
Warning( "I-node is in use" );
|
||||
return( -1L );
|
||||
}
|
||||
|
||||
|
||||
/* Only recover files that belonged to the real user. */
|
||||
|
||||
{
|
||||
uid_t real_uid = getuid();
|
||||
struct passwd *user = getpwuid( real_uid );
|
||||
|
||||
if ( real_uid != SU_UID && real_uid != inode->i_uid )
|
||||
{
|
||||
Warning( "I-node did not belong to user %s", user ? user->pw_name : "" );
|
||||
return( -1L );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Recover all the blocks of the file. */
|
||||
|
||||
{
|
||||
off_t file_size = inode->i_size;
|
||||
int i;
|
||||
|
||||
|
||||
/* Up to s->ndzones pointers are stored in the i-node. */
|
||||
|
||||
for ( i = 0; i < s->ndzones; ++i )
|
||||
{
|
||||
if ( file_size == 0 )
|
||||
return( inode->i_size );
|
||||
|
||||
if ( ! Data_Block( s, inode->i_zone[ i ], &file_size ) )
|
||||
return( -1L );
|
||||
}
|
||||
|
||||
if ( file_size == 0 )
|
||||
return( inode->i_size );
|
||||
|
||||
|
||||
/* An indirect block can contain up to inode->i_indirects more blk ptrs. */
|
||||
|
||||
if ( ! Indirect( s, inode->i_zone[ s->ndzones ], &file_size, 0 ) )
|
||||
return( -1L );
|
||||
|
||||
if ( file_size == 0 )
|
||||
return( inode->i_size );
|
||||
|
||||
|
||||
/* A double indirect block can contain up to inode->i_indirects blk ptrs. */
|
||||
|
||||
if ( ! Indirect( s, inode->i_zone[ s->ndzones+1 ], &file_size, 1 ) )
|
||||
return( -1L );
|
||||
|
||||
if ( file_size == 0 )
|
||||
return( inode->i_size );
|
||||
|
||||
Error( "Internal fault (file_size != 0)" );
|
||||
}
|
||||
|
||||
/* NOTREACHED */
|
||||
return( -1L );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Indirect( state, block, &file_size, double )
|
||||
*
|
||||
* Recover all the blocks pointed to by the indirect block
|
||||
* "block", up to "file_size" bytes. If "double" is true,
|
||||
* then "block" is a double-indirect block pointing to
|
||||
* V*_INDIRECTS indirect blocks.
|
||||
*
|
||||
* If a "hole" is encountered, then just seek ahead in the
|
||||
* output file.
|
||||
*/
|
||||
|
||||
|
||||
int Indirect( s, block, file_size, dblind )
|
||||
de_state *s;
|
||||
zone_t block;
|
||||
off_t *file_size;
|
||||
int dblind;
|
||||
|
||||
{
|
||||
union
|
||||
{
|
||||
zone1_t ind1[ V1_INDIRECTS ];
|
||||
zone_t ind2[ V2_INDIRECTS(_MAX_BLOCK_SIZE) ];
|
||||
} indirect;
|
||||
int i;
|
||||
zone_t zone;
|
||||
|
||||
/* Check for a "hole". */
|
||||
|
||||
if ( block == NO_ZONE )
|
||||
{
|
||||
off_t skip = (off_t) s->nr_indirects * K;
|
||||
|
||||
if ( *file_size < skip || dblind )
|
||||
{
|
||||
Warning( "File has a hole at the end" );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
if ( fseek( s->file_f, skip, SEEK_CUR ) == -1 )
|
||||
{
|
||||
Warning( "Problem seeking %s", s->file_name );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
*file_size -= skip;
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
|
||||
/* Not a "hole". Recover indirect block, if not in use. */
|
||||
|
||||
if ( ! Free_Block( s, block ) )
|
||||
return( 0 );
|
||||
|
||||
|
||||
Read_Disk( s, (long) block << K_SHIFT, (char *) &indirect );
|
||||
|
||||
for ( i = 0; i < s->nr_indirects; ++i )
|
||||
{
|
||||
if ( *file_size == 0 )
|
||||
return( 1 );
|
||||
|
||||
zone = (s->v1 ? indirect.ind1[ i ] : indirect.ind2[ i ]);
|
||||
if ( dblind )
|
||||
{
|
||||
if ( ! Indirect( s, zone, file_size, 0 ) )
|
||||
return( 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ! Data_Block( s, zone, file_size ) )
|
||||
return( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Data_Block( state, block, &file_size )
|
||||
*
|
||||
* If "block" is free then write Min(file_size, k)
|
||||
* bytes from it onto the current output file.
|
||||
*
|
||||
* If "block" is zero, this means that a 1k "hole"
|
||||
* is in the file. The recovered file maintains
|
||||
* the reduced size by not allocating the block.
|
||||
*
|
||||
* The file size is decremented accordingly.
|
||||
*/
|
||||
|
||||
|
||||
int Data_Block( s, block, file_size )
|
||||
de_state *s;
|
||||
zone_t block;
|
||||
off_t *file_size;
|
||||
|
||||
{
|
||||
char buffer[ K ];
|
||||
off_t block_size = *file_size > K ? K : *file_size;
|
||||
|
||||
|
||||
/* Check for a "hole". */
|
||||
|
||||
if ( block == NO_ZONE )
|
||||
{
|
||||
if ( block_size < K )
|
||||
{
|
||||
Warning( "File has a hole at the end" );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
if ( fseek( s->file_f, block_size, SEEK_CUR ) == -1 )
|
||||
{
|
||||
Warning( "Problem seeking %s", s->file_name );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
*file_size -= block_size;
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
|
||||
/* Block is not a "hole". Copy it to output file, if not in use. */
|
||||
|
||||
if ( ! Free_Block( s, block ) )
|
||||
return( 0 );
|
||||
|
||||
Read_Disk( s, (long) block << K_SHIFT, buffer );
|
||||
|
||||
|
||||
if ( fwrite( buffer, 1, (size_t) block_size, s->file_f )
|
||||
!= (size_t) block_size )
|
||||
{
|
||||
Warning( "Problem writing %s", s->file_name );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
*file_size -= block_size;
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Free_Block( state, block )
|
||||
*
|
||||
* Make sure "block" is a valid data block number, and it
|
||||
* has not been allocated to another file.
|
||||
*/
|
||||
|
||||
|
||||
int Free_Block( s, block )
|
||||
de_state *s;
|
||||
zone_t block;
|
||||
|
||||
{
|
||||
if ( block < s->first_data || block >= s->zones )
|
||||
{
|
||||
Warning( "Illegal block number" );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
if ( In_Use( (bit_t) (block - (s->first_data - 1)), s->zone_map ) )
|
||||
{
|
||||
Warning( "Encountered an \"in use\" data block" );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
|
@ -1,298 +0,0 @@
|
|||
/****************************************************************/
|
||||
/* */
|
||||
/* de_stdin.c */
|
||||
/* */
|
||||
/* Processing input from the "de" user. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
/* origination 1989-Jan-15 Terrence W. Holm */
|
||||
/****************************************************************/
|
||||
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <termios.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <minix/config.h>
|
||||
#include <minix/const.h>
|
||||
#include "mfs/const.h"
|
||||
#include "mfs/inode.h"
|
||||
|
||||
#include "de.h"
|
||||
|
||||
FORWARD _PROTOTYPE(int Timed_Get_Char , (int time ));
|
||||
FORWARD _PROTOTYPE(void Timed_Out , (int sig));
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************/
|
||||
/* */
|
||||
/* Save_Term() */
|
||||
/* */
|
||||
/* Save the current terminal characteristics. */
|
||||
/* */
|
||||
/* */
|
||||
/* Set_Term() */
|
||||
/* */
|
||||
/* Set up the terminal characteristics. */
|
||||
/* */
|
||||
/* */
|
||||
/* Reset_Term() */
|
||||
/* */
|
||||
/* Restore the terminal characteristics. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
|
||||
static struct termios saved_term;
|
||||
|
||||
|
||||
void Save_Term()
|
||||
|
||||
{
|
||||
tcgetattr( 0, &saved_term );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Set_Term()
|
||||
|
||||
{
|
||||
struct termios term;
|
||||
|
||||
term = saved_term;
|
||||
|
||||
|
||||
/* No tab expansion, no echo, don't map ^M to ^J, cbreak mode */
|
||||
|
||||
term.c_iflag &= ~ICRNL;
|
||||
term.c_oflag &= ~OPOST;
|
||||
term.c_lflag &= ~ICANON & ~ECHO;
|
||||
|
||||
|
||||
/* Change the interrupt character to ^C */
|
||||
|
||||
term.c_cc[VINTR] = '\003';
|
||||
|
||||
tcsetattr( 0, TCSANOW, &term );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Reset_Term()
|
||||
|
||||
{
|
||||
tcsetattr( 0, TCSANOW, &saved_term );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************/
|
||||
/* */
|
||||
/* Get_Char() */
|
||||
/* */
|
||||
/* Return the next input character. Escape */
|
||||
/* sequences are mapped to special codes. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
|
||||
int Get_Char()
|
||||
{
|
||||
int c;
|
||||
static int unget_char = EOF;
|
||||
|
||||
|
||||
/* Flush the output to the screen before waiting */
|
||||
/* for input from the user. */
|
||||
|
||||
fflush( stdout );
|
||||
|
||||
if ( unget_char == EOF )
|
||||
{
|
||||
while ( (c = Timed_Get_Char( 60 * 60 )) < EOF )
|
||||
printf( "%c", BELL );
|
||||
}
|
||||
else
|
||||
{
|
||||
c = unget_char;
|
||||
unget_char = EOF;
|
||||
}
|
||||
|
||||
if ( c == EOF )
|
||||
return( EOF );
|
||||
|
||||
if ( c != ESCAPE )
|
||||
return( c );
|
||||
|
||||
if ( (c = Timed_Get_Char( 1 )) <= EOF )
|
||||
return( ESCAPE );
|
||||
|
||||
if ( c != '[' )
|
||||
{
|
||||
unget_char = c;
|
||||
return( ESCAPE );
|
||||
}
|
||||
|
||||
if ( (c = Timed_Get_Char( 1 )) <= EOF )
|
||||
{
|
||||
unget_char = '[';
|
||||
return( ESCAPE );
|
||||
}
|
||||
|
||||
return( c | 0x80 ); /* Flag ESC [ x */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int Timed_Get_Char( time )
|
||||
int time;
|
||||
|
||||
{
|
||||
char c;
|
||||
int count;
|
||||
|
||||
signal( SIGALRM, Timed_Out );
|
||||
|
||||
alarm( time );
|
||||
count = read( 0, &c, 1 );
|
||||
alarm( 0 );
|
||||
|
||||
if ( count <= 0 )
|
||||
return( EOF + count );
|
||||
|
||||
return( c & 0x7f );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************/
|
||||
/* */
|
||||
/* Get_Line() */
|
||||
/* */
|
||||
/* Read a line from the user. Returns a pointer */
|
||||
/* to a local buffer, or NULL if DEL or a non- */
|
||||
/* ASCII character was typed. Processes ^H and */
|
||||
/* ^U. ^M terminates the input. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
|
||||
char *Get_Line()
|
||||
|
||||
{
|
||||
int c;
|
||||
int i;
|
||||
static char line[ MAX_STRING + 1 ];
|
||||
|
||||
for ( i = 0; i <= MAX_STRING; ++i )
|
||||
{
|
||||
c = Get_Char();
|
||||
|
||||
if ( c == EOF || c == DEL || (c & 0x80) )
|
||||
return( NULL );
|
||||
|
||||
if ( c == BS )
|
||||
{
|
||||
if ( --i >= 0 )
|
||||
{
|
||||
printf( "\b \b" );
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
else if ( c == CTRL_U )
|
||||
{
|
||||
for ( --i; i >= 0; --i )
|
||||
printf( "\b \b" );
|
||||
}
|
||||
|
||||
else if ( c == '\r' )
|
||||
{
|
||||
line[ i ] = '\0';
|
||||
return( line );
|
||||
}
|
||||
|
||||
else if ( i < MAX_STRING )
|
||||
{
|
||||
line[ i ] = c;
|
||||
Print_Ascii( c );
|
||||
}
|
||||
|
||||
else /* Line buffer is full, don't add any more to it. */
|
||||
{
|
||||
putchar( BELL );
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
Error( "Internal fault (line buffer overflow)" );
|
||||
|
||||
/* NOTREACHED */
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************/
|
||||
/* */
|
||||
/* Arrow_Esc( char ) */
|
||||
/* */
|
||||
/* If the keyboard does not generate Ansi escape */
|
||||
/* codes for the arrow keys, but does generate */
|
||||
/* single byte control codes, then map these */
|
||||
/* codes to the special characters we are using */
|
||||
/* to denote the Ansi escape codes. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
|
||||
extern char Kup; /* (ku) - Up arrow key */
|
||||
extern char Kdown; /* (kd) - Down arrow key */
|
||||
extern char Kleft; /* (kl) - Left arrow key */
|
||||
extern char Kright; /* (kr) - Right arrow key */
|
||||
|
||||
|
||||
int Arrow_Esc( c )
|
||||
int c;
|
||||
|
||||
{
|
||||
if ( c == Kup )
|
||||
return( ESC_UP );
|
||||
|
||||
if ( c == Kdown )
|
||||
return( ESC_DOWN );
|
||||
|
||||
if ( c == Kleft )
|
||||
return( ESC_LEFT );
|
||||
|
||||
if ( c == Kright )
|
||||
return( ESC_RIGHT );
|
||||
|
||||
return( c );
|
||||
}
|
||||
|
||||
void Timed_Out(sig)
|
||||
int sig;
|
||||
{}
|
||||
|
||||
/*
|
||||
* $PchHeader: /mount/hd2/minix/sys/cmd/de/RCS/de_stdin.c,v 1.3 1995/02/10 08:01:30 philip Exp $
|
||||
*/
|
File diff suppressed because it is too large
Load diff
|
@ -4,7 +4,6 @@
|
|||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/dir.h>
|
||||
#include <sys/stat.h>
|
||||
#include <machine/partition.h>
|
||||
#include <minix/partition.h>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#define bit_nr bit_t
|
||||
#define block_nr block_t
|
||||
#define d_inode d2_inode
|
||||
#define d_inum d_ino
|
||||
#define d_inum mfs_d_ino
|
||||
#define dir_struct struct direct
|
||||
#define i_mode d2_mode
|
||||
#define i_nlinks d2_nlinks
|
||||
|
@ -36,7 +36,6 @@
|
|||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/dir.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
@ -51,6 +50,7 @@
|
|||
#include "mfs/const.h"
|
||||
#include "mfs/inode.h"
|
||||
#include "mfs/type.h"
|
||||
#include "mfs/mfsdir.h"
|
||||
#include <minix/fslib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
|
@ -327,7 +327,7 @@ unsigned nelem, elsize;
|
|||
void printname(s)
|
||||
char *s;
|
||||
{
|
||||
register n = NAME_MAX;
|
||||
register n = MFS_NAME_MAX;
|
||||
int c;
|
||||
|
||||
do {
|
||||
|
@ -346,7 +346,7 @@ void printrec(struct stack *sp)
|
|||
if (sp->st_next != 0) {
|
||||
printrec(sp->st_next);
|
||||
putchar('/');
|
||||
printname(sp->st_dir->d_name);
|
||||
printname(sp->st_dir->mfs_d_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -991,10 +991,10 @@ register int n;
|
|||
/* See if the `.' or `..' entry is as expected. */
|
||||
int chkdots(ino_t ino, off_t pos, dir_struct *dp, ino_t exp)
|
||||
{
|
||||
char printable_name[4 * NAME_MAX + 1];
|
||||
char printable_name[4 * MFS_NAME_MAX + 1];
|
||||
|
||||
if (dp->d_inum != exp) {
|
||||
make_printable_name(printable_name, dp->d_name, sizeof(dp->d_name));
|
||||
make_printable_name(printable_name, dp->mfs_d_name, sizeof(dp->mfs_d_name));
|
||||
printf("bad %s in ", printable_name);
|
||||
printpath(1, 0);
|
||||
printf("%s is linked to %u ", printable_name, dp->d_inum);
|
||||
|
@ -1008,8 +1008,8 @@ int chkdots(ino_t ino, off_t pos, dir_struct *dp, ino_t exp)
|
|||
count[exp]++;
|
||||
return(0);
|
||||
}
|
||||
} else if (pos != (dp->d_name[1] ? DIR_ENTRY_SIZE : 0)) {
|
||||
make_printable_name(printable_name, dp->d_name, sizeof(dp->d_name));
|
||||
} else if (pos != (dp->mfs_d_name[1] ? DIR_ENTRY_SIZE : 0)) {
|
||||
make_printable_name(printable_name, dp->mfs_d_name, sizeof(dp->mfs_d_name));
|
||||
printf("warning: %s has offset %ld in ", printable_name, pos);
|
||||
printpath(1, 0);
|
||||
printf("%s is linked to %u)\n", printable_name, dp->d_inum);
|
||||
|
@ -1023,8 +1023,8 @@ int chkdots(ino_t ino, off_t pos, dir_struct *dp, ino_t exp)
|
|||
/* Check the name in a directory entry. */
|
||||
int chkname(ino_t ino, dir_struct *dp)
|
||||
{
|
||||
register n = NAME_MAX + 1;
|
||||
register char *p = dp->d_name;
|
||||
register n = MFS_NAME_MAX + 1;
|
||||
register char *p = dp->mfs_d_name;
|
||||
|
||||
if (*p == '\0') {
|
||||
printf("null name found in ");
|
||||
|
@ -1038,7 +1038,7 @@ int chkname(ino_t ino, dir_struct *dp)
|
|||
printpath(1, 0);
|
||||
setbit(spec_imap, (bit_nr) ino);
|
||||
printf("entry = '");
|
||||
printname(dp->d_name);
|
||||
printname(dp->mfs_d_name);
|
||||
printf("')");
|
||||
if (Remove(dp)) return(0);
|
||||
break;
|
||||
|
@ -1056,7 +1056,7 @@ int chkentry(ino_t ino, off_t pos, dir_struct *dp)
|
|||
printpath(1, 0);
|
||||
printf("ino found = %u, ", dp->d_inum);
|
||||
printf("name = '");
|
||||
printname(dp->d_name);
|
||||
printname(dp->mfs_d_name);
|
||||
printf("')");
|
||||
if (yes(". remove entry")) {
|
||||
memset((void *) dp, 0, sizeof(dir_struct));
|
||||
|
@ -1067,17 +1067,17 @@ int chkentry(ino_t ino, off_t pos, dir_struct *dp)
|
|||
if ((unsigned) count[dp->d_inum] == SHRT_MAX) {
|
||||
printf("too many links to ino %u\n", dp->d_inum);
|
||||
printf("discovered at entry '");
|
||||
printname(dp->d_name);
|
||||
printname(dp->mfs_d_name);
|
||||
printf("' in directory ");
|
||||
printpath(0, 1);
|
||||
if (Remove(dp)) return(0);
|
||||
}
|
||||
count[dp->d_inum]++;
|
||||
if (strcmp(dp->d_name, ".") == 0) {
|
||||
if (strcmp(dp->mfs_d_name, ".") == 0) {
|
||||
ftop->st_presence |= DOT;
|
||||
return(chkdots(ino, pos, dp, ino));
|
||||
}
|
||||
if (strcmp(dp->d_name, "..") == 0) {
|
||||
if (strcmp(dp->mfs_d_name, "..") == 0) {
|
||||
ftop->st_presence |= DOTDOT;
|
||||
return(chkdots(ino, pos, dp, ino == ROOT_INODE ? ino :
|
||||
ftop->st_next->st_dir->d_inum));
|
||||
|
@ -1087,7 +1087,7 @@ int chkentry(ino_t ino, off_t pos, dir_struct *dp)
|
|||
printf("link to directory discovered in ");
|
||||
printpath(1, 0);
|
||||
printf("name = '");
|
||||
printname(dp->d_name);
|
||||
printname(dp->mfs_d_name);
|
||||
printf("', dir ino = %u)", dp->d_inum);
|
||||
return !Remove(dp);
|
||||
}
|
||||
|
@ -1463,7 +1463,7 @@ void chktree()
|
|||
nfreeinode = sb.s_ninodes;
|
||||
nfreezone = N_DATA;
|
||||
dir.d_inum = ROOT_INODE;
|
||||
dir.d_name[0] = 0;
|
||||
dir.mfs_d_name[0] = 0;
|
||||
if (!descendtree(&dir)) fatal("bad root inode");
|
||||
putchar('\n');
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/dir.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
@ -26,6 +25,7 @@
|
|||
#include <minix/type.h>
|
||||
#include <minix/minlib.h>
|
||||
#include "mfs/const.h"
|
||||
#include "mfs/mfsdir.h"
|
||||
#if (MACHINE == IBM_PC)
|
||||
#include <minix/partition.h>
|
||||
#include <minix/u64.h>
|
||||
|
@ -686,11 +686,11 @@ char *name;
|
|||
for (l = 0; l < zone_size; l++) {
|
||||
get_block((z << zone_shift) + l, (char *) dir_entry);
|
||||
for (i = 0; i < NR_DIR_ENTRIES(block_size); i++) {
|
||||
if (dir_entry[i].d_ino == 0) {
|
||||
dir_entry[i].d_ino = child;
|
||||
if (dir_entry[i].mfs_d_ino == 0) {
|
||||
dir_entry[i].mfs_d_ino = child;
|
||||
p1 = name;
|
||||
p2 = dir_entry[i].d_name;
|
||||
j = sizeof(dir_entry[i].d_name);
|
||||
p2 = dir_entry[i].mfs_d_name;
|
||||
j = sizeof(dir_entry[i].mfs_d_name);
|
||||
while (j--) {
|
||||
*p2++ = *p1;
|
||||
if (*p1 != 0) p1++;
|
||||
|
@ -1189,8 +1189,8 @@ void print_fs()
|
|||
/* This is a directory */
|
||||
get_block(inode1[i].d1_zone[0], (char *) dir);
|
||||
for (j = 0; j < NR_DIR_ENTRIES(block_size); j++)
|
||||
if (dir[j].d_ino)
|
||||
printf("\tInode %2d: %s\n", dir[j].d_ino, dir[j].d_name);
|
||||
if (dir[j].mfs_d_ino)
|
||||
printf("\tInode %2d: %s\n", dir[j].mfs_d_ino, dir[j].mfs_d_name);
|
||||
}
|
||||
} else {
|
||||
if (inode2[i].d2_mode != 0) {
|
||||
|
@ -1205,8 +1205,8 @@ void print_fs()
|
|||
/* This is a directory */
|
||||
get_block(inode2[i].d2_zone[0], (char *) dir);
|
||||
for (j = 0; j < NR_DIR_ENTRIES(block_size); j++)
|
||||
if (dir[j].d_ino)
|
||||
printf("\tInode %2d: %s\n", dir[j].d_ino, dir[j].d_name);
|
||||
if (dir[j].mfs_d_ino)
|
||||
printf("\tInode %2d: %s\n", dir[j].mfs_d_ino, dir[j].mfs_d_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
PROG= readfs
|
||||
CPPFLAGS+= -I${MINIXSRCDIR}/servers
|
||||
MAN=
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -1,601 +0,0 @@
|
|||
/* readfs - read a MINIX file system Author: Paul Polderman */
|
||||
|
||||
/* Command: readfs - read and extract a MINIX filesystem.
|
||||
*
|
||||
* Syntax: readfs [-li] block-special [directory]
|
||||
*
|
||||
* Flags: -l: Extract files and dirs and produce a mkfs-listing on stdout
|
||||
* -i: Information only: give the listing, but do not extract files.
|
||||
* -d: Don't extract regular files, just the skeleton please.
|
||||
*
|
||||
* Examples: readfs /dev/fd1 # extract all files from /dev/fd1.
|
||||
* readfs -i /dev/hd2 # see what's on /dev/hd2.
|
||||
* readfs -l /dev/at0 rootfs # extract and list the filesystem
|
||||
* # of /dev/at0 and put the tree
|
||||
* # in the directory `rootfs'.
|
||||
*
|
||||
* Readfs reads a MINIX filesystem and extracts recursively all directories
|
||||
* and files, and (optionally) produces a mkfs-listing of them on stdout.
|
||||
* The root directory contents are placed in the current directory, unless
|
||||
* a directory is given as argument, in which case the contents are put there.
|
||||
* Readfs tries to restore the attributes (mode/uid/gid/time) of the files
|
||||
* extracted to those of the original files.
|
||||
* Special files are created as ordinary files, but the mkfs-listing
|
||||
* enables mkfs to restore them to original.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/dir.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <utime.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#define BLOCK_SIZE _STATIC_BLOCK_SIZE
|
||||
|
||||
#include <minix/config.h>
|
||||
#include <minix/const.h>
|
||||
#include <minix/type.h>
|
||||
#include "mfs/const.h"
|
||||
#include "mfs/type.h"
|
||||
#include "mfs/buf.h"
|
||||
#include "mfs/super.h"
|
||||
|
||||
#undef printf /* Definition used only in the kernel */
|
||||
#include <stdio.h>
|
||||
|
||||
/* Compile with -I/user0/ast/minix
|
||||
* (i.e. the directory containing the MINIX system sources)
|
||||
*
|
||||
* Author: Paul Polderman (polder@cs.vu.nl) April 1987
|
||||
*/
|
||||
|
||||
char verbose = 0; /* give a mkfs-listing of the filesystem */
|
||||
/* And extracts its contents. */
|
||||
char noaction = 0; /* just give a mkfs-listing, do not extract
|
||||
* files. */
|
||||
char nofiles = 0; /* only extract the skeleton FS structure */
|
||||
|
||||
struct super_block sb;
|
||||
char pathname[1024];
|
||||
int inodes_per_block;
|
||||
|
||||
_PROTOTYPE(int main, (int argc, char **argv));
|
||||
_PROTOTYPE(void get_flags, (char *flags));
|
||||
_PROTOTYPE(void readfs, (char *special_file, char *directory));
|
||||
_PROTOTYPE(int get_inode, (int fd, Ino_t inum, d1_inode * ip));
|
||||
_PROTOTYPE(void dump_dir, (int special, d1_inode * ip, char *directory));
|
||||
_PROTOTYPE(int dump_file, (int special, d1_inode * ip, char *filename));
|
||||
_PROTOTYPE(int get_fileblock, (int special, d1_inode * ip, block_t b, struct buf * bp));
|
||||
_PROTOTYPE(int get_block, (int fd, block_t block, struct buf * bp, int type));
|
||||
_PROTOTYPE(int get_rawblock, (int special, block_t blockno, char *bufp));
|
||||
_PROTOTYPE(void restore, (char *name, d1_inode * ip));
|
||||
_PROTOTYPE(void show_info, (char *name, d1_inode * ip, char *path));
|
||||
_PROTOTYPE(void do_indent, (int i));
|
||||
_PROTOTYPE(int Mkdir, (char *directory));
|
||||
|
||||
int main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
switch (argc) {
|
||||
case 2:
|
||||
pathname[0] = '\0';
|
||||
readfs(argv[1], pathname);
|
||||
break;
|
||||
case 3:
|
||||
if (argv[1][0] == '-') {
|
||||
get_flags(&argv[1][1]);
|
||||
pathname[0] = '\0';
|
||||
readfs(argv[2], pathname);
|
||||
} else {
|
||||
strcpy(pathname, argv[2]);
|
||||
readfs(argv[1], pathname);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (argv[1][0] == '-') {
|
||||
get_flags(&argv[1][1]);
|
||||
strcpy(pathname, argv[3]);
|
||||
readfs(argv[2], pathname);
|
||||
break;
|
||||
} /* else fall through .. */
|
||||
default:
|
||||
fprintf(stderr, "Usage: %s [-li] <special> [dirname]\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
void get_flags(flags)
|
||||
register char *flags;
|
||||
{
|
||||
while (*flags) {
|
||||
switch (*flags) {
|
||||
case 'L':
|
||||
case 'l': verbose = 1; break;
|
||||
case 'I':
|
||||
case 'i':
|
||||
noaction = 1;
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'D':
|
||||
case 'd': nofiles = 1; break;
|
||||
default:
|
||||
fprintf(stderr, "Bad flag: %c\n", *flags);
|
||||
break;
|
||||
}
|
||||
flags++;
|
||||
}
|
||||
}
|
||||
|
||||
#define zone_shift (sb.s_log_zone_size) /* zone to block ratio */
|
||||
|
||||
void readfs(special_file, directory)
|
||||
char *special_file, *directory;
|
||||
/* Readfs: opens the given special file (with MINIX filesystem),
|
||||
* and extracts its contents into the given directory.
|
||||
*/
|
||||
{
|
||||
d1_inode root_inode;
|
||||
int special, magic;
|
||||
off_t super_b;
|
||||
|
||||
umask(0);
|
||||
|
||||
/* Open the special file */
|
||||
if ((special = open(special_file, O_RDONLY)) < 0) {
|
||||
fprintf(stderr, "cannot open %s\n", special_file);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read the superblock */
|
||||
super_b = (off_t) 1 *(off_t) BLOCK_SIZE;
|
||||
if (lseek(special, super_b, SEEK_SET) != super_b) {
|
||||
fprintf(stderr, "cannot seek to superblock\n");
|
||||
return;
|
||||
}
|
||||
if (read(special, (char *) &sb, sizeof(struct super_block))
|
||||
!= sizeof(struct super_block)) {
|
||||
fprintf(stderr, "cannot read superblock\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* The number of inodes in a block differs in V1 and V2. */
|
||||
magic = sb.s_magic;
|
||||
if (magic == SUPER_MAGIC || magic == SUPER_REV) {
|
||||
inodes_per_block = V1_INODES_PER_BLOCK;
|
||||
} else {
|
||||
inodes_per_block = V2_INODES_PER_BLOCK(BLOCK_SIZE);
|
||||
}
|
||||
|
||||
/* Is it really a MINIX filesystem ? */
|
||||
if (magic != SUPER_MAGIC && magic != SUPER_V2) {
|
||||
fprintf(stderr, "%s is not a valid MINIX filesystem\n", special_file);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fetch the inode of the root directory */
|
||||
if (get_inode(special, (ino_t) ROOT_INODE, &root_inode) < 0) {
|
||||
fprintf(stderr, "cannot get inode of root directory\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Print number of blocks and inodes */
|
||||
if (verbose) printf("boot\n%ld %d\n",
|
||||
(block_t) sb.s_nzones << zone_shift, sb.s_ninodes);
|
||||
|
||||
/* Extract (recursively) the root directory */
|
||||
dump_dir(special, &root_inode, directory);
|
||||
}
|
||||
|
||||
/* Different type of blocks: (used in routine get_block for caching) */
|
||||
|
||||
#define B_INODE 0 /* Cache #0 is the inode cache */
|
||||
#define B_INDIRECT 1 /* Cache #1 is the (dbl) indirect block cache */
|
||||
#define B_DATA 2 /* No cache for data blocks (only read once) */
|
||||
|
||||
int get_inode(fd, inum, ip)
|
||||
int fd;
|
||||
ino_t inum;
|
||||
d1_inode *ip;
|
||||
|
||||
/* Get inode `inum' from the MINIX filesystem. (Uses the inode-cache) */
|
||||
{
|
||||
struct buf bp;
|
||||
block_t block;
|
||||
block_t ino_block;
|
||||
unsigned short ino_offset;
|
||||
|
||||
/* Calculate start of i-list */
|
||||
block = 1 + 1 + sb.s_imap_blocks + sb.s_zmap_blocks;
|
||||
|
||||
/* Calculate block with inode inum */
|
||||
ino_block = ((inum - 1) / inodes_per_block);
|
||||
ino_offset = ((inum - 1) % inodes_per_block);
|
||||
block += ino_block;
|
||||
|
||||
/* Fetch the block */
|
||||
if (get_block(fd, block, &bp, B_INODE) == 0) {
|
||||
memcpy((void *) ip, (void *) &bp.b_v1_ino[ino_offset], sizeof(d1_inode));
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Oeps, foutje .. */
|
||||
fprintf(stderr, "cannot find inode %d\n", inum);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
static int indent = 0; /* current indent (used for mkfs-listing) */
|
||||
|
||||
void dump_dir(special, ip, directory)
|
||||
int special;
|
||||
d1_inode *ip;
|
||||
char *directory;
|
||||
/* Make the given directory (if non-NULL),
|
||||
* and recursively extract its contents.
|
||||
*/
|
||||
{
|
||||
register struct direct *dp;
|
||||
register int n_entries;
|
||||
register char *name;
|
||||
block_t b = 0;
|
||||
d1_inode dip;
|
||||
struct buf bp;
|
||||
|
||||
if (verbose) {
|
||||
show_info(directory, ip, "");
|
||||
indent++;
|
||||
}
|
||||
if (!noaction && *directory) {
|
||||
/* Try to make the directory if not already there */
|
||||
if (Mkdir(directory) != 0 || chdir(directory) < 0) {
|
||||
fprintf(stderr, "Mkdir %s failed\n", directory);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (name = directory; *name; name++) /* Find end of pathname */
|
||||
;
|
||||
*name++ = '/'; /* Add trailing slash */
|
||||
|
||||
n_entries = (int) (ip->d1_size / (off_t) sizeof(struct direct));
|
||||
while (n_entries > 0) {
|
||||
|
||||
/* Read next block of the directory */
|
||||
if (get_fileblock(special, ip, b, &bp) < 0) return;
|
||||
dp = &bp.b_dir[0];
|
||||
if (b++ == (block_t) 0) {
|
||||
dp += 2; /* Skip "." and ".." */
|
||||
n_entries -= 2;
|
||||
}
|
||||
|
||||
/* Extract the files/directories listed in the block */
|
||||
while (n_entries-- > 0 && dp < &bp.b_dir[NR_DIR_ENTRIES(BLOCK_SIZE)]) {
|
||||
if (dp->d_ino != (ino_t) 0) {
|
||||
if (get_inode(special, dp->d_ino, &dip) < 0) {
|
||||
/* Bad luck */
|
||||
dp++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Add new pathname-component to `pathname'. */
|
||||
strncpy(name, dp->d_name, (size_t) NAME_MAX);
|
||||
name[NAME_MAX] = '\0';
|
||||
|
||||
/* Call the right routine */
|
||||
if ((dip.d1_mode & I_TYPE) == I_DIRECTORY)
|
||||
dump_dir(special, &dip, name);
|
||||
else
|
||||
dump_file(special, &dip, name);
|
||||
}
|
||||
dp++; /* Next entry, please. */
|
||||
}
|
||||
}
|
||||
*--name = '\0'; /* Restore `pathname' to what it was. */
|
||||
if (!noaction && *directory) {
|
||||
chdir(".."); /* Go back up. */
|
||||
restore(directory, ip); /* Restore mode/owner/accesstime */
|
||||
}
|
||||
if (verbose) {
|
||||
do_indent(--indent); /* Let mkfs know we are done */
|
||||
printf("$\n"); /* with this directory. */
|
||||
}
|
||||
}
|
||||
|
||||
int dump_file(special, ip, filename)
|
||||
int special;
|
||||
d1_inode *ip;
|
||||
char *filename;
|
||||
/* Extract given filename from the MINIX-filesystem,
|
||||
* and store it on the local filesystem.
|
||||
*/
|
||||
{
|
||||
int file;
|
||||
block_t b = 0;
|
||||
struct buf bp;
|
||||
off_t size;
|
||||
|
||||
if (nofiles && (ip->d1_mode & I_TYPE) == I_REGULAR) return(0);
|
||||
|
||||
if (verbose) show_info(filename, ip, pathname);
|
||||
|
||||
if (noaction) return(0);
|
||||
|
||||
if (access(filename, 0) == 0) {
|
||||
/* Should not happen, but just in case .. */
|
||||
fprintf(stderr, "Will not create %s: file exists\n", filename);
|
||||
return(-1);
|
||||
}
|
||||
if ((file = creat(filename, (ip->d1_mode & ALL_MODES))) < 0) {
|
||||
fprintf(stderr, "cannot create %s\n", filename);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* Don't try to extract /dev/hd0 */
|
||||
if ((ip->d1_mode & I_TYPE) == I_REGULAR) {
|
||||
size = ip->d1_size;
|
||||
while (size > (off_t) 0) {
|
||||
/* Get next block of file */
|
||||
if (get_fileblock(special, ip, b++, &bp) < 0) {
|
||||
close(file);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* Write it to the file */
|
||||
if (size > (off_t) BLOCK_SIZE)
|
||||
write(file, bp.b_data, BLOCK_SIZE);
|
||||
else
|
||||
write(file, bp.b_data, (int) size);
|
||||
|
||||
size -= (off_t) BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
close(file);
|
||||
restore(filename, ip); /* Restore mode/owner/filetimes */
|
||||
return(0);
|
||||
}
|
||||
|
||||
int get_fileblock(special, ip, b, bp)
|
||||
int special;
|
||||
d1_inode *ip;
|
||||
block_t b;
|
||||
struct buf *bp;
|
||||
/* Read the `b'-th block from the file whose inode is `ip'. */
|
||||
{
|
||||
zone_t zone, ind_zone;
|
||||
block_t z, zone_index;
|
||||
int r;
|
||||
|
||||
/* Calculate zone in which the datablock number is contained */
|
||||
zone = (zone_t) (b >> zone_shift);
|
||||
|
||||
/* Calculate index of the block number in the zone */
|
||||
zone_index = b - ((block_t) zone << zone_shift);
|
||||
|
||||
/* Go get the zone */
|
||||
if (zone < (zone_t) V1_NR_DZONES) { /* direct block */
|
||||
zone = ip->d1_zone[(int) zone];
|
||||
z = ((block_t) zone << zone_shift) + zone_index;
|
||||
r = get_block(special, z, bp, B_DATA);
|
||||
return(r);
|
||||
}
|
||||
|
||||
/* The zone is not a direct one */
|
||||
zone -= (zone_t) V1_NR_DZONES;
|
||||
|
||||
/* Is it single indirect ? */
|
||||
if (zone < (zone_t) V1_INDIRECTS) { /* single indirect block */
|
||||
ind_zone = ip->d1_zone[V1_NR_DZONES];
|
||||
} else { /* double indirect block */
|
||||
/* Fetch the double indirect block */
|
||||
ind_zone = ip->d1_zone[V1_NR_DZONES + 1];
|
||||
z = (block_t) ind_zone << zone_shift;
|
||||
r = get_block(special, z, bp, B_INDIRECT);
|
||||
if (r < 0) return(r);
|
||||
|
||||
/* Extract the indirect zone number from it */
|
||||
zone -= (zone_t) V1_INDIRECTS;
|
||||
|
||||
/* The next line assumes a V1 file system only! */
|
||||
ind_zone = bp->b_v1_ind[(int) (zone / V1_INDIRECTS)];
|
||||
zone %= (zone_t) V1_INDIRECTS;
|
||||
}
|
||||
|
||||
/* Extract the datablock number from the indirect zone */
|
||||
z = (block_t) ind_zone << zone_shift;
|
||||
r = get_block(special, z, bp, B_INDIRECT);
|
||||
if (r < 0) return(r);
|
||||
|
||||
/* The next line assumes a V1 file system only! */
|
||||
zone = bp->b_v1_ind[(int) zone];
|
||||
|
||||
/* Calculate datablock number to be fetched */
|
||||
z = ((block_t) zone << zone_shift) + zone_index;
|
||||
r = get_block(special, z, bp, B_DATA);
|
||||
return(r);
|
||||
}
|
||||
|
||||
/* The following routines simulate a LRU block cache.
|
||||
*
|
||||
* Definition of a cache block:
|
||||
*/
|
||||
|
||||
struct cache_block {
|
||||
block_t b_block; /* block number of block */
|
||||
long b_access; /* counter value of last access */
|
||||
char b_buf[BLOCK_SIZE]; /* buffer for block */
|
||||
};
|
||||
|
||||
#define NR_CACHES 2 /* total number of caches */
|
||||
#define NR_CBLOCKS 5 /* number of blocks in a cache */
|
||||
|
||||
static struct cache_block cache[NR_CACHES][NR_CBLOCKS];
|
||||
static long counter = 0L; /* Counter used as a sense of time. */
|
||||
/* Incremented after each cache operation. */
|
||||
|
||||
int get_block(fd, block, bp, type)
|
||||
int fd;
|
||||
block_t block;
|
||||
struct buf *bp;
|
||||
int type;
|
||||
/* Get the requested block from the device with filedescriptor fd.
|
||||
* If it is in the cache, no (floppy-) disk access is needed,
|
||||
* if not, allocate a cache block and read the block into it.
|
||||
*/
|
||||
{
|
||||
register int i;
|
||||
register struct cache_block *cache_p, *cp;
|
||||
|
||||
if (block == (block_t) NO_ZONE) {
|
||||
/* Should never happen in a good filesystem. */
|
||||
fprintf(stderr, "get_block: NO_ZONE requested !\n");
|
||||
return(-1);
|
||||
}
|
||||
if (type < 0 || type >= NR_CACHES) /* No cache for this type */
|
||||
return(get_rawblock(fd, block, (char *) bp));
|
||||
|
||||
cache_p = cache[type];
|
||||
cp = (struct cache_block *) 0;
|
||||
|
||||
/* First find out if block requested is in the cache */
|
||||
for (i = 0; i < NR_CBLOCKS; i++) {
|
||||
if (cache_p[i].b_block == block) { /* found right block */
|
||||
cp = &cache_p[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cp == (struct cache_block *) 0) { /* block is not in cache */
|
||||
cp = cache_p; /* go find oldest buffer */
|
||||
for (i = 0; i < NR_CBLOCKS; i++) {
|
||||
if (cache_p[i].b_access < cp->b_access) cp = &cache_p[i];
|
||||
}
|
||||
|
||||
/* Fill the buffer with the right block */
|
||||
if (get_rawblock(fd, block, cp->b_buf) < 0) return(-1);
|
||||
}
|
||||
|
||||
/* Update/store last access counter */
|
||||
cp->b_access = ++counter;
|
||||
cp->b_block = block;
|
||||
memcpy((void *) bp, (void *) cp->b_buf, BLOCK_SIZE);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int get_rawblock(special, blockno, bufp)
|
||||
int special;
|
||||
block_t blockno;
|
||||
char *bufp;
|
||||
/* Read a block from the disk. */
|
||||
{
|
||||
off_t pos;
|
||||
|
||||
/* Calculate the position of the block on the disk */
|
||||
pos = (off_t) blockno *(off_t) BLOCK_SIZE;
|
||||
|
||||
/* Read the block from the disk */
|
||||
if (lseek(special, pos, SEEK_SET) == pos
|
||||
&& read(special, bufp, BLOCK_SIZE) == BLOCK_SIZE)
|
||||
return(0);
|
||||
|
||||
/* Should never get here .. */
|
||||
fprintf(stderr, "read block %d failed\n", blockno);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void restore(name, ip)
|
||||
char *name;
|
||||
d1_inode *ip;
|
||||
/* Restores given file's attributes.
|
||||
* `ip' contains the attributes of the file on the MINIX filesystem,
|
||||
* `name' is the filename of the extracted file on the local filesystem.
|
||||
*/
|
||||
{
|
||||
long ttime[2];
|
||||
|
||||
chown(name, ip->d1_uid, ip->d1_gid); /* Fails if not superuser */
|
||||
chmod(name, (ip->d1_mode & ALL_MODES));
|
||||
ttime[0] = ttime[1] = ip->d1_mtime;
|
||||
utime(name, (struct utimbuf *) ttime);
|
||||
}
|
||||
|
||||
/* Characters to use as prefix to `mkfs' mode field */
|
||||
|
||||
static char special_chars[] = {
|
||||
'-', /* I_REGULAR */
|
||||
'c', /* I_CHAR_SPECIAL */
|
||||
'd', /* I_DIRECTORY */
|
||||
'b' /* I_BLOCK_SPECIAL */
|
||||
};
|
||||
|
||||
void show_info(name, ip, path)
|
||||
char *name;
|
||||
d1_inode *ip;
|
||||
char *path;
|
||||
/* Show information about the given file/dir in `mkfs'-format */
|
||||
{
|
||||
char c1, c2, c3;
|
||||
|
||||
c1 = special_chars[(ip->d1_mode >> 13) & 03];
|
||||
c2 = ((ip->d1_mode & ALL_MODES & ~RWX_MODES) == I_SET_UID_BIT) ? 'u' : '-';
|
||||
c3 = ((ip->d1_mode & ALL_MODES & ~RWX_MODES) == I_SET_GID_BIT) ? 'g' : '-';
|
||||
|
||||
if (*name) {
|
||||
do_indent(indent);
|
||||
printf("%-14s ", name);
|
||||
}
|
||||
printf("%c%c%c%03o %d %d", c1, c2, c3,
|
||||
(ip->d1_mode & RWX_MODES), ip->d1_uid, ip->d1_gid);
|
||||
|
||||
switch (ip->d1_mode & I_TYPE) {
|
||||
case I_DIRECTORY:
|
||||
break;
|
||||
case I_CHAR_SPECIAL: /* Print major and minor dev numbers */
|
||||
printf(" %d %d", (ip->d1_zone[0] >> MAJOR) & 0377,
|
||||
(ip->d1_zone[0] >> MINOR) & 0377);
|
||||
break;
|
||||
case I_BLOCK_SPECIAL: /* Print major and minor dev numbers */
|
||||
printf(" %d %d", (ip->d1_zone[0] >> MAJOR) & 0377,
|
||||
(ip->d1_zone[0] >> MINOR) & 0377);
|
||||
/* Also print the number of blocks on the device */
|
||||
printf(" %ld", (ip->d1_size / (off_t) BLOCK_SIZE));
|
||||
break;
|
||||
default: /* Just print the pathname */
|
||||
printf(" %s", path);
|
||||
break;
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
#define INDENT_SIZE 4
|
||||
|
||||
void do_indent(i)
|
||||
int i;
|
||||
{
|
||||
i *= INDENT_SIZE;
|
||||
while (i-- > 0) putchar(' ');
|
||||
}
|
||||
|
||||
int Mkdir(directory)
|
||||
char *directory;
|
||||
/* Make a directory, return exit status.
|
||||
* This routine is not necessary on systems that
|
||||
* have a system call to make directories.
|
||||
*/
|
||||
{
|
||||
int pid, status;
|
||||
|
||||
if ((pid = fork()) == 0) {
|
||||
execl("/bin/Mkdir", "Mkdir", directory, (char *) 0);
|
||||
execl("/usr/bin/Mkdir", "Mkdir", directory, (char *) 0);
|
||||
exit(1);
|
||||
} else if (pid < 0)
|
||||
return(-1);
|
||||
while (wait(&status) != pid);
|
||||
return(status);
|
||||
}
|
|
@ -36,7 +36,7 @@ typedef unsigned long int u_int32_t;
|
|||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define NAMELEN (DIRSIZ+5)
|
||||
#define NAMELEN (NAME_MAX+5)
|
||||
#define ISONAMELEN 12
|
||||
#define PLATFORM_80X86 0
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ INCS+= env.h fetch.h hgfs.h lib.h libutil.h timers.h
|
|||
INCS+= minix/acpi.h minix/ansi.h minix/audio_fw.h minix/bitmap.h \
|
||||
minix/callnr.h minix/com.h minix/compiler.h minix/config.h \
|
||||
minix/const.h minix/cpufeature.h minix/crtso.h minix/debug.h \
|
||||
minix/devio.h minix/devman.h minix/dir.h minix/dmap.h \
|
||||
minix/devio.h minix/devman.h minix/dmap.h \
|
||||
minix/driver.h minix/drivers.h minix/drvlib.h minix/ds.h \
|
||||
minix/endpoint.h minix/fslib.h minix/gcov.h minix/hash.h \
|
||||
minix/ioctl.h minix/input.h minix/ipc.h minix/ipcconst.h \
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
/* The <dir.h> header gives the layout of a directory. */
|
||||
|
||||
#ifndef _DIR_H
|
||||
#define _DIR_H
|
||||
|
||||
#ifdef __NBSD_LIBC
|
||||
#include <sys/cdefs.h>
|
||||
#endif
|
||||
#include <minix/types.h>
|
||||
|
||||
#define DIRBLKSIZ 512 /* size of directory block */
|
||||
|
||||
#ifndef DIRSIZ
|
||||
#define DIRSIZ 60
|
||||
#endif
|
||||
|
||||
struct direct {
|
||||
ino_t d_ino;
|
||||
char d_name[DIRSIZ];
|
||||
#ifdef __NBSD_LIBC
|
||||
} __packed;
|
||||
#else
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* _DIR_H */
|
|
@ -53,8 +53,6 @@
|
|||
*/
|
||||
#endif
|
||||
|
||||
#include <minix/dir.h>
|
||||
|
||||
/* Minimum sizes required by the POSIX P1003.1 standard (Table 2-3). */
|
||||
#ifdef _POSIX_SOURCE /* these are only visible for POSIX */
|
||||
#define _POSIX_ARG_MAX 4096 /* exec() may have 4K worth of args */
|
||||
|
@ -62,7 +60,7 @@
|
|||
#define _POSIX_LINK_MAX 8 /* a file may have 8 links */
|
||||
#define _POSIX_MAX_CANON 255 /* size of the canonical input queue */
|
||||
#define _POSIX_MAX_INPUT 255 /* you can type 255 chars ahead */
|
||||
#define _POSIX_NAME_MAX DIRSIZ /* max. file name length */
|
||||
#define _POSIX_NAME_MAX NAME_MAX /* max. file name length */
|
||||
#define _POSIX_NGROUPS_MAX 8 /* max. number of supplemental groups */
|
||||
|
||||
/* a process may have this many files open */
|
||||
|
@ -100,7 +98,7 @@
|
|||
#endif
|
||||
#define MAX_CANON 255 /* size of the canonical input queue */
|
||||
#define MAX_INPUT 255 /* size of the type-ahead buffer */
|
||||
#define NAME_MAX DIRSIZ /* # chars in a file name */
|
||||
#define NAME_MAX 255 /* system-wide filename limit (up to fs) */
|
||||
#define PATH_MAX __MINIX_PATH_MAX /* # chars in a path name */
|
||||
#define PIPE_BUF 32768 /* # bytes in atomic write to a pipe */
|
||||
#define STREAM_MAX 20 /* must be the same as FOPEN_MAX in stdio.h */
|
||||
|
|
|
@ -15,28 +15,9 @@
|
|||
#include <minix/types.h>
|
||||
#endif
|
||||
|
||||
#include <minix/dir.h>
|
||||
|
||||
/* _fl_direct is a flexible directory entry. Actually it's a union of 8
|
||||
* characters and the 3 fields defined below.
|
||||
*/
|
||||
|
||||
/* Flexible directory entry: */
|
||||
struct _fl_direct { /* First slot in an entry */
|
||||
ino_t d_ino;
|
||||
unsigned char d_extent;
|
||||
char d_name[3]; /* two characters for the shortest name */
|
||||
};
|
||||
|
||||
/* Name of length len needs _EXTENT(len) extra slots. */
|
||||
#define _EXTENT(len) (((len) + 5) >> 3)
|
||||
|
||||
/* Version 7 directory entry: */
|
||||
struct _v7_direct {
|
||||
ino_t d_ino;
|
||||
char d_name[DIRSIZ];
|
||||
};
|
||||
|
||||
/* The block size must be at least 1024 bytes, because otherwise
|
||||
* the superblock (at 1024 bytes) overlaps with other filesystem data.
|
||||
*/
|
||||
|
@ -52,10 +33,6 @@ struct _v7_direct {
|
|||
/* This is the block size for the fixed versions of the filesystem (V1/V2) */
|
||||
#define _STATIC_BLOCK_SIZE 1024
|
||||
|
||||
#define _STATIC_FLEX_PER_BLOCK (_STATIC_BLOCK_SIZE/sizeof(struct _fl_direct))
|
||||
#define _FLEX_PER_V7 (_EXTENT(DIRSIZ) + 1)
|
||||
#define _FLEX_PER_BLOCK (_STATIC_BLOCK_SIZE/sizeof(struct _fl_direct))
|
||||
|
||||
/* Definitions for the directory(3) routines: */
|
||||
typedef struct {
|
||||
int _fd; /* Filedescriptor of open directory */
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#ifndef _MINIX_ANSI_H
|
||||
#include <minix/ansi.h>
|
||||
#endif
|
||||
#include <minix/types.h>
|
||||
|
||||
#include <sys/null.h> /* For NULL */
|
||||
|
||||
|
@ -56,8 +57,7 @@ typedef struct __iobuf {
|
|||
|
||||
#define FOPEN_MAX 20
|
||||
|
||||
#include <minix/dir.h>
|
||||
#define FILENAME_MAX DIRSIZ
|
||||
#define FILENAME_MAX NAME_MAX
|
||||
|
||||
#define TMP_MAX 999
|
||||
#define L_tmpnam (sizeof("/tmp/") + FILENAME_MAX)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
INCSDIR= /usr/include.ack/sys
|
||||
|
||||
INCS= asynchio.h dir.h file.h \
|
||||
INCS= asynchio.h file.h \
|
||||
ioctl.h ipc.h jmp_buf.h kbdio.h mman.h \
|
||||
mount.h mtio.h param.h ptrace.h queue.h resource.h \
|
||||
select.h sem.h shm.h sigcontext.h signal.h socket.h \
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
/*
|
||||
* this files resolves conflicts between the file of the host system and
|
||||
* the minix specific one. This file is included directly only on Minix
|
||||
* and it is an error to do so on any other system
|
||||
*/
|
||||
|
||||
#if !defined(_MINIX) && !defined(__minix) && !defined(__ACK__)
|
||||
#error "Including Minix specific file in program targeted for other system"
|
||||
#else
|
||||
#include <minix/dir.h>
|
||||
#endif
|
|
@ -15,7 +15,7 @@ MAN= acd.1 anm.1 ar.1 ash.1 asize.1 at.1 banner.1 basename.1 \
|
|||
mkproto.1 modem.1 mount.1 mt.1 nice.1 nm.1 nohup.1 od.1 \
|
||||
ossinfo.1 ossmix.1 ossplay.1 ossrecord.1 osstest.1 passwd.1 \
|
||||
paste.1 ping.1 playwave.1 postmort.1 pr.1 prep.1 \
|
||||
profile.1 ps.1 pwd.1 rcp.1 readall.1 readfs.1 recwave.1 \
|
||||
profile.1 ps.1 pwd.1 rcp.1 readall.1 recwave.1 \
|
||||
ref.1 remsync.1 rget.1 rlogin.1 rmdir.1 rsh.1 rz.1 \
|
||||
shar.1 acksize.1 sleep.1 sort.1 soundoff.1 soundon.1 spell.1 \
|
||||
split.1 strip.1 stty.1 su.1 sum.1 svc.1 \
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
.TH READFS 1
|
||||
.SH NAME
|
||||
readfs \- read a MINIX 3 file system
|
||||
.SH SYNOPSIS
|
||||
\fBreadfs\fR [\fB\-il\fR] \fIblock_special\fR [\fIdir\fR]\fR
|
||||
.br
|
||||
.de FL
|
||||
.TP
|
||||
\\fB\\$1\\fR
|
||||
\\$2
|
||||
..
|
||||
.de EX
|
||||
.TP 20
|
||||
\\fB\\$1\\fR
|
||||
# \\$2
|
||||
..
|
||||
.SH OPTIONS
|
||||
.FL "\-i" "Give information about the file, but do not extract files"
|
||||
.FL "\-l" "List the files extracted on standard output"
|
||||
.SH EXAMPLES
|
||||
.EX "readfs \-l /dev/fd0" "List contents of diskette"
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
\fIReadfs\fR reads a diskette containing a
|
||||
\s-1MINIX 3\s-1
|
||||
file system. It can
|
||||
extract all the files from it, give a listing of them, or both. The files
|
||||
extracted can be put in a user-specified directory (default: current
|
||||
directory). If subdirectories are needed, they will be created automatically.
|
||||
.SH "SEE ALSO"
|
||||
.BR mkproto (1).
|
|
@ -1,4 +1,4 @@
|
|||
MAN= as.1x awk.1x de.1x dis88.1x elle.1x elvis.1x kermit.1x \
|
||||
MAN= as.1x awk.1x dis88.1x elle.1x elvis.1x kermit.1x \
|
||||
macros.1x mined.1x
|
||||
|
||||
.include <bsd.man.mk>
|
||||
|
|
313
man/man1x/de.1x
313
man/man1x/de.1x
|
@ -1,313 +0,0 @@
|
|||
.so mnx.mac
|
||||
.TH DE 1x
|
||||
.CD "de \(en disk editor"
|
||||
.SX "de\fR [\fB\(enw\fR] \fIblock_device"
|
||||
.SX "de \(enr \fIfile
|
||||
.FL "\(enr" "Recover a file that has been removed"
|
||||
.FL "\(enw" "Enable writing, so device can be modified"
|
||||
.EX "de \(enr /usr/ast/prog.c" "Undo the effects of: \fIrm /usr/ast/prog.c\fR"
|
||||
.EX "de \(enw /dev/fd0" "Edit \fI/dev/fd0\fR for writing"
|
||||
.PP
|
||||
The \fIde\fR program allows a system administrator to examine and modify
|
||||
a \s-2MINIX\s0 file system device.
|
||||
Commands are available to move to any address on the disk
|
||||
and display the disk block contents. This information may
|
||||
be presented in one of three visual modes: as two-byte words,
|
||||
as ASCII characters or as a bit map. The disk may be searched
|
||||
for a string of characters. If the \fB\(enw\fR option is given,
|
||||
\fIde\fR will open the device for writing and words may be
|
||||
modified.
|
||||
Without this flag, writing is prohibited.
|
||||
Lost blocks and files can be recovered using a variety of
|
||||
commands. The \fB\(enr\fR option supports automated recovery of
|
||||
files removed by \fIunlink\fR.
|
||||
.SS "Positioning"
|
||||
.PP
|
||||
Disks are divided into blocks (also called \*(OQzones\*(CQ) of 1024
|
||||
bytes. \fIDe\fR keeps a current address on the disk as a
|
||||
block number and a byte offset within the block. In some
|
||||
visual modes the offset is rounded off, for example, in
|
||||
\*(OQword\*(CQ mode the offset must be even.
|
||||
.PP
|
||||
There are different types of blocks on a file system device,
|
||||
including a super block, bit maps, i-nodes and data blocks.
|
||||
\fIDe\fR knows the type of the current block, but will allow
|
||||
most positioning commands and visual modes to function
|
||||
anywhere on the disk.
|
||||
.PP
|
||||
The \fIf\fR command (or PGDN on the keypad) moves forward to the
|
||||
next block, similarly \fIb\fR (PGUP) moves backwards one block.
|
||||
\fIF\fR (END) moves to the last block and \fIB\fR (HOME) moves to the
|
||||
first block.
|
||||
.PP
|
||||
The arrow keys (or
|
||||
\fIu\fR, \fId\fR, \fIl\fR, and \fIr\fR) change the current
|
||||
address by small increments. The size of the increment
|
||||
depends on the current display mode, as shown below. The
|
||||
various sizes suit each display and pointers move on the
|
||||
screen to follow each press of an arrow key.
|
||||
.HS
|
||||
.if t .ta .75iR 1.5iR 2.25iR 3.0iR 3.75iR
|
||||
.if n .ta .75i 1.5i 2.25i 3.0i 3.75i
|
||||
.nf
|
||||
\fB Mode Up Down Left Right\fR
|
||||
Word \(mi2 +2 \(mi32 +32
|
||||
Block \(mi64 +64 \(mi1 +1
|
||||
Map \(mi256 +256 \(mi4 +4
|
||||
.fi
|
||||
.HS
|
||||
The \fIg\fR command allows movement to any specified block.
|
||||
Like all commands that take arguments, a prompt and
|
||||
subsequent input are written to the bottom line of the
|
||||
screen. Numerical entry may be decimal, octal or
|
||||
hexadecimal, for example 234, \(mi1, 070, 0xf3, \(miX3C.
|
||||
.PP
|
||||
While checking an i-node one may want to move to a block
|
||||
listed as a zone of the file. The \fIG\fR command takes the
|
||||
contents at the current address in the device as a block
|
||||
number and indirectly jumps to that block.
|
||||
.PP
|
||||
The address may be set to the start of any i-node using
|
||||
the \fI\fR command and supplying an i-node number. The \fII\fR
|
||||
command maps a given file name into an i-node address.
|
||||
The file must exist on the current device and this
|
||||
device must be mounted.
|
||||
.SS "The Display"
|
||||
.PP
|
||||
The first line of the display contains the device name,
|
||||
the name of the current output file (if one is open) and
|
||||
the current search string. If \fIde\fR is being run with
|
||||
the \fB\(enw\fR option then the device name is flagged with \*(OQ(w).\*(CQ
|
||||
If a string is too long to fit on the line it is marked with \*(OQ...\*(CQ.
|
||||
.PP
|
||||
The second line contains the current block number, the
|
||||
total number of blocks, and the type of the current block.
|
||||
The types are: boot, super, i-node bit map, zone bit map,
|
||||
i-nodes and data block.
|
||||
If the current address is
|
||||
within a data block then the string \*(OQin use\*(CQ is displayed
|
||||
if the block corresponds to a set in the zone bit map.
|
||||
.PP
|
||||
The third line shows the offset in the current block. If
|
||||
the current address is within either the i-node or zone bit
|
||||
maps then the i-node or block number corresponding to the
|
||||
current bit is shown. If the current address is within an
|
||||
i-node then the i-node number and \*(OQin use\*(CQ status is displayed.
|
||||
If the address is within a bit map or i-node block, but past
|
||||
the last usable entry, then the string \*(OQpadding\*(CQ is shown.
|
||||
.PP
|
||||
The rest of the screen is used to display data from the
|
||||
current block. There are three visual display modes:
|
||||
\*(OQword,\*(CQ \*(OQblock,\*(CQ and \*(OQmap.\*(CQ
|
||||
The \fIv\fR command followed by
|
||||
\fIw\fR, \fIb\fR, or \fIm\fR sets the current display mode.
|
||||
.PP
|
||||
In \*(OQword\*(CQ mode 16 words, of two bytes each, are shown in
|
||||
either base 2, 8, 10 or 16. The current base is displayed
|
||||
to the far right of the screen. It can be changed using the
|
||||
\fIo\fR command followed by either an \fIh\fR (hexadecimal), \fId\fR
|
||||
(decimal), \fIo\fR (octal) or \fIb\fR (binary).
|
||||
.PP
|
||||
\fIDe\fR knows where i-nodes are, and will display the
|
||||
contents in a readable format, including the \fIrwx\fR bits,
|
||||
the user name and the time field. If the current page
|
||||
is at the beginning of the super block, or an executable
|
||||
file or an \fIar\fR archive, then \fIde\fR will also inform
|
||||
the user. In all other cases the contents of the 16
|
||||
words are shown to the right as equivalent ASCII
|
||||
characters.
|
||||
.PP
|
||||
In \*(OQblock\*(CQ mode a whole block of 1024 bytes is displayed
|
||||
as ASCII characters, 64 columns by 16 lines. Control codes
|
||||
are shown as highlighted characters. If the high order bit
|
||||
is set in any of the 1024 bytes then an \*(OQMSB\*(CQ flag is shown
|
||||
on the far right of the screen, but these bytes are not
|
||||
individually marked.
|
||||
.PP
|
||||
In \*(OQmap\*(CQ mode 2048 bits (256 bytes) are displayed from the
|
||||
top to the bottom (32 bits) and from the left to the right
|
||||
of the screen. Bit zero of a byte is towards the top of the
|
||||
screen. This visual mode is generally used to observe
|
||||
the bit map blocks. The number of set bits displayed is
|
||||
written on the far right of the screen.
|
||||
.SS "Searching"
|
||||
.PP
|
||||
A search for an ASCII string is initiated by the \fI/\fR command.
|
||||
Control characters not used for other purposes may be
|
||||
entered in the search string, for example CTRL-J is an end-of-line
|
||||
character. The search is from the current position to
|
||||
the end of the current device.
|
||||
.PP
|
||||
Once a search string has been defined by a use of \fI/\fR, the
|
||||
next search may be initiated with the \fIn\fR command, (a \fI/\fR
|
||||
followed immediately by an ENTER is equivalent to an \fIn\fR).
|
||||
.PP
|
||||
Whenever a search is in progress \fIde\fR will append
|
||||
one \fI.\fR to the prompt line for every 500 blocks searched. If the
|
||||
string is found between the end of the file system and the
|
||||
actual end of the device, then the current address is set to
|
||||
the end of the file system.
|
||||
.PP
|
||||
Some of the positioning commands push the current address
|
||||
and visual mode in a stack before going to a new address.
|
||||
These commands are
|
||||
\fIB\fR, \fIF\fR, \fIg\fR, \fIG\fR, \fIi\fR, \fII\fR, \fIn\fR, \fIx\fR and
|
||||
\fI/\fR.
|
||||
The \fIp\fR
|
||||
(previous) command pops the last address and visual mode
|
||||
from the stack. This stack is eight entries deep.
|
||||
.SS "Modifying the File System"
|
||||
.PP
|
||||
The \fIs\fR command will prompt for a data word and store it at
|
||||
the current address on the disk. This is used to change
|
||||
information that can not be easily changed by any other
|
||||
means.
|
||||
.PP
|
||||
The data word is 16 bits wide, it may be entered in decimal,
|
||||
octal or hexadecimal. Remember that the \fB\(enw\fR option must
|
||||
be specified for the \fIs\fR command to operate. Be careful
|
||||
when modifying a mounted file system.
|
||||
.SS "Recovering Files"
|
||||
.PP
|
||||
Any block on the disk may be written to an output file.
|
||||
This is used to recover blocks marked as free on the
|
||||
disk. A write command will request a file name the first
|
||||
time it is used, on subsequent writes the data is appended
|
||||
to the current output file.
|
||||
.PP
|
||||
The name of the current output file is changed using the
|
||||
\fIc\fR command. This file should be on a different file system,
|
||||
to avoid overwriting an i-node or block before it is
|
||||
recovered.
|
||||
.PP
|
||||
An ASCII block is usually recovered using the \fIw\fR command.
|
||||
All bytes will have their most significant bit cleared before
|
||||
being written to the output file. Bytes containing '\\0'
|
||||
or '\\177' are not copied. The \fIW\fR command writes the current
|
||||
block (1024 bytes exactly) to the output file.
|
||||
.PP
|
||||
When a file is deleted using \fIunlink\fR the i-node number
|
||||
in the directory is zeroed, but before its removal, it is
|
||||
copied into the end of the file name field. This allows
|
||||
the i-node of a deleted file to be found by searching
|
||||
through a directory. The \fIx\fR command asks for the path
|
||||
name of a lost file, extracts the old i-node number and
|
||||
changes the current disk address to the start of the
|
||||
i-node.
|
||||
.PP
|
||||
Once an i-node is found, all of the freed blocks may be
|
||||
recovered by checking the i-node zone fields, using 'G'
|
||||
to go to a block, writing it back out using 'w', going
|
||||
back to the i-node with \fIp\fR and advancing to the next
|
||||
block. This file extraction process is automated by using
|
||||
the \fIX\fR command, which goes through the i-node, indirect
|
||||
and double indirect blocks finding all the block pointers
|
||||
and recovering all the blocks of the file.
|
||||
.PP
|
||||
The \fIX\fR command closes the current output file and asks
|
||||
for the name of a new output file. All of the disk blocks
|
||||
must be marked as free, if they are not the command stops
|
||||
and the file must be recovered manually.
|
||||
.PP
|
||||
When extracting lost blocks \fIde\fR will maintain \*(OQholes\*(CQ in
|
||||
the file. Thus, a recovered sparse file does not allocate
|
||||
unused blocks and will keep its efficient storage scheme.
|
||||
This property of the \fIX\fR command may be used to move a sparse
|
||||
file from one device to another.
|
||||
.PP
|
||||
Automatic recovery may be initiated by the \fB\(enr\fR option on
|
||||
the command line. Also specified is the path name of a
|
||||
file just removed by \fIunlink\fR. \fIDe\fR determines which
|
||||
mounted file system device held the file and opens it for
|
||||
reading. The lost i-node is found and the file extracted by
|
||||
automatically performing an \fIx\fR and an \fIX\fR command.
|
||||
.PP
|
||||
The recovered file will be written to \fI/tmp\fR. \fIDe\fR will
|
||||
refuse to automatically recover a file on the same file
|
||||
system as \fI/tmp\fR. The lost file must have belonged to the
|
||||
user. If automatic recovery will not complete, then manual
|
||||
recovery may be performed.
|
||||
.SS "Miscellaneous"
|
||||
.PP
|
||||
The user can terminate a session with \fIde\fR by typing
|
||||
\fIq\fR, CTRL-D, or the key associated with SIGQUIT.
|
||||
.PP
|
||||
The \fIm\fR command invokes the \s-2MINIX\s0 \fIsh\fR shell as a subprocess.
|
||||
.PP
|
||||
For help while using \fIde\fR use \fIh\fR.
|
||||
.SS "Command Summary"
|
||||
.LP
|
||||
.ta 0.25i 1.0i 1.5i
|
||||
.nf
|
||||
.sp
|
||||
PGUP b Back one block
|
||||
PGDN f Forward one block
|
||||
HOME B Goto first block
|
||||
END F Goto last block
|
||||
UP u Move back 2/64/256 bytes
|
||||
DOWN d Move forward 2/64/256 bytes
|
||||
LEFT l Move back 32/1/4 bytes
|
||||
RIGHT r Move forward 32/1/4 bytes
|
||||
g Goto specified block
|
||||
G Goto block indirectly
|
||||
i Goto specified i-node
|
||||
I Filename to i-node
|
||||
/ Search
|
||||
n Next occurrence
|
||||
p Previous address
|
||||
h Help
|
||||
EOF q Quit
|
||||
m \s-2MINIX\s0 shell
|
||||
v Visual mode (w b m)
|
||||
o Output base (h d o b)
|
||||
c Change file name
|
||||
w Write ASCII block
|
||||
W Write block exactly
|
||||
x Extract lost directory entry
|
||||
X Extract lost file blocks
|
||||
s Store word
|
||||
.fi
|
||||
.sp
|
||||
NOTES:
|
||||
When entering a line in response to a prompt from \fIde\fR
|
||||
there are a couple of editing characters available. The
|
||||
previous character may be erased by typing CTRL-H and the
|
||||
whole line may be erased by typing CTRL-U. ENTER terminates
|
||||
the input. If DELETE or a non-ASCII character is typed
|
||||
then the command requesting the input is aborted.
|
||||
.PP
|
||||
The commands \fIG\fR, \fIs\fR and \fIX\fR will only function if
|
||||
the current visual display mode is \*(OQword.\*(CQ
|
||||
The commands
|
||||
\fIi\fR, \fII\fR and \fIx\fR change the mode to \*(OQword\*(CQ on
|
||||
completion. The commands \fIG\fR and \fI/\fR change the mode
|
||||
to \*(OQblock\*(CQ. These restrictions and automatic mode
|
||||
conversions are intended to aid the user.
|
||||
.PP
|
||||
The \*(OQmap\*(CQ mode uses special graphic characters, and
|
||||
only functions if the user is at the console.
|
||||
.PP
|
||||
\fIDe\fR generates warnings for illegal user input or if
|
||||
erroneous data is found on the disk, for example a
|
||||
corrupted magic number. Warnings appear in the middle
|
||||
of the screen for two seconds, then the current page
|
||||
is redrawn. Some minor errors, for example, setting
|
||||
an unknown visual mode, simply ring the bell. Major
|
||||
errors, for example I/O problems on the file system
|
||||
device cause an immediate exit from \fIde\fR.
|
||||
.PP
|
||||
The i-node and zone bit maps are read from the device
|
||||
when \fIde\fR starts up. These determine whether \*(OQin use\*(CQ
|
||||
or \*(OQnot in use\*(CQ is displayed in the status field at
|
||||
the top of the screen. The bit maps are not re-read
|
||||
while using \fIde\fR and will become out-of-date if
|
||||
observing a mounted file system.
|
||||
.PP
|
||||
\fIDe\fR requires termcap definitions for \*(OQcm\*(CQ and \*(OQcl\*(CQ.
|
||||
Furthermore, \*(OQso\*(CQ and \*(OQse\*(CQ will also be used if available.
|
||||
The ANSI strings generated by the keypad arrows are recognized,
|
||||
as well as any single character codes defined by \*(OQku\*(CQ,
|
||||
\*(OQkd\*(CQ, \*(OQkl\*(CQ and \*(OQkr\*(CQ.
|
||||
.SS "Author"
|
||||
.PP
|
||||
The \fIde\fR program was written by Terrence Holm.
|
|
@ -53,10 +53,8 @@ typedef struct _dirdesc DIR;
|
|||
|
||||
#if defined(_NETBSD_SOURCE)
|
||||
|
||||
#ifndef __minix
|
||||
/* definitions for library routines operating on directories. */
|
||||
#define DIRBLKSIZ 1024
|
||||
#endif
|
||||
|
||||
/* structure describing an open directory. */
|
||||
struct _dirdesc {
|
||||
|
|
|
@ -12,28 +12,10 @@
|
|||
#define _DIRENT_H
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <minix/dir.h>
|
||||
|
||||
/* _fl_direct is a flexible directory entry. Actually it's a union of 8
|
||||
* characters and the 3 fields defined below.
|
||||
*/
|
||||
|
||||
/* Flexible directory entry: */
|
||||
struct _fl_direct { /* First slot in an entry */
|
||||
ino_t d_ino;
|
||||
unsigned char d_extent;
|
||||
char d_name[3]; /* two characters for the shortest name */
|
||||
};
|
||||
|
||||
/* Name of length len needs _EXTENT(len) extra slots. */
|
||||
#define _EXTENT(len) (((len) + 5) >> 3)
|
||||
|
||||
/* Version 7 directory entry: */
|
||||
struct _v7_direct {
|
||||
ino_t d_ino;
|
||||
char d_name[DIRSIZ];
|
||||
};
|
||||
|
||||
/* The block size must be at least 1024 bytes, because otherwise
|
||||
* the superblock (at 1024 bytes) overlaps with other filesystem data.
|
||||
*/
|
||||
|
@ -49,8 +31,4 @@ struct _v7_direct {
|
|||
/* This is the block size for the fixed versions of the filesystem (V1/V2) */
|
||||
#define _STATIC_BLOCK_SIZE 1024
|
||||
|
||||
#define _STATIC_FLEX_PER_BLOCK (_STATIC_BLOCK_SIZE/sizeof(struct _fl_direct))
|
||||
#define _FLEX_PER_V7 (_EXTENT(DIRSIZ) + 1)
|
||||
#define _FLEX_PER_BLOCK (_STATIC_BLOCK_SIZE/sizeof(struct _fl_direct))
|
||||
|
||||
#endif /* _DIRENT_H */
|
||||
|
|
|
@ -12,7 +12,7 @@ INCS+= ioc_net.h statfs.h
|
|||
INCS+= ansi.h atomic.h \
|
||||
bitops.h bswap.h \
|
||||
cdefs.h cdefs_aout.h cdefs_elf.h ctype_bits.h ctype_inline.h \
|
||||
dir.h dirent.h exec_elf.h \
|
||||
dirent.h exec_elf.h \
|
||||
endian.h errno.h \
|
||||
fcntl.h fd_set.h featuretest.h file.h \
|
||||
float_ieee754.h gcq.h gmon.h hash.h \
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
/*
|
||||
* this files resolves conflicts between the file of the host system and
|
||||
* the minix specific one. This file is included directly only on Minix
|
||||
* and it is an error to do so on any other system
|
||||
*/
|
||||
|
||||
#if !defined(_MINIX) || !defined(__minix)
|
||||
#error "Including Minix specific file in program targeted for other system"
|
||||
#else
|
||||
#include <minix/dir.h>
|
||||
#endif
|
|
@ -26,7 +26,7 @@
|
|||
#define LINK_MAX SHRT_MAX /* # links a file may have */
|
||||
#define MAX_CANON 255 /* size of the canonical input queue */
|
||||
#define MAX_INPUT 255 /* size of the type-ahead buffer */
|
||||
#define NAME_MAX 60 /* # chars in a file name (actually DIRSZ) */
|
||||
#define NAME_MAX 255 /* system-wide max # chars in a file name */
|
||||
#define NGROUPS_MAX 8 /* max. number of supplemental groups */
|
||||
#define UID_MAX SHRT_MAX /* max value for a uid_t */
|
||||
#ifndef OPEN_MAX
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#ifndef EXT2_BUF_H
|
||||
#define EXT2_BUF_H
|
||||
|
||||
#include <sys/dir.h> /* need struct direct */
|
||||
#include <dirent.h>
|
||||
|
||||
union fsdata_u {
|
||||
|
|
|
@ -1,22 +1,12 @@
|
|||
#include <sys/dir.h> /* need struct direct */
|
||||
#include <dirent.h>
|
||||
|
||||
PUBLIC struct buf {
|
||||
union {
|
||||
char b__data[_MAX_BLOCK_SIZE]; /* ordinary user data */
|
||||
struct direct b__dir[NR_DIR_ENTRIES(_MAX_BLOCK_SIZE)];/* directory block */
|
||||
} b;
|
||||
|
||||
char b_data[_MAX_BLOCK_SIZE]; /* ordinary user data */
|
||||
block_t b_blocknr; /* block number of its (minor) device */
|
||||
char b_count; /* number of users of this buffer */
|
||||
} buf[NR_BUFS];
|
||||
|
||||
/* A block is free if b_dev == NO_DEV. */
|
||||
|
||||
|
||||
/* These defs make it possible to use to bp->b_data instead of bp->b.b__data */
|
||||
#define b_data b.b__data
|
||||
#define b_dir b.b__dir
|
||||
|
||||
#define INODE_BLOCK 0 /* inode block */
|
||||
#define DIRECTORY_BLOCK 1 /* directory block */
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
* will eventually be rewritten to the disk.
|
||||
*/
|
||||
|
||||
#include <sys/dir.h> /* need struct direct */
|
||||
#include <dirent.h>
|
||||
|
||||
union fsdata_u {
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
#define INODE_HASH_SIZE ((unsigned long)1<<INODE_HASH_LOG2)
|
||||
#define INODE_HASH_MASK (((unsigned long)1<<INODE_HASH_LOG2)-1)
|
||||
|
||||
/* Max. filename length */
|
||||
#define MFS_NAME_MAX MFS_DIRSIZ
|
||||
|
||||
|
||||
/* The type of sizeof may be (unsigned) long. Use the following macro for
|
||||
* taking the sizes of small objects so that there are no surprises like
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <minix/syslib.h>
|
||||
#include <minix/sysutil.h>
|
||||
|
||||
#include "mfsdir.h"
|
||||
#include "const.h"
|
||||
#include "type.h"
|
||||
#include "proto.h"
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
FORWARD _PROTOTYPE( int freesp_inode, (struct inode *rip, off_t st,
|
||||
off_t end) );
|
||||
FORWARD _PROTOTYPE( int remove_dir, (struct inode *rldirp,
|
||||
struct inode *rip, char dir_name[NAME_MAX]) );
|
||||
struct inode *rip, char dir_name[MFS_NAME_MAX]) );
|
||||
FORWARD _PROTOTYPE( int unlink_file, (struct inode *dirp,
|
||||
struct inode *rip, char file_name[NAME_MAX]) );
|
||||
struct inode *rip, char file_name[MFS_NAME_MAX]) );
|
||||
FORWARD _PROTOTYPE( off_t nextblock, (off_t pos, int zone_size) );
|
||||
FORWARD _PROTOTYPE( void zerozone_half, (struct inode *rip, off_t pos,
|
||||
int half, int zone_size) );
|
||||
|
@ -36,7 +36,7 @@ PUBLIC int fs_link()
|
|||
|
||||
struct inode *ip, *rip;
|
||||
register int r;
|
||||
char string[NAME_MAX];
|
||||
char string[MFS_NAME_MAX];
|
||||
struct inode *new_ip;
|
||||
phys_bytes len;
|
||||
|
||||
|
@ -119,7 +119,7 @@ PUBLIC int fs_unlink()
|
|||
register struct inode *rip;
|
||||
struct inode *rldirp;
|
||||
int r;
|
||||
char string[NAME_MAX];
|
||||
char string[MFS_NAME_MAX];
|
||||
phys_bytes len;
|
||||
|
||||
/* Copy the last component */
|
||||
|
@ -213,7 +213,7 @@ PUBLIC int fs_rdlink()
|
|||
PRIVATE int remove_dir(rldirp, rip, dir_name)
|
||||
struct inode *rldirp; /* parent directory */
|
||||
struct inode *rip; /* directory to be removed */
|
||||
char dir_name[NAME_MAX]; /* name of directory to be removed */
|
||||
char dir_name[MFS_NAME_MAX]; /* name of directory to be removed */
|
||||
{
|
||||
/* A directory file has to be removed. Five conditions have to met:
|
||||
* - The file must be a directory
|
||||
|
@ -249,7 +249,7 @@ char dir_name[NAME_MAX]; /* name of directory to be removed */
|
|||
PRIVATE int unlink_file(dirp, rip, file_name)
|
||||
struct inode *dirp; /* parent directory of file */
|
||||
struct inode *rip; /* inode of file, may be NULL too. */
|
||||
char file_name[NAME_MAX]; /* name of file to be removed */
|
||||
char file_name[MFS_NAME_MAX]; /* name of file to be removed */
|
||||
{
|
||||
/* Unlink 'file_name'; rip must be the inode of 'file_name' or NULL. */
|
||||
|
||||
|
@ -291,7 +291,7 @@ PUBLIC int fs_rename()
|
|||
int r = OK; /* error flag; initially no error */
|
||||
int odir, ndir; /* TRUE iff {old|new} file is dir */
|
||||
int same_pdir; /* TRUE iff parent dirs are the same */
|
||||
char old_name[NAME_MAX], new_name[NAME_MAX];
|
||||
char old_name[MFS_NAME_MAX], new_name[MFS_NAME_MAX];
|
||||
ino_t numb;
|
||||
phys_bytes len;
|
||||
|
||||
|
|
26
servers/mfs/mfsdir.h
Normal file
26
servers/mfs/mfsdir.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#ifndef _MFSDIR_H
|
||||
#define _MFSDIR_H
|
||||
|
||||
#ifdef __NBSD_LIBC
|
||||
#include <sys/cdefs.h>
|
||||
#endif
|
||||
#include <minix/types.h>
|
||||
|
||||
/* Maximum Minix MFS on-disk directory filename.
|
||||
* MFS uses 'struct direct' to write and parse
|
||||
* directory entries, so this can't be changed
|
||||
* without breaking filesystems.
|
||||
*/
|
||||
|
||||
#define MFS_DIRSIZ 60
|
||||
|
||||
struct direct {
|
||||
ino_t mfs_d_ino;
|
||||
char mfs_d_name[MFS_DIRSIZ];
|
||||
#ifdef __NBSD_LIBC
|
||||
} __packed;
|
||||
#else
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* _MFSDIR_H */
|
|
@ -20,7 +20,7 @@ PUBLIC int fs_create()
|
|||
struct inode *ldirp;
|
||||
struct inode *rip;
|
||||
mode_t omode;
|
||||
char lastc[NAME_MAX];
|
||||
char lastc[MFS_NAME_MAX];
|
||||
|
||||
/* Read request message */
|
||||
omode = (mode_t) fs_m_in.REQ_MODE;
|
||||
|
@ -73,7 +73,7 @@ PUBLIC int fs_create()
|
|||
PUBLIC int fs_mknod()
|
||||
{
|
||||
struct inode *ip, *ldirp;
|
||||
char lastc[NAME_MAX];
|
||||
char lastc[MFS_NAME_MAX];
|
||||
phys_bytes len;
|
||||
|
||||
/* Copy the last component and set up caller's user and group id */
|
||||
|
@ -108,7 +108,7 @@ PUBLIC int fs_mkdir()
|
|||
int r1, r2; /* status codes */
|
||||
ino_t dot, dotdot; /* inode numbers for . and .. */
|
||||
struct inode *rip, *ldirp;
|
||||
char lastc[NAME_MAX]; /* last component */
|
||||
char lastc[MFS_NAME_MAX]; /* last component */
|
||||
phys_bytes len;
|
||||
|
||||
/* Copy the last component and set up caller's user and group id */
|
||||
|
@ -175,7 +175,7 @@ PUBLIC int fs_slink()
|
|||
struct inode *sip; /* inode containing symbolic link */
|
||||
struct inode *ldirp; /* directory containing link */
|
||||
register int r; /* error code */
|
||||
char string[NAME_MAX]; /* last component of the new dir's path name */
|
||||
char string[MFS_NAME_MAX]; /* last component of the new dir's path name */
|
||||
struct buf *bp; /* disk buffer for link */
|
||||
|
||||
caller_uid = (uid_t) fs_m_in.REQ_UID;
|
||||
|
@ -254,7 +254,7 @@ PRIVATE struct inode *new_node(struct inode *ldirp,
|
|||
* to an appropriate value (OK or an error code).
|
||||
*
|
||||
* The parsed path rest is returned in 'parsed' if parsed is nonzero. It
|
||||
* has to hold at least NAME_MAX bytes.
|
||||
* has to hold at least MFS_NAME_MAX bytes.
|
||||
*/
|
||||
|
||||
register struct inode *rip;
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
PUBLIC char dot1[2] = "."; /* used for search_dir to bypass the access */
|
||||
PUBLIC char dot2[3] = ".."; /* permissions for . and .. */
|
||||
|
||||
FORWARD _PROTOTYPE( char *get_name, (char *name, char string[NAME_MAX+1]) );
|
||||
FORWARD _PROTOTYPE( char *get_name, (char *name, char string[MFS_NAME_MAX+1]) );
|
||||
FORWARD _PROTOTYPE( int ltraverse, (struct inode *rip, char *suffix) );
|
||||
FORWARD _PROTOTYPE( int parse_path, (ino_t dir_ino, ino_t root_ino,
|
||||
int flags, struct inode **res_inop,
|
||||
|
@ -143,7 +143,7 @@ int *symlinkp;
|
|||
int r, leaving_mount;
|
||||
struct inode *rip, *dir_ip;
|
||||
char *cp, *next_cp; /* component and next component */
|
||||
char component[NAME_MAX+1];
|
||||
char component[MFS_NAME_MAX+1];
|
||||
|
||||
/* Start parsing path at the first component in user_path */
|
||||
cp = user_path;
|
||||
|
@ -356,7 +356,7 @@ char *suffix; /* current remaining path. Has to point in the
|
|||
*===========================================================================*/
|
||||
PUBLIC struct inode *advance(dirp, string, chk_perm)
|
||||
struct inode *dirp; /* inode for directory to be searched */
|
||||
char string[NAME_MAX]; /* component name to look for */
|
||||
char string[MFS_NAME_MAX]; /* component name to look for */
|
||||
int chk_perm; /* check permissions when string is looked up*/
|
||||
{
|
||||
/* Given a directory and a component of a path, look up the component in
|
||||
|
@ -424,7 +424,7 @@ int chk_perm; /* check permissions when string is looked up*/
|
|||
*===========================================================================*/
|
||||
PRIVATE char *get_name(path_name, string)
|
||||
char *path_name; /* path name to parse */
|
||||
char string[NAME_MAX+1]; /* component extracted from 'old_name' */
|
||||
char string[MFS_NAME_MAX+1]; /* component extracted from 'old_name' */
|
||||
{
|
||||
/* Given a pointer to a path name in fs space, 'path_name', copy the first
|
||||
* component to 'string' (truncated if necessary, always nul terminated).
|
||||
|
@ -450,8 +450,8 @@ char string[NAME_MAX+1]; /* component extracted from 'old_name' */
|
|||
|
||||
len = (size_t) (ep - cp);
|
||||
|
||||
/* Truncate the amount to be copied if it exceeds NAME_MAX */
|
||||
if (len > NAME_MAX) len = NAME_MAX;
|
||||
/* Truncate the amount to be copied if it exceeds MFS_NAME_MAX */
|
||||
if (len > MFS_NAME_MAX) len = MFS_NAME_MAX;
|
||||
|
||||
/* Special case of the string at cp is empty */
|
||||
if (len == 0)
|
||||
|
@ -470,7 +470,7 @@ char string[NAME_MAX+1]; /* component extracted from 'old_name' */
|
|||
*===========================================================================*/
|
||||
PUBLIC int search_dir(ldir_ptr, string, numb, flag, check_permissions)
|
||||
register struct inode *ldir_ptr; /* ptr to inode for dir to search */
|
||||
char string[NAME_MAX]; /* component to search for */
|
||||
char string[MFS_NAME_MAX]; /* component to search for */
|
||||
ino_t *numb; /* pointer to inode number */
|
||||
int flag; /* LOOK_UP, ENTER, DELETE or IS_EMPTY */
|
||||
int check_permissions; /* check permissions when flag is !IS_EMPTY */
|
||||
|
@ -543,13 +543,14 @@ int check_permissions; /* check permissions when flag is !IS_EMPTY */
|
|||
}
|
||||
|
||||
/* Match occurs if string found. */
|
||||
if (flag != ENTER && dp->d_ino != NO_ENTRY) {
|
||||
if (flag != ENTER && dp->mfs_d_ino != NO_ENTRY) {
|
||||
if (flag == IS_EMPTY) {
|
||||
/* If this test succeeds, dir is not empty. */
|
||||
if (strcmp(dp->d_name, "." ) != 0 &&
|
||||
strcmp(dp->d_name, "..") != 0) match = 1;
|
||||
if (strcmp(dp->mfs_d_name, "." ) != 0 &&
|
||||
strcmp(dp->mfs_d_name, "..") != 0) match = 1;
|
||||
} else {
|
||||
if (strncmp(dp->d_name, string, NAME_MAX) == 0){
|
||||
if (strncmp(dp->mfs_d_name, string,
|
||||
sizeof(dp->mfs_d_name)) == 0){
|
||||
match = 1;
|
||||
}
|
||||
}
|
||||
|
@ -561,9 +562,9 @@ int check_permissions; /* check permissions when flag is !IS_EMPTY */
|
|||
if (flag == IS_EMPTY) r = ENOTEMPTY;
|
||||
else if (flag == DELETE) {
|
||||
/* Save d_ino for recovery. */
|
||||
t = NAME_MAX - sizeof(ino_t);
|
||||
*((ino_t *) &dp->d_name[t]) = dp->d_ino;
|
||||
dp->d_ino = NO_ENTRY; /* erase entry */
|
||||
t = MFS_NAME_MAX - sizeof(ino_t);
|
||||
*((ino_t *) &dp->mfs_d_name[t]) = dp->mfs_d_ino;
|
||||
dp->mfs_d_ino = NO_ENTRY; /* erase entry */
|
||||
bp->b_dirt = DIRTY;
|
||||
ldir_ptr->i_update |= CTIME | MTIME;
|
||||
ldir_ptr->i_dirt = DIRTY;
|
||||
|
@ -572,14 +573,14 @@ int check_permissions; /* check permissions when flag is !IS_EMPTY */
|
|||
} else {
|
||||
sp = ldir_ptr->i_sp; /* 'flag' is LOOK_UP */
|
||||
*numb = (ino_t) conv4(sp->s_native,
|
||||
(int) dp->d_ino);
|
||||
(int) dp->mfs_d_ino);
|
||||
}
|
||||
put_block(bp, DIRECTORY_BLOCK);
|
||||
return(r);
|
||||
}
|
||||
|
||||
/* Check for free slot for the benefit of ENTER. */
|
||||
if (flag == ENTER && dp->d_ino == 0) {
|
||||
if (flag == ENTER && dp->mfs_d_ino == 0) {
|
||||
e_hit = TRUE; /* we found a free slot */
|
||||
break;
|
||||
}
|
||||
|
@ -613,10 +614,10 @@ int check_permissions; /* check permissions when flag is !IS_EMPTY */
|
|||
}
|
||||
|
||||
/* 'bp' now points to a directory block with space. 'dp' points to slot. */
|
||||
(void) memset(dp->d_name, 0, (size_t) NAME_MAX); /* clear entry */
|
||||
for (i = 0; i < NAME_MAX && string[i]; i++) dp->d_name[i] = string[i];
|
||||
(void) memset(dp->mfs_d_name, 0, (size_t) MFS_NAME_MAX); /* clear entry */
|
||||
for (i = 0; i < MFS_NAME_MAX && string[i]; i++) dp->mfs_d_name[i] = string[i];
|
||||
sp = ldir_ptr->i_sp;
|
||||
dp->d_ino = conv4(sp->s_native, (int) *numb);
|
||||
dp->mfs_d_ino = conv4(sp->s_native, (int) *numb);
|
||||
bp->b_dirt = DIRTY;
|
||||
put_block(bp, DIRECTORY_BLOCK);
|
||||
ldir_ptr->i_update |= CTIME | MTIME; /* mark mtime for update later */
|
||||
|
|
|
@ -68,9 +68,9 @@ _PROTOTYPE( int fs_slink, (void) );
|
|||
/* path.c */
|
||||
_PROTOTYPE( int fs_lookup, (void) );
|
||||
_PROTOTYPE( struct inode *advance, (struct inode *dirp,
|
||||
char string[NAME_MAX], int chk_perm) );
|
||||
char string[MFS_NAME_MAX], int chk_perm) );
|
||||
_PROTOTYPE( int search_dir, (struct inode *ldir_ptr,
|
||||
char string [NAME_MAX], ino_t *numb, int flag,
|
||||
char string [MFS_NAME_MAX], ino_t *numb, int flag,
|
||||
int check_permissions) );
|
||||
|
||||
|
||||
|
|
|
@ -605,15 +605,15 @@ PUBLIC int fs_getdents(void)
|
|||
else
|
||||
dp = &bp->b_dir[0];
|
||||
for (; dp < &bp->b_dir[NR_DIR_ENTRIES(block_size)]; dp++) {
|
||||
if (dp->d_ino == 0)
|
||||
if (dp->mfs_d_ino == 0)
|
||||
continue; /* Entry is not in use */
|
||||
|
||||
/* Compute the length of the name */
|
||||
cp = memchr(dp->d_name, '\0', NAME_MAX);
|
||||
cp = memchr(dp->mfs_d_name, '\0', sizeof(dp->mfs_d_name));
|
||||
if (cp == NULL)
|
||||
len = NAME_MAX;
|
||||
len = sizeof(dp->mfs_d_name);
|
||||
else
|
||||
len = cp - (dp->d_name);
|
||||
len = cp - (dp->mfs_d_name);
|
||||
|
||||
/* Compute record length */
|
||||
reclen = offsetof(struct dirent, d_name) + len + 1;
|
||||
|
@ -651,10 +651,10 @@ PUBLIC int fs_getdents(void)
|
|||
}
|
||||
|
||||
dep = (struct dirent *) &getdents_buf[tmpbuf_off];
|
||||
dep->d_ino = dp->d_ino;
|
||||
dep->d_ino = dp->mfs_d_ino;
|
||||
dep->d_off = ent_pos;
|
||||
dep->d_reclen = (unsigned short) reclen;
|
||||
memcpy(dep->d_name, dp->d_name, len);
|
||||
memcpy(dep->d_name, dp->mfs_d_name, len);
|
||||
dep->d_name[len] = '\0';
|
||||
tmpbuf_off += reclen;
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ PUBLIC int fs_statvfs()
|
|||
st.f_favail = st.f_ffree;
|
||||
st.f_fsid = fs_dev;
|
||||
st.f_flag = (sp->s_rd_only == 1 ? ST_RDONLY : 0);
|
||||
st.f_namemax = NAME_MAX;
|
||||
st.f_namemax = MFS_DIRSIZ;
|
||||
|
||||
/* Copy the struct to user space. */
|
||||
r = sys_safecopyto(fs_m_in.m_source, fs_m_in.REQ_GRANT, 0, (vir_bytes) &st,
|
||||
|
|
Loading…
Reference in a new issue