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:
Ben Gras 2011-08-04 23:15:16 +00:00
parent e2bdf44720
commit f984dbba70
48 changed files with 125 additions and 5451 deletions

View file

@ -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;

View file

@ -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));

View file

@ -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

View file

@ -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 *);

View file

@ -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 \

View file

@ -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;
}

View file

@ -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>

View file

@ -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.

File diff suppressed because it is too large Load diff

View file

@ -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 */

View file

@ -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 );
}

View file

@ -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 );
}

View file

@ -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

View file

@ -4,7 +4,6 @@
*/
#include <sys/types.h>
#include <sys/dir.h>
#include <sys/stat.h>
#include <machine/partition.h>
#include <minix/partition.h>

View file

@ -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');
}

View file

@ -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);
}
}
}

View file

@ -1,5 +0,0 @@
PROG= readfs
CPPFLAGS+= -I${MINIXSRCDIR}/servers
MAN=
.include <bsd.prog.mk>

View file

@ -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);
}

View file

@ -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

View file

@ -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 \

View file

@ -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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -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)

View file

@ -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 \

View file

@ -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

View file

@ -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 \

View file

@ -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).

View file

@ -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>

View file

@ -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.

View file

@ -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 {

View file

@ -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 */

View file

@ -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 \

View file

@ -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

View file

@ -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

View file

@ -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 {

View file

@ -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 */

View file

@ -14,7 +14,6 @@
* will eventually be rewritten to the disk.
*/
#include <sys/dir.h> /* need struct direct */
#include <dirent.h>
union fsdata_u {

View file

@ -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

View file

@ -24,6 +24,7 @@
#include <minix/syslib.h>
#include <minix/sysutil.h>
#include "mfsdir.h"
#include "const.h"
#include "type.h"
#include "proto.h"

View file

@ -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
View 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 */

View file

@ -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;

View file

@ -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 */

View file

@ -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) );

View file

@ -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;
}

View file

@ -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,