⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 msdos_misc.c

📁 DOS/Windows FAT 文件系统实现源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  Miscellaneous routines implementation for MSDOS filesystem * *  Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia *  Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru> * *  The license and distribution terms for this file may be *  found in the file LICENSE in this distribution or at *  http://www.OARcorp.com/rtems/license.html. * *  @(#) $Id: msdos_misc.c,v 1.20 2002/02/11 16:42:14 jack Exp $ */#if HAVE_CONFIG_H#include "config.h"#endif#include <stdlib.h>#include <sys/time.h>#include <unistd.h>#include <rtems/libio_.h>#include "fat.h"#include "fat_fat_operations.h"#include "fat_file.h"#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[] = " ";#elsestatic 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. * * PARAMETERS: *     path      - path to get token from *     ret_token - returned token *     token_len - length of returned token * * RETURNS: *     token type, token and token length  * */msdos_token_types_t msdos_get_token(const char *path, char *ret_token, int *token_len){    int                 rc = RC_OK;    register int        i = 0;    msdos_token_types_t type = MSDOS_NAME;    char                token[MSDOS_NAME_MAX_WITH_DOT+1];      register char       c;    /*      *  Copy a name into token.  (Remember NULL is a token.)     */    c = path[i];    while ( (!msdos_is_separator(c)) && (i <= MSDOS_NAME_MAX_WITH_DOT) )     {        token[i] = c;        if ( i == MSDOS_NAME_MAX_WITH_DOT )            return MSDOS_INVALID_TOKEN;        if ( !msdos_is_valid_name_char(c) )            return MSDOS_INVALID_TOKEN;           c = path [++i];    }    /*     *  Copy a seperator into token.     */    if ( i == 0 )     {        token[i] = c;        if ( token[i] != '\0' )         {            i++;            type = MSDOS_CURRENT_DIR;        }         else              type = MSDOS_NO_MORE_PATH;    }     else if (token[ i-1 ] != '\0')         token[i] = '\0';    /*     *  Set token_len to the number of characters copied.     */    *token_len = i;    /*     *  If we copied something that was not a seperator see if     *  it was a special name.     */    if ( type == MSDOS_NAME )     {        if ( strcmp( token, "..") == 0 )        {            strcpy(ret_token, MSDOS_DOTDOT_NAME);            type = MSDOS_UP_DIR;            return type;        }          if ( strcmp( token, "." ) == 0 )        {            strcpy(ret_token, MSDOS_DOT_NAME);            type = MSDOS_CURRENT_DIR;            return type;                }        rc = msdos_format_name('r', token, *token_len, ret_token, 0);        if ( rc != RC_OK )            return MSDOS_INVALID_TOKEN;         }    ret_token[MSDOS_NAME_MAX] = '\0';    return type;}/* msdos_find_name -- *     Find the node which correspondes to the name, open fat-file which  *     correspondes to the found node and close fat-file which correspondes  *     to the node we searched in. * * PARAMETERS: *     parent_loc - parent node description *     name       - name to find * * RETURNS: *     RC_OK and updated 'parent_loc' on success, or -1 if error  *     occured (errno set apropriately) * */int msdos_find_name(    rtems_filesystem_location_info_t *parent_loc,    char                             *name    ){    int              rc = RC_OK;    msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info;    fat_file_fd_t   *fat_fd = NULL;    fat_auxiliary_t  aux;    unsigned short   time_val = 0;    unsigned short   date = 0;    unsigned char    node_entry[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];      memset(node_entry, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);      /*      * find the node which correspondes to the name in the directory pointed by      * 'parent_loc'     */    rc = msdos_get_name_node(parent_loc, name, &aux, node_entry);    if (rc != RC_OK)        return rc;    /* open fat-file corresponded to the found node */    rc = fat_file_open(parent_loc->mt_entry, aux.cln, aux.ofs, &fat_fd);    if (rc != RC_OK)        return rc;      /*     * I don't like this if, but: we should do it , or should write new file      * size and first cluster num to the disk after each write operation      * (even if one byte is written  - that is TOO non-optimize) because      * otherwise real values of these fields stored in fat-file descriptor      * may be accidentely rewritten with wrong values stored on the disk     */    if (fat_fd->links_num == 1)    {        fat_fd->info_cln = aux.cln;        fat_fd->info_ofs = aux.ofs;        fat_fd->cln = MSDOS_EXTRACT_CLUSTER_NUM(node_entry);        fat_fd->first_char = *MSDOS_DIR_NAME(node_entry);            time_val = *MSDOS_DIR_WRITE_TIME(node_entry);        date = *MSDOS_DIR_WRITE_DATE(node_entry);            fat_fd->mtime = msdos_date_dos2unix(CF_LE_W(time_val), CF_LE_W(date));         if ((*MSDOS_DIR_ATTR(node_entry)) & MSDOS_ATTR_DIRECTORY)        {            fat_fd->fat_file_type = FAT_DIRECTORY;            fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;                                                  rc = fat_file_size(parent_loc->mt_entry, fat_fd);            if (rc != RC_OK)            {                fat_file_close(parent_loc->mt_entry, fat_fd);                return rc;            }        }        else        {            fat_fd->fat_file_size = CF_LE_L(*MSDOS_DIR_FILE_SIZE(node_entry));             fat_fd->fat_file_type = FAT_FILE;                                                fat_fd->size_limit = MSDOS_MAX_FILE_SIZE;        }                /* these data is not actual for zero-length fat-file */        fat_fd->map.file_cln = 0;        fat_fd->map.disk_cln = fat_fd->cln;                if ((fat_fd->fat_file_size != 0) &&             (fat_fd->fat_file_size <= fs_info->fat.vol.bpc))        {            fat_fd->map.last_cln = fat_fd->cln;        }        else        {            fat_fd->map.last_cln = FAT_UNDEFINED_VALUE;        }    }      /* close fat-file corresponded to the node we searched in */    rc = fat_file_close(parent_loc->mt_entry, parent_loc->node_access);    if (rc != RC_OK)    {        fat_file_close(parent_loc->mt_entry, fat_fd);        return rc;    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -