kernels/linux-2.4.0/fs/vfat/namei.c
/* Given a valid longname, create a unique shortname.  Make sure the
 * shortname does not exist
 */
Given a valid longname, create a unique shortname.  Make sure the
shortname does not exist
Given a valid longname create a unique shortname . Make sure the shortname does not exist
static int vfat_create_shortname(struct inode *dir, struct nls_table *nls,
					wchar_t *name, int len,
					char *name_res)
{
	wchar_t *ip, *op, *ext_start, *end, *name_start;
	wchar_t msdos_name[13];
	char base[9], ext[4], buf[8], *p;
	unsigned char charbuf[NLS_MAX_CHARSET_SIZE];
	int chl, chi;
	int sz, extlen, baselen, i;
	PRINTK2(("Entering vfat_create_shortname\n"));
	chl = 0;
	sz = 0;			
	if (len <= 12) {
		for (i = 0, op = &msdos_name[0], ip = name; ; i++, ip++, op++) {
			if (i == len) {
				if (vfat_format_name(nls, &msdos_name[0], len,
							name_res) < 0)
					break;
				PRINTK3(("vfat_create_shortname 1\n"));
				if (vfat_find_form(dir, name_res) < 0)
					return 0;
				return -EEXIST;
			}
			chl = vfat_uni2upper_short(nls, *ip, charbuf, NLS_MAX_CHARSET_SIZE);
			for (chi = 0; chi < chl; chi++){
				if (charbuf[chi] == ' ')
					break;
			}
			if (chi < chl)
				break;
			*op = *ip;
		}
	}
	PRINTK3(("vfat_create_shortname 3\n"));
	ext_start = end = &name[len];
	while (--ext_start >= name) {
		chl = vfat_uni2upper_short(nls, *ext_start, charbuf, NLS_MAX_CHARSET_SIZE);
		for (chi = 0; chi < chl; chi++) {
			if (charbuf[chi] == '.') {
				if (ext_start == end - 1) {
					sz = len;
					ext_start = NULL;
				}
				goto stop0;
			}
		}
	}
stop0:;	
	if (ext_start == name - 1) {
		sz = len;
		ext_start = NULL;
	} else if (ext_start) {
		name_start = &name[0];
		while (name_start < ext_start)
		{
			chl = vfat_uni2upper_short(nls, *name_start, charbuf, NLS_MAX_CHARSET_SIZE);
			if (chl == 0)
				break;
			for (chi = 0; chi < chl; chi++)
				if (!strchr(skip_chars, charbuf[chi])) {
					goto stop1;
				}
			name_start++;
		}
stop1:;		
		if (name_start != ext_start) {
			sz = ext_start - name;
			ext_start++;
		} else {
			sz = len;
			ext_start=NULL;
		}
	}
	for (baselen = i = 0, p = base, ip = name; i < sz && baselen < 8; i++, ip++)
	{
		chl = vfat_uni2upper_short(nls, *ip, charbuf, NLS_MAX_CHARSET_SIZE);
		if (chl == 0){
			*p++ = '_';
			baselen++;
			continue;
		}
		for (chi = 0; chi < chl; chi++){
			if (!strchr(skip_chars, charbuf[chi])){
				if (strchr(replace_chars, charbuf[chi]))
					*p = '_';
				else
					*p = charbuf[chi];
				p++; baselen++;
			}
		}
	}
	if (baselen == 0) {
		return -EINVAL;
	}
	extlen = 0;
	if (ext_start) {
		for (p = ext, ip = ext_start; extlen < 3 && ip < end; ip++) {
			chl = vfat_uni2upper_short(nls, *ip, charbuf, NLS_MAX_CHARSET_SIZE);
			if (chl == 0) {
				*p++ = '_';
				extlen++;
				continue;
			}
			for (chi = 0; chi < chl; chi++) {
				if (!strchr(skip_chars, charbuf[chi])) {
					if (strchr(replace_chars, charbuf[chi]))
						*p = '_';
					else
						*p = charbuf[chi];
					p++; extlen++;
				}
			}
		}
	}
	ext[extlen] = '\0';
	base[baselen] = '\0';
	if (IS_FREE(base))
		base[0]='_';
	memset(name_res, ' ', MSDOS_NAME);
	memcpy(name_res,base,baselen);
	memcpy(name_res+8,ext,extlen);
	if (MSDOS_SB(dir->i_sb)->options.numtail == 0)
		if (vfat_find_form(dir, name_res) < 0)
			return 0;
	if (baselen>6)
		baselen = 6;
	name_res[baselen] = '~';
	for (i = 1; i < 10; i++) {
		name_res[baselen+1] = i + '0';
		if (vfat_find_form(dir, name_res) < 0)
			return 0;
	}
	i = jiffies & 0xffff;
	sz = (jiffies >> 16) & 0x7;
	if (baselen>2)
		baselen = 2;
	name_res[baselen+4] = '~';
	name_res[baselen+5] = '1' + sz;
	while (1) {
		sprintf(buf, "%04X", i);
		memcpy(&name_res[baselen], buf, 4);
		if (vfat_find_form(dir, name_res) < 0)
			break;
		i -= 11;
	}
	return 0;
}
static int vfat_create_shortname ( struct inode * dir , struct nls_table * nls , wchar_t * name , int len , char * name_res ) { wchar_t * ip , * op , * ext_start , * end , * name_start ; wchar_t msdos_name [ 13 ] ; char base [ 9 ] , ext [ 4 ] , buf [ 8 ] , * p ; unsigned char charbuf [ NLS_MAX_CHARSET_SIZE ] ; int chl , chi ; int sz , extlen , baselen , i ; PRINTK2 ( ( " \n " ) ) ; chl = 0 ; sz = 0 ; if ( len <= 12 ) { for ( i = 0 , op = & msdos_name [ 0 ] , ip = name ; ; i ++ , ip ++ , op ++ ) { if ( i == len ) { if ( vfat_format_name ( nls , & msdos_name [ 0 ] , len , name_res ) < 0 ) break ; PRINTK3 ( ( " \n " ) ) ; if ( vfat_find_form ( dir , name_res ) < 0 ) return 0 ; return - EEXIST ; } chl = vfat_uni2upper_short ( nls , * ip , charbuf , NLS_MAX_CHARSET_SIZE ) ; for ( chi = 0 ; chi < chl ; chi ++ ) { if ( charbuf [ chi ] == ' ' ) break ; } if ( chi < chl ) break ; * op = * ip ; } } PRINTK3 ( ( " \n " ) ) ; ext_start = end = & name [ len ] ; while ( -- ext_start >= name ) { chl = vfat_uni2upper_short ( nls , * ext_start , charbuf , NLS_MAX_CHARSET_SIZE ) ; for ( chi = 0 ; chi < chl ; chi ++ ) { if ( charbuf [ chi ] == ' ' ) { if ( ext_start == end - 1 ) { sz = len ; ext_start = NULL ; } goto stop0 ; } } } stop0 : ; if ( ext_start == name - 1 ) { sz = len ; ext_start = NULL ; } else if ( ext_start ) { name_start = & name [ 0 ] ; while ( name_start < ext_start ) { chl = vfat_uni2upper_short ( nls , * name_start , charbuf , NLS_MAX_CHARSET_SIZE ) ; if ( chl == 0 ) break ; for ( chi = 0 ; chi < chl ; chi ++ ) if ( ! strchr ( skip_chars , charbuf [ chi ] ) ) { goto stop1 ; } name_start ++ ; } stop1 : ; if ( name_start != ext_start ) { sz = ext_start - name ; ext_start ++ ; } else { sz = len ; ext_start = NULL ; } } for ( baselen = i = 0 , p = base , ip = name ; i < sz && baselen < 8 ; i ++ , ip ++ ) { chl = vfat_uni2upper_short ( nls , * ip , charbuf , NLS_MAX_CHARSET_SIZE ) ; if ( chl == 0 ) { * p ++ = ' ' ; baselen ++ ; continue ; } for ( chi = 0 ; chi < chl ; chi ++ ) { if ( ! strchr ( skip_chars , charbuf [ chi ] ) ) { if ( strchr ( replace_chars , charbuf [ chi ] ) ) * p = ' ' ; else * p = charbuf [ chi ] ; p ++ ; baselen ++ ; } } } if ( baselen == 0 ) { return - EINVAL ; } extlen = 0 ; if ( ext_start ) { for ( p = ext , ip = ext_start ; extlen < 3 && ip < end ; ip ++ ) { chl = vfat_uni2upper_short ( nls , * ip , charbuf , NLS_MAX_CHARSET_SIZE ) ; if ( chl == 0 ) { * p ++ = ' ' ; extlen ++ ; continue ; } for ( chi = 0 ; chi < chl ; chi ++ ) { if ( ! strchr ( skip_chars , charbuf [ chi ] ) ) { if ( strchr ( replace_chars , charbuf [ chi ] ) ) * p = ' ' ; else * p = charbuf [ chi ] ; p ++ ; extlen ++ ; } } } } ext [ extlen ] = ' \0 ' ; base [ baselen ] = ' \0 ' ; if ( IS_FREE ( base ) ) base [ 0 ] = ' ' ; memset ( name_res , ' ' , MSDOS_NAME ) ; memcpy ( name_res , base , baselen ) ; memcpy ( name_res + 8 , ext , extlen ) ; if ( MSDOS_SB ( dir -> i_sb ) -> options . numtail == 0 ) if ( vfat_find_form ( dir , name_res ) < 0 ) return 0 ; if ( baselen > 6 ) baselen = 6 ; name_res [ baselen ] = ' ' ; for ( i = 1 ; i < 10 ; i ++ ) { name_res [ baselen + 1 ] = i + ' ' ; if ( vfat_find_form ( dir , name_res ) < 0 ) return 0 ; } i = jiffies & 0xffff ; sz = ( jiffies >> 16 ) & 0x7 ; if ( baselen > 2 ) baselen = 2 ; name_res [ baselen + 4 ] = ' ' ; name_res [ baselen + 5 ] = ' ' + sz ; while ( 1 ) { sprintf ( buf , " " , i ) ; memcpy ( & name_res [ baselen ] , buf , 4 ) ; if ( vfat_find_form ( dir , name_res ) < 0 ) break ; i -= 11 ; } return 0 ; }
Given a valid longname, create a unique shortname.
Given a valid longname create a unique shortname .
/* Make compiler happy */ /* Do a case insensitive search if the name would be a valid
		 * shortname if is were all capitalized.  However, do not
		 * allow spaces in short names because Win95 scandisk does
		 * not like that */ /* Now, we need to create a shortname from the long name */ /*
		 * Names which start with a dot could be just
		 * an extension eg. "...test".  In this case Win95
		 * uses the extension as the name and sets no extension.
		 */ /* Yes, it can happen. ".\xe5" would do it. */ /* OK, at this point we know that base is not longer than 8 symbols,
	 * ext is not longer than 3, base is nonempty, both don't contain
	 * any bad symbols (lowercase transformed to uppercase).
	 */ /*
	 * Try to find a unique extension.  This used to
	 * iterate through all possibilities sequentially,
	 * but that gave extremely bad performance.  Windows
	 * only tries a few cases before using random
	 * values for part of the base.
	 */