fat_dentry.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008 Jakub Jermar
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00038 #include "fat_dentry.h"
00039 #include <ctype.h>
00040 #include <str.h>
00041 
00042 static bool is_d_char(const char ch)
00043 {
00044         if (isalnum(ch) || ch == '_' || ch == '-')
00045                 return true;
00046         else
00047                 return false;
00048 }
00049 
00062 int fat_dentry_namecmp(char *name, const char *component)
00063 {
00064         int rc;
00065         size_t size;
00066 
00067         if (!(rc = stricmp(name, component)))
00068                 return rc;
00069         if (!str_chr(name, '.')) {
00070                 /*
00071                  * There is no '.' in the name, so we know that there is enough
00072                  * space for appending an extra '.' to name.
00073                  */
00074                 size = str_size(name);
00075                 name[size] = '.';
00076                 name[size + 1] = '\0';
00077                 rc = stricmp(name, component);
00078         }
00079         return rc;
00080 }
00081 
00082 bool fat_dentry_name_verify(const char *name)
00083 {
00084         unsigned int i;
00085         unsigned int dot = 0;
00086         bool dot_found = false;
00087         
00088 
00089         for (i = 0; name[i]; i++) {
00090                 if (name[i] == '.') {
00091                         if (dot_found) {
00092                                 return false;
00093                         } else {
00094                                 dot_found = true;
00095                                 dot = i;
00096                         }
00097                 } else {
00098                         if (!is_d_char(name[i]))
00099                                 return false;
00100                 }
00101         }
00102 
00103         if (dot_found) {
00104                 if (dot > FAT_NAME_LEN)
00105                         return false;
00106                 if (i - dot > FAT_EXT_LEN + 1)
00107                         return false;
00108         } else {
00109                 if (i > FAT_NAME_LEN)
00110                         return false;
00111         }
00112 
00113         return true;
00114 }
00115 
00116 void fat_dentry_name_get(const fat_dentry_t *d, char *buf)
00117 {
00118         unsigned int i;
00119         
00120         for (i = 0; i < FAT_NAME_LEN; i++) {
00121                 if (d->name[i] == FAT_PAD)
00122                         break;
00123                 
00124                 if (d->name[i] == FAT_DENTRY_E5_ESC)
00125                         *buf++ = 0xe5;
00126                 else {
00127                         if (d->lcase & FAT_LCASE_LOWER_NAME)
00128                                 *buf++ = tolower(d->name[i]);
00129                         else
00130                                 *buf++ = d->name[i];
00131                 }
00132         }
00133         
00134         if (d->ext[0] != FAT_PAD)
00135                 *buf++ = '.';
00136         
00137         for (i = 0; i < FAT_EXT_LEN; i++) {
00138                 if (d->ext[i] == FAT_PAD) {
00139                         *buf = '\0';
00140                         return;
00141                 }
00142                 
00143                 if (d->ext[i] == FAT_DENTRY_E5_ESC)
00144                         *buf++ = 0xe5;
00145                 else {
00146                         if (d->lcase & FAT_LCASE_LOWER_EXT)
00147                                 *buf++ = tolower(d->ext[i]);
00148                         else
00149                                 *buf++ = d->ext[i];
00150                 }
00151         }
00152         
00153         *buf = '\0';
00154 }
00155 
00156 void fat_dentry_name_set(fat_dentry_t *d, const char *name)
00157 {
00158         unsigned int i;
00159         const char fake_ext[] = "   ";
00160         bool lower_name = true;
00161         bool lower_ext = true;
00162         
00163         for (i = 0; i < FAT_NAME_LEN; i++) {
00164                 switch ((uint8_t) *name) {
00165                 case 0xe5:
00166                         d->name[i] = FAT_DENTRY_E5_ESC;
00167                         name++;
00168                         break;
00169                 case '\0':
00170                 case '.':
00171                         d->name[i] = FAT_PAD;
00172                         break;
00173                 default:
00174                         if (isalpha(*name)) {
00175                                 if (!islower(*name))
00176                                         lower_name = false;
00177                         }
00178                         
00179                         d->name[i] = toupper(*name++);
00180                         break;
00181                 }
00182         }
00183         
00184         if (*name++ != '.')
00185                 name = fake_ext;
00186         
00187         for (i = 0; i < FAT_EXT_LEN; i++) {
00188                 switch ((uint8_t) *name) {
00189                 case 0xe5:
00190                         d->ext[i] = FAT_DENTRY_E5_ESC;
00191                         name++;
00192                         break;
00193                 case '\0':
00194                         d->ext[i] = FAT_PAD;
00195                         break;
00196                 default:
00197                         if (isalpha(*name)) {
00198                                 if (!islower(*name))
00199                                         lower_ext = false;
00200                         }
00201                         
00202                         d->ext[i] = toupper(*name++);
00203                         break;
00204                 }
00205         }
00206         
00207         if (lower_name)
00208                 d->lcase |= FAT_LCASE_LOWER_NAME;
00209         else
00210                 d->lcase &= ~FAT_LCASE_LOWER_NAME;
00211         
00212         if (lower_ext)
00213                 d->lcase |= FAT_LCASE_LOWER_EXT;
00214         else
00215                 d->lcase &= ~FAT_LCASE_LOWER_EXT;
00216 }
00217 
00218 fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d)
00219 {
00220         if (d->attr & FAT_ATTR_VOLLABEL) {
00221                 /* volume label entry */
00222                 return FAT_DENTRY_SKIP;
00223         }
00224         if (d->name[0] == FAT_DENTRY_ERASED) {
00225                 /* not-currently-used entry */
00226                 return FAT_DENTRY_FREE;
00227         }
00228         if (d->name[0] == FAT_DENTRY_UNUSED) {
00229                 /* never used entry */
00230                 return FAT_DENTRY_LAST;
00231         }
00232         if (d->name[0] == FAT_DENTRY_DOT) {
00233                 /*
00234                  * Most likely '.' or '..'.
00235                  * It cannot occur in a regular file name.
00236                  */
00237                 return FAT_DENTRY_SKIP;
00238         }
00239         return FAT_DENTRY_VALID;
00240 }
00241 

Generated on Thu Jun 2 07:45:49 2011 for HelenOS/USB by  doxygen 1.4.7