[U-Boot] [PATCH v2] FAT: Add FAT write feature
Mike Frysinger
vapier at gentoo.org
Thu Oct 27 00:45:13 CEST 2011
On Tue, Oct 25, 2011 at 09:15, Donggeun Kim wrote:
> In some cases, saving data in RAM as a file with FAT format is required.
> This patch allows the file to be written in FAT formatted partition.
i thought Wolfgang NAK-ed FS write patches in the past ...
> --- a/fs/fat/Makefile
> +++ b/fs/fat/Makefile
>
> COBJS-$(CONFIG_CMD_FAT) := fat.o
> +COBJS-$(CONFIG_FAT_WRITE):= fat_write.o
missing whitespace before that ":="
> --- /dev/null
> +++ b/fs/fat/fat_write.c
>
> +/*
> + * fat_write.c
> + *
> + * R/W (V)FAT 12/16/32 filesystem implementation by Donggeun Kim
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
there's no actual copyright here. you wrote this all from scratch ?
> +static void set_name(dir_entry *dirent, const char *filename)
> +{
> + int period_location, len, i, ext_num;
> +
> + len = strlen(filename);
i/period_location/len should be size_t, not int
> + memcpy(s_name, filename, len);
> + uppercase(s_name, len);
you use this uppercase() func exactly once, and do a memcpy right
before. drop the memcpy, and inline the uppercase func and use the
proper toupper helper from linux/ctype.h
> + /* Pad spaces when the length of file name is shorter than eight */
> + if (period_location < 8) {
> + memcpy(dirent->name, s_name, period_location);
> + for (i = period_location; i < 8; i++)
> + dirent->name[i] = ' ';
> + } else if (period_location == 8) {
> + memcpy(dirent->name, s_name, period_location);
> + } else {
> + memcpy(dirent->name, s_name, 6);
> + dirent->name[6] = '~';
> + dirent->name[7] = '1';
> + }
err, doesn't this "~1" hardcode assume that there is no "~1" file
already existing ? and if there happens to be, you blow it
away/corrupt the fs ?
> +static __u32 get_fatent_value(fsdata *mydata, __u32 entry)
> +{
> + /* Get the actual entry from the table */
> + switch (mydata->fatsize) {
> + case 32:
> + ret = FAT2CPU32(((__u32 *) mydata->fatbuf)[offset]);
> + break;
> + case 16:
> + ret = FAT2CPU16(((__u16 *) mydata->fatbuf)[offset]);
ugh, whoever dreamt up these FAT2CPU* macros should get smacked.
these need to get scrubbed from fat.h and all code in u-boot and
replaced with proper get/put unaligned macros from include/linux/.
> +static int is_next_clust(fsdata *mydata, dir_entry *dentptr);
> +static void flush_dir_table(fsdata *mydata, dir_entry **dentptr);
re-order these tiny funcs in the file to avoid having to use prototypes
> +/*
> + * Fill dir_slot entries with appropriate name, id, and attr
> + * The real directory entry is returned by 'dentptr'
> + */
> +static void
> +fill_dir_slot(fsdata *mydata, dir_entry **dentptr, const char *l_name)
> +{
> + dir_slot *slotptr = (dir_slot *)get_vfatname_block;
> + __u8 counter, checksum;
> + int idx = 0, ret;
> + char s_name[16];
> +
> + /* Get short file name and checksum value */
> + strncpy(s_name, (*dentptr)->name, 16);
> + checksum = mkcksum(s_name);
> +
> + do {
> + memset(slotptr, 0x00, sizeof(dir_slot));
> + ret = str2slot(slotptr, l_name, &idx);
> + slotptr->id = ++counter;
> + slotptr->attr = ATTR_VFAT;
> + slotptr->alias_checksum = checksum;
> + slotptr++;
> + } while (ret == 0);
> +
> + slotptr--;
> + slotptr->id |= LAST_LONG_ENTRY_MASK;
> +
> + while (counter >= 1) {
> + if (is_next_clust(mydata, *dentptr)) {
> + /* A new cluster is allocated for directory table */
> + flush_dir_table(mydata, dentptr);
> + }
> + memcpy(*dentptr, slotptr, sizeof(dir_slot));
> + (*dentptr)++;
> + slotptr--;
> + counter--;
> + }
> +
> + if (is_next_clust(mydata, *dentptr)) {
> + /* A new cluster is allocated for directory table */
> + flush_dir_table(mydata, dentptr);
> + }
> +}
> +
> +static __u32 dir_curclust;
all these global variables make me cry. i guess it's a good thing
u-boot is single threaded.
> +static int set_fatent_value(fsdata *mydata, __u32 entry, __u32 entry_value)
> +{
> ...
> + /* Set the actual entry */
> + switch (mydata->fatsize) {
> + case 32:
> + ((__u32 *) mydata->fatbuf)[offset] = cpu_to_le32(entry_value);
> + break;
> + case 16:
> + ((__u16 *) mydata->fatbuf)[offset] = cpu_to_le16(entry_value);
use proper put_unaligned helpers from include/linux/
> +static int is_next_clust(fsdata *mydata, dir_entry *dentptr)
> +{
> ...
> + cur_position = (__u8 *)dentptr - get_dentfromdir_block;
you've got a lot of random casts throughout this file. makes me
really wonder as to its sanity.
> + printf("Error: flush fat buffer\n");
all of these printf() calls without any format args should be puts() instead
> --- a/include/fat.h
> +++ b/include/fat.h
>
> #define TOLOWER(c) if((c) >= 'A' && (c) <= 'Z'){(c)+=('a' - 'A');}
> +#define TOUPPER(c) if ((c) >= 'a' && (c) <= 'z') \
> + (c) -= ('a' - 'A');
why do these exist ? we already have tolower/toupper in
linux/ctype.h, and macros shouldn't be embedding ugly if/assignments.
-mike
More information about the U-Boot
mailing list