Patch from Victor V. Vengerov <vvv@oktet.ru> to remove Linux code.

This commit is contained in:
Chris Johns
2003-07-02 14:09:15 +00:00
parent 3b44f15375
commit c125425b61
7 changed files with 318 additions and 167 deletions

View File

@@ -1,3 +1,10 @@
2003-07-02 Chris Johns <cjohns@cybertec.com.au>
* src/dosfs/Makefile.am, src/dosfs/msdos.h,
src/dosfs/msdos_conv.c, src/dosfs/msdos_create.c,
src/dosfs/msdos_dir.c, src/dosfs/msdos_misc.c: Patch from Victor
V. Vengerov <vvv@oktet.ru> to remove Linux code.
* src/dosfs/fat.c, src/dosfs/fat.h: Comment have been updated.
2003-06-10 Phil Torre <ptorre@zetron.com>
PR 411/filesystem

View File

@@ -14,7 +14,8 @@ FATFS_C_FILES = fat.c fat_fat_operations.c fat_file.c
DOSFS_C_FILES = msdos_create.c msdos_dir.c msdos_eval.c msdos_file.c \
msdos_free.c msdos_fsunmount.c msdos_handlers_dir.c \
msdos_handlers_file.c msdos_init.c msdos_initsupp.c \
msdos_misc.c msdos_mknod.c msdos_node_type.c
msdos_misc.c msdos_mknod.c msdos_node_type.c \
msdos_conv.c
if !UNIX
LIB = ${ARCH}/libdosfs.a

View File

@@ -81,7 +81,7 @@ typedef rtems_filesystem_node_types_t msdos_node_type_t;
/*
* Macros for fetching fields from 32 bytes long FAT Directory Entry
* Structure (see M$ White Paper)
* Structure
*/
#define MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE 32 /* 32 bytes */
@@ -104,7 +104,7 @@ typedef rtems_filesystem_node_types_t msdos_node_type_t;
/*
* Fields offset in 32 bytes long FAT Directory Entry
* Structure (see M$ White Paper)
* Structure
*/
#define MSDOS_FILE_SIZE_OFFSET 28
#define MSDOS_FILE_NAME_OFFSET 0
@@ -115,7 +115,7 @@ typedef rtems_filesystem_node_types_t msdos_node_type_t;
/*
* Possible values of DIR_Attr field of 32 bytes long FAT Directory Entry
* Structure (see M$ White Paper)
* Structure
*/
#define MSDOS_ATTR_READ_ONLY 0x01
#define MSDOS_ATTR_HIDDEN 0x02
@@ -124,9 +124,24 @@ typedef rtems_filesystem_node_types_t msdos_node_type_t;
#define MSDOS_ATTR_DIRECTORY 0x10
#define MSDOS_ATTR_ARCHIVE 0x20
#define MSDOS_DT_2SECONDS_MASK 0x1F /* seconds divided by 2 */
#define MSDOS_DT_2SECONDS_SHIFT 0
#define MSDOS_DT_MINUTES_MASK 0x7E0 /* minutes */
#define MSDOS_DT_MINUTES_SHIFT 5
#define MSDOS_DT_HOURS_MASK 0xF800 /* hours */
#define MSDOS_DT_HOURS_SHIFT 11
#define MSDOS_DD_DAY_MASK 0x1F /* day of month */
#define MSDOS_DD_DAY_SHIFT 0
#define MSDOS_DD_MONTH_MASK 0x1E0 /* month */
#define MSDOS_DD_MONTH_SHIFT 5
#define MSDOS_DD_YEAR_MASK 0xFE00 /* year - 1980 */
#define MSDOS_DD_YEAR_SHIFT 9
/*
* Possible values of DIR_Name[0] field of 32 bytes long FAT Directory Entry
* Structure (see M$ White Paper)
* Structure
*/
#define MSDOS_THIS_DIR_ENTRY_EMPTY 0xE5
#define MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY 0x00
@@ -171,7 +186,7 @@ typedef enum msdos_token_types_e
#define DOT_NODE_P(p) ((char *)(p))
#define DOTDOT_NODE_P(p) ((char *)((p) + MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE))
/* Size limits for files and directories (see M$ White Paper) */
/* Size limits for files and directories */
#define MSDOS_MAX_DIR_LENGHT 0x200000 /* 2,097,152 bytes */
#define MSDOS_MAX_FILE_SIZE 0xFFFFFFFF /* 4 Gb */
@@ -345,13 +360,15 @@ msdos_get_name_node(rtems_filesystem_location_info_t *parent_loc,
int
msdos_dir_info_remove(rtems_filesystem_location_info_t *pathloc);
void
msdos_date_unix2dos(int unix_date,
unsigned short *time_val,
unsigned short *date);
int
msdos_filename_unix2dos(char *un, int unlen, char *dn);
unsigned int
msdos_date_dos2unix(unsigned short time_val, unsigned short date);
void
msdos_date_unix2dos(unsigned int tsp, unsigned short *ddp,
unsigned short *dtp);
unsigned int
msdos_date_dos2unix(unsigned int dd, unsigned int dt);
int
msdos_set_first_cluster_num(rtems_filesystem_mount_table_entry_t *mt_entry,

View File

@@ -0,0 +1,273 @@
/*
* Adaptation of NetBSD code for RTEMS by Victor V. Vengerov <vvv@oktet.ru>
*/
/* $NetBSD: msdosfs_conv.c,v 1.10 1994/12/27 18:36:24 mycroft Exp $ */
/*
* Written by Paul Popelka (paulp@uts.amdahl.com)
*
* You can do anything you want with this software, just don't say you wrote
* it, and don't remove this notice.
*
* This software is provided "as is".
*
* The author supplies this software to be publicly redistributed on the
* understanding that the author is not responsible for the correct
* functioning of this software in any circumstances and is not liable for
* any damages caused by this software.
*
* October 1992
*/
#include <rtems.h>
#include "msdos.h"
/*
* Days in each month in a regular year.
*/
static u_short regyear[] = {
31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31
};
/*
* Days in each month in a leap year.
*/
static u_short leapyear[] = {
31, 29, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31
};
/*
* Variables used to remember parts of the last time conversion. Maybe we
* can avoid a full conversion.
*/
static u_long lasttime;
static u_long lastday;
static u_short lastddate;
static u_short lastdtime;
/*
* Convert the unix version of time to dos's idea of time to be used in
* file timestamps. The passed in unix time is assumed to be in GMT.
*/
void
msdos_date_unix2dos(unsigned int t, unsigned short *ddp,
unsigned short *dtp)
{
u_long days;
u_long inc;
u_long year;
u_long month;
u_short *months;
/*
* If the time from the last conversion is the same as now, then
* skip the computations and use the saved result.
*/
if (lasttime != t) {
lasttime = t;
lastdtime = (((t % 60) >> 1) << MSDOS_DT_2SECONDS_SHIFT)
+ (((t / 60) % 60) << MSDOS_DT_MINUTES_SHIFT)
+ (((t / 3600) % 24) << MSDOS_DT_HOURS_SHIFT);
/*
* If the number of days since 1970 is the same as the last
* time we did the computation then skip all this leap year
* and month stuff.
*/
days = t / (24 * 60 * 60);
if (days != lastday) {
lastday = days;
for (year = 1970;; year++) {
inc = year & 0x03 ? 365 : 366;
if (days < inc)
break;
days -= inc;
}
months = year & 0x03 ? regyear : leapyear;
for (month = 0; month < 12; month++) {
if (days < months[month])
break;
days -= months[month];
}
lastddate = ((days + 1) << MSDOS_DD_DAY_SHIFT)
+ ((month + 1) << MSDOS_DD_MONTH_SHIFT);
/*
* Remember dos's idea of time is relative to 1980.
* unix's is relative to 1970. If somehow we get a
* time before 1980 then don't give totally crazy
* results.
*/
if (year > 1980)
lastddate += (year - 1980) <<
MSDOS_DD_YEAR_SHIFT;
}
}
*dtp = lastdtime;
*ddp = lastddate;
}
/*
* The number of seconds between Jan 1, 1970 and Jan 1, 1980. In that
* interval there were 8 regular years and 2 leap years.
*/
#define SECONDSTO1980 (((8 * 365) + (2 * 366)) * (24 * 60 * 60))
static u_short lastdosdate;
static u_long lastseconds;
/*
* Convert from dos' idea of time to unix'. This will probably only be
* called from the stat(), and fstat() system calls and so probably need
* not be too efficient.
*/
unsigned int
msdos_date_dos2unix(unsigned int dd, unsigned int dt)
{
u_long seconds;
u_long m, month;
u_long y, year;
u_long days;
u_short *months;
seconds = ((dt & MSDOS_DT_2SECONDS_MASK) >> MSDOS_DT_2SECONDS_SHIFT)
+ ((dt & MSDOS_DT_MINUTES_MASK) >> MSDOS_DT_MINUTES_SHIFT) * 60
+ ((dt & MSDOS_DT_HOURS_MASK) >> MSDOS_DT_HOURS_SHIFT) * 3600;
/*
* If the year, month, and day from the last conversion are the
* same then use the saved value.
*/
if (lastdosdate != dd) {
lastdosdate = dd;
days = 0;
year = (dd & MSDOS_DD_YEAR_MASK) >> MSDOS_DD_YEAR_SHIFT;
for (y = 0; y < year; y++)
days += y & 0x03 ? 365 : 366;
months = year & 0x03 ? regyear : leapyear;
/*
* Prevent going from 0 to 0xffffffff in the following
* loop.
*/
month = (dd & MSDOS_DD_MONTH_MASK) >> MSDOS_DD_MONTH_SHIFT;
if (month == 0) {
month = 1;
}
for (m = 0; m < month - 1; m++)
days += months[m];
days += ((dd & MSDOS_DD_DAY_MASK) >> MSDOS_DD_DAY_SHIFT) - 1;
lastseconds = (days * 24 * 60 * 60) + SECONDSTO1980;
}
return seconds + lastseconds;
}
/*
* Cheezy macros to do case detection and conversion for the ascii
* character set. DOESN'T work for ebcdic.
*/
#define isupper(c) (c >= 'A' && c <= 'Z')
#define islower(c) (c >= 'a' && c <= 'z')
#define toupper(c) (c & ~' ')
#define tolower(c) (c | ' ')
static const u_char msdos_map[] = {
/* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 18 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 20 */ 0x00, 0x21, 0x00, 0x23, 0x24, 0x25, 0x26, 0x27, /* !"#$%&' */
/* 28 */ 0x28, 0x29, 0x00, 0x00, 0x00, 0x2D, 0x2E, 0x00, /* ()*+,-./ */
/* 30 */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 01234567 */
/* 38 */ 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 89:;<=>? */
/* 40 */ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* @ABCDEFG */
/* 48 */ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, /* HIJKLMNO */
/* 50 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* PQRSTUVW */
/* 58 */ 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x00, 0x5E, 0x5F, /* XYZ[\]^_ */
/* 60 */ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* `abcdefg */
/* 68 */ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, /* hijklmno */
/* 70 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* pqrstuvw */
/* 78 */ 0x58, 0x59, 0x5A, 0x5B, 0x7C, 0x00, 0x7E, 0x00, /* xyz{|}~ */
/* 80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 88 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 98 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* A0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* A8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* B0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* B8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* C0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* C8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* D0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* D8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* E0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* E8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* F0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* F8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
/*
* Convert a unix filename to a DOS filename. Return -1 if wrong name is
* supplied.
*/
int
msdos_filename_unix2dos(char *un, int unlen, char *dn)
{
int i;
u_char c;
/*
* Fill the dos filename string with blanks. These are DOS's pad
* characters.
*/
for (i = 0; i <= 10; i++)
dn[i] = ' ';
/*
* The filenames "." and ".." are handled specially, since they
* don't follow dos filename rules.
*/
if (un[0] == '.' && unlen == 1) {
dn[0] = '.';
return 0;
}
if (un[0] == '.' && un[1] == '.' && unlen == 2) {
dn[0] = '.';
dn[1] = '.';
return 0;
}
/*
* Copy the unix filename into the dos filename string upto the end
* of string, a '.', or 8 characters. Whichever happens first stops
* us. This forms the name portion of the dos filename. Fold to
* upper case.
*/
for (i = 0; i <= 7 && unlen && (c = *un) && c != '.'; i++) {
if ((dn[i] = msdos_map[c]) == 0)
return -1;
un++;
unlen--;
}
/*
* Strip any further characters up to a '.' or the end of the
* string.
*/
while (unlen && (c = *un)) {
un++;
unlen--;
/* Make sure we've skipped over the dot before stopping. */
if (c == '.')
break;
}
/*
* Copy in the extension part of the name, if any. Force to upper
* case. Note that the extension is allowed to contain '.'s.
* Filenames in this form are probably inaccessable under dos.
*/
for (i = 8; i <= 10 && unlen && (c = *un); i++) {
if ((dn[i] = msdos_map[c]) == 0)
return -1;
un++;
unlen--;
}
return 0;
}

View File

@@ -30,11 +30,10 @@
/* msdos_creat_node --
* Create a new node. If a new node is file, FAT 32 Bytes Directory
* Entry Structure (see M$ White Paper) is initialized, free space is
* found in parent directory and structure is written to the disk.
* In case of directory, all above steps present and also new cluster
* is allocated for a new directory and dot and dotdot nodes are created
* in alloceted cluster.
* Entry Structure is initialized, free space is found in parent
* directory and structure is written to the disk. In case of directory,
* all above steps present and also new cluster is allocated for a
* new directory and dot and dotdot nodes are created in alloceted cluster.
*
* PARAMETERS:
* parent_loc - parent (directory we are going to create node in)
@@ -94,8 +93,7 @@ msdos_creat_node(
/*
* find free space in the parent directory and write new initialized
* FAT 32 Bytes Directory Entry Structure (see M$ White Paper)
* to the disk
* FAT 32 Bytes Directory Entry Structure to the disk
*/
rc = msdos_get_name_node(parent_loc, NULL, &aux, new_node);
if ( rc != RC_OK )

View File

@@ -442,8 +442,8 @@ msdos_dir_stat(
/* msdos_dir_sync --
* The following routine does a syncronization on a MSDOS directory node.
* DIR_WrtTime, DIR_WrtDate and DIR_fileSize fields of 32 Bytes Directory
* Entry Structure(see M$ White Paper) should not be updated for
* directories, so only call to corresponding fat-file routine.
* Entry Structure should not be updated for directories, so only call
* to corresponding fat-file routine.
*
* PARAMETERS:
* iop - file control block

View File

@@ -28,151 +28,6 @@
#include "msdos.h"
/* This copied from Linux */
static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 };
/* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */
#undef CONFIG_ATARI
/* MS-DOS "device special files" */
static const char *reserved_names[] = {
#ifndef CONFIG_ATARI /* GEMDOS is less stupid */
"CON ","PRN ","NUL ","AUX ",
"LPT1 ","LPT2 ","LPT3 ","LPT4 ",
"COM1 ","COM2 ","COM3 ","COM4 ",
#endif
NULL };
static char bad_chars[] = "*?<>|\"";
#ifdef CONFIG_ATARI
/* GEMDOS is less restrictive */
static char bad_if_strict[] = " ";
#else
static char bad_if_strict[] = "+=,; ";
#endif
/* The following three functions copied from Linux */
/*
* Formats an MS-DOS file name. Rejects invalid names
*
* conv is relaxed/normal/strict, name is proposed name,
* len is the length of the proposed name, res is the result name,
* dotsOK is if hidden files get dots.
*/
int
msdos_format_name(char conv, const char *name, int len, char *res,
char dotsOK)
{
char *walk;
const char **reserved;
unsigned char c;
int space;
if (name[0] == '.') { /* dotfile because . and .. already done */
if (!dotsOK) return -EINVAL;
/* Get rid of dot - test for it elsewhere */
name++; len--;
}
#ifndef CONFIG_ATARI
space = 1; /* disallow names that _really_ start with a dot */
#else
space = 0; /* GEMDOS does not care */
#endif
c = 0;
for (walk = res; len && walk-res < 8; walk++) {
c = *name++;
len--;
if (conv != 'r' && strchr(bad_chars,c)) return -EINVAL;
if (conv == 's' && strchr(bad_if_strict,c)) return -EINVAL;
if (c >= 'A' && c <= 'Z' && conv == 's') return -EINVAL;
if (c < ' ' || c == ':' || c == '\\') return -EINVAL;
/* 0xE5 is legal as a first character, but we must substitute 0x05 */
/* because 0xE5 marks deleted files. Yes, DOS really does this. */
/* It seems that Microsoft hacked DOS to support non-US characters */
/* after the 0xE5 character was already in use to mark deleted files. */
if((res==walk) && (c==0xE5)) c=0x05;
if (c == '.') break;
space = (c == ' ');
*walk = (c >= 'a' && c <= 'z') ? c-32 : c;
}
if (space) return -EINVAL;
if (conv == 's' && len && c != '.') {
c = *name++;
len--;
if (c != '.') return -EINVAL;
}
while (c != '.' && len--) c = *name++;
if (c == '.') {
while (walk-res < 8) *walk++ = ' ';
while (len > 0 && walk-res < MSDOS_NAME_MAX) {
c = *name++;
len--;
if (conv != 'r' && strchr(bad_chars,c)) return -EINVAL;
if (conv == 's' && strchr(bad_if_strict,c))
return -EINVAL;
if (c < ' ' || c == ':' || c == '\\')
return -EINVAL;
if (c == '.') {
if (conv == 's')
return -EINVAL;
break;
}
if (c >= 'A' && c <= 'Z' && conv == 's') return -EINVAL;
space = c == ' ';
*walk++ = c >= 'a' && c <= 'z' ? c-32 : c;
}
if (space) return -EINVAL;
if (conv == 's' && len) return -EINVAL;
}
while (walk-res < MSDOS_NAME_MAX) *walk++ = ' ';
for (reserved = reserved_names; *reserved; reserved++)
if (!strncmp(res,*reserved,8)) return -EINVAL;
return 0;
}
/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70) */
unsigned int
msdos_date_dos2unix(unsigned short time_val,unsigned short date)
{
int month,year,secs;
month = ((date >> 5) & 15)-1;
year = date >> 9;
secs = (time_val & 31)*2+60*((time_val >> 5) & 63)+
(time_val >> 11)*3600+86400*
((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
month < 2 ? 1 : 0)+3653);
/* days since 1.1.70 plus 80's leap day */
return secs;
}
/* Convert linear UNIX date to a MS-DOS time/date pair */
void msdos_date_unix2dos(int unix_date,
unsigned short *time_val,
unsigned short *date)
{
int day,year,nl_day,month;
*time_val = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+
(((unix_date/3600) % 24) << 11);
day = unix_date/86400-3652;
year = day/365;
if ((year+3)/4+365*year > day) year--;
day -= (year+3)/4+365*year;
if (day == 59 && !(year & 3)) {
nl_day = day;
month = 2;
}
else {
nl_day = (year & 3) || day <= 59 ? day : day-1;
for (month = 0; month < 12; month++)
if (day_n[month] > nl_day) break;
}
*date = nl_day-day_n[month-1]+1+(month << 5)+(year << 9);
}
/* msdos_get_token --
* Routine to get a token (name or separator) from the path.
*
@@ -250,7 +105,7 @@ msdos_get_token(const char *path, char *ret_token, int *token_len)
return type;
}
rc = msdos_format_name('r', token, *token_len, ret_token, 0);
rc = msdos_filename_unix2dos(token, *token_len, ret_token);
if ( rc != RC_OK )
return MSDOS_INVALID_TOKEN;
}