All of lore.kernel.org
 help / color / mirror / Atom feed
From: AKASHI Takahiro <takahiro.akashi@linaro.org>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 07/17] fs: fat: support write with sub-directory path
Date: Fri, 20 Jul 2018 11:57:13 +0900	[thread overview]
Message-ID: <20180720025723.6736-8-takahiro.akashi@linaro.org> (raw)
In-Reply-To: <20180720025723.6736-1-takahiro.akashi@linaro.org>

In this patch, write implementation is overhauled and rewritten by
making full use of directory iterator. The ovbious bonus is that we are
now able to write to a file with a directory path, like /A/B/C/FILE.

Please note that, as there is no notion of "current directory" on u-boot,
a file name specified must contain an absolute directory path. Otherwise,
"/" (root directory) is assumed.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 fs/fat/fat.c       |   9 -
 fs/fat/fat_write.c | 469 +++++++++++++++------------------------------
 2 files changed, 157 insertions(+), 321 deletions(-)

diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index d9bfb08d97..9bafc3a40c 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -464,15 +464,6 @@ static __u8 mkcksum(const char name[8], const char ext[3])
 	return ret;
 }
 
-/*
- * TODO these should go away once fat_write is reworked to use the
- * directory iterator
- */
-__u8 get_dentfromdir_block[MAX_CLUSTSIZE]
-	__aligned(ARCH_DMA_MINALIGN);
-__u8 do_fat_read_at_block[MAX_CLUSTSIZE]
-	__aligned(ARCH_DMA_MINALIGN);
-
 /*
  * Read boot sector and volume info from a FAT filesystem
  */
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
index 1e4f5af910..96edb6674c 100644
--- a/fs/fat/fat_write.c
+++ b/fs/fat/fat_write.c
@@ -99,7 +99,6 @@ static void set_name(dir_entry *dirent, const char *filename)
 	debug("ext : %s\n", dirent->ext);
 }
 
-static __u8 num_of_fats;
 /*
  * Write fat buffer into block device
  */
@@ -128,7 +127,7 @@ static int flush_dirty_fat_buffer(fsdata *mydata)
 		return -1;
 	}
 
-	if (num_of_fats == 2) {
+	if (mydata->bs_fats == 2) {
 		/* Update corresponding second FAT blocks */
 		startblock += mydata->fatlength;
 		if (disk_write(startblock, getsize, bufptr) < 0) {
@@ -210,15 +209,14 @@ name11_12:
 	return 1;
 }
 
-static int is_next_clust(fsdata *mydata, dir_entry *dentptr);
-static void flush_dir_table(fsdata *mydata, dir_entry **dentptr);
+static int flush_dir_table(fat_itr *itr);
 
 /*
  * Fill dir_slot entries with appropriate name, id, and attr
- * The real directory entry is returned by 'dentptr'
+ * 'itr' will point to a next entry
  */
-static void
-fill_dir_slot(fsdata *mydata, dir_entry **dentptr, const char *l_name)
+static int
+fill_dir_slot(fat_itr *itr, const char *l_name)
 {
 	__u8 temp_dir_slot_buffer[MAX_LFN_SLOT * sizeof(dir_slot)];
 	dir_slot *slotptr = (dir_slot *)temp_dir_slot_buffer;
@@ -226,7 +224,7 @@ fill_dir_slot(fsdata *mydata, dir_entry **dentptr, const char *l_name)
 	int idx = 0, ret;
 
 	/* Get short file name checksum value */
-	checksum = mkcksum((*dentptr)->name, (*dentptr)->ext);
+	checksum = mkcksum(itr->dent->name, itr->dent->ext);
 
 	do {
 		memset(slotptr, 0x00, sizeof(dir_slot));
@@ -241,120 +239,21 @@ fill_dir_slot(fsdata *mydata, dir_entry **dentptr, const char *l_name)
 	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)++;
+		memcpy(itr->dent, slotptr, sizeof(dir_slot));
 		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;
-
-/*
- * Extract the full long filename starting at 'retdent' (which is really
- * a slot) into 'l_name'. If successful also copy the real directory entry
- * into 'retdent'
- * If additional adjacent cluster for directory entries is read into memory,
- * then 'get_contents_vfatname_block' is copied into 'get_dentfromdir_block' and
- * the location of the real directory entry is returned by 'retdent'
- * Return 0 on success, -1 otherwise.
- */
-static int
-get_long_file_name(fsdata *mydata, int curclust, __u8 *cluster,
-	      dir_entry **retdent, char *l_name)
-{
-	dir_entry *realdent;
-	dir_slot *slotptr = (dir_slot *)(*retdent);
-	dir_slot *slotptr2 = NULL;
-	__u8 *buflimit = cluster + mydata->sect_size * ((curclust == 0) ?
-							PREFETCH_BLOCKS :
-							mydata->clust_size);
-	__u8 counter = (slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff;
-	int idx = 0, cur_position = 0;
-
-	if (counter > VFAT_MAXSEQ) {
-		debug("Error: VFAT name is too long\n");
-		return -1;
-	}
-
-	while ((__u8 *)slotptr < buflimit) {
-		if (counter == 0)
-			break;
-		if (((slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff) != counter)
-			return -1;
-		slotptr++;
-		counter--;
-	}
-
-	if ((__u8 *)slotptr >= buflimit) {
-		if (curclust == 0)
-			return -1;
-		curclust = get_fatent(mydata, dir_curclust);
-		if (CHECK_CLUST(curclust, mydata->fatsize)) {
-			debug("curclust: 0x%x\n", curclust);
-			printf("Invalid FAT entry\n");
-			return -1;
-		}
-
-		dir_curclust = curclust;
-
-		if (get_cluster(mydata, curclust, get_contents_vfatname_block,
-				mydata->clust_size * mydata->sect_size) != 0) {
-			debug("Error: reading directory block\n");
-			return -1;
-		}
-
-		slotptr2 = (dir_slot *)get_contents_vfatname_block;
-		while (counter > 0) {
-			if (((slotptr2->id & ~LAST_LONG_ENTRY_MASK)
-			    & 0xff) != counter)
+		if (!fat_itr_next(itr))
+			if (!itr->dent && !itr->is_root && flush_dir_table(itr))
 				return -1;
-			slotptr2++;
-			counter--;
-		}
-
-		/* Save the real directory entry */
-		realdent = (dir_entry *)slotptr2;
-		while ((__u8 *)slotptr2 > get_contents_vfatname_block) {
-			slotptr2--;
-			slot2str(slotptr2, l_name, &idx);
-		}
-	} else {
-		/* Save the real directory entry */
-		realdent = (dir_entry *)slotptr;
 	}
 
-	do {
-		slotptr--;
-		if (slot2str(slotptr, l_name, &idx))
-			break;
-	} while (!(slotptr->id & LAST_LONG_ENTRY_MASK));
-
-	l_name[idx] = '\0';
-	if (*l_name == DELETED_FLAG)
-		*l_name = '\0';
-	else if (*l_name == aRING)
-		*l_name = DELETED_FLAG;
-	downcase(l_name, INT_MAX);
-
-	/* Return the real directory entry */
-	*retdent = realdent;
-
-	if (slotptr2) {
-		memcpy(get_dentfromdir_block, get_contents_vfatname_block,
-			mydata->clust_size * mydata->sect_size);
-		cur_position = (__u8 *)realdent - get_contents_vfatname_block;
-		*retdent = (dir_entry *) &get_dentfromdir_block[cur_position];
-	}
+	if (!itr->dent && !itr->is_root)
+		/*
+		 * don't care return value here because we have already
+		 * finished completing an entry with name, only ending up
+		 * no more entry left
+		 */
+		flush_dir_table(itr);
 
 	return 0;
 }
@@ -569,20 +468,20 @@ static int find_empty_cluster(fsdata *mydata)
 }
 
 /*
- * Write directory entries in 'get_dentfromdir_block' to block device
+ * Write directory entries in itr's buffer to block device
  */
-static void flush_dir_table(fsdata *mydata, dir_entry **dentptr)
+static int flush_dir_table(fat_itr *itr)
 {
+	fsdata *mydata = itr->fsdata;
 	int dir_newclust = 0;
+	unsigned int bytesperclust = mydata->clust_size * mydata->sect_size;
 
-	if (set_cluster(mydata, dir_curclust,
-		    get_dentfromdir_block,
-		    mydata->clust_size * mydata->sect_size) != 0) {
-		printf("error: wrinting directory entry\n");
-		return;
+	if (set_cluster(mydata, itr->clust, itr->block, bytesperclust) != 0) {
+		printf("error: writing directory entry\n");
+		return -1;
 	}
 	dir_newclust = find_empty_cluster(mydata);
-	set_fatent_value(mydata, dir_curclust, dir_newclust);
+	set_fatent_value(mydata, itr->clust, dir_newclust);
 	if (mydata->fatsize == 32)
 		set_fatent_value(mydata, dir_newclust, 0xffffff8);
 	else if (mydata->fatsize == 16)
@@ -590,15 +489,19 @@ static void flush_dir_table(fsdata *mydata, dir_entry **dentptr)
 	else if (mydata->fatsize == 12)
 		set_fatent_value(mydata, dir_newclust, 0xff8);
 
-	dir_curclust = dir_newclust;
+	itr->clust = dir_newclust;
+	itr->next_clust = dir_newclust;
 
 	if (flush_dirty_fat_buffer(mydata) < 0)
-		return;
+		return -1;
+
+	memset(itr->block, 0x00, bytesperclust);
 
-	memset(get_dentfromdir_block, 0x00,
-		mydata->clust_size * mydata->sect_size);
+	itr->dent = (dir_entry *)itr->block;
+	itr->last_cluster = 1;
+	itr->remaining = bytesperclust / sizeof(dir_entry) - 1;
 
-	*dentptr = (dir_entry *) get_dentfromdir_block;
+	return 0;
 }
 
 /*
@@ -764,139 +667,83 @@ static int check_overflow(fsdata *mydata, __u32 clustnum, loff_t size)
 	return 0;
 }
 
-/*
- * Check if adding several entries exceed one cluster boundary
- */
-static int is_next_clust(fsdata *mydata, dir_entry *dentptr)
-{
-	int cur_position;
-
-	cur_position = (__u8 *)dentptr - get_dentfromdir_block;
-
-	if (cur_position >= mydata->clust_size * mydata->sect_size)
-		return 1;
-	else
-		return 0;
-}
-
-static dir_entry *empty_dentptr;
 /*
  * Find a directory entry based on filename or start cluster number
  * If the directory entry is not found,
  * the new position for writing a directory entry will be returned
  */
-static dir_entry *find_directory_entry(fsdata *mydata, int startsect,
-	char *filename, dir_entry *retdent, __u32 start)
+static dir_entry *find_directory_entry(fat_itr *itr, char *filename)
 {
-	__u32 curclust = sect_to_clust(mydata, startsect);
-
-	debug("get_dentfromdir: %s\n", filename);
+	int match = 0;
 
-	while (1) {
-		dir_entry *dentptr;
+	while (fat_itr_next(itr)) {
+		/* check both long and short name: */
+		if (!strcasecmp(filename, itr->name))
+			match = 1;
+		else if (itr->name != itr->s_name &&
+			 !strcasecmp(filename, itr->s_name))
+			match = 1;
 
-		int i;
+		if (!match)
+			continue;
 
-		if (get_cluster(mydata, curclust, get_dentfromdir_block,
-			    mydata->clust_size * mydata->sect_size) != 0) {
-			printf("Error: reading directory block\n");
+		if (itr->dent->name[0] == '\0')
 			return NULL;
-		}
-
-		dentptr = (dir_entry *)get_dentfromdir_block;
-
-		dir_curclust = curclust;
-
-		for (i = 0; i < DIRENTSPERCLUST; i++) {
-			char s_name[14], l_name[VFAT_MAXLEN_BYTES];
-
-			l_name[0] = '\0';
-			if (dentptr->name[0] == DELETED_FLAG) {
-				dentptr++;
-				if (is_next_clust(mydata, dentptr))
-					break;
-				continue;
-			}
-			if ((dentptr->attr & ATTR_VOLUME)) {
-				if ((dentptr->attr & ATTR_VFAT) &&
-				    (dentptr->name[0] & LAST_LONG_ENTRY_MASK)) {
-					get_long_file_name(mydata, curclust,
-						     get_dentfromdir_block,
-						     &dentptr, l_name);
-					debug("vfatname: |%s|\n", l_name);
-				} else {
-					/* Volume label or VFAT entry */
-					dentptr++;
-					if (is_next_clust(mydata, dentptr))
-						break;
-					continue;
-				}
-			}
-			if (dentptr->name[0] == 0) {
-				debug("Dentname == NULL - %d\n", i);
-				empty_dentptr = dentptr;
-				return NULL;
-			}
-
-			get_name(dentptr, s_name);
-
-			if (strncasecmp(filename, s_name, sizeof(s_name)) &&
-			    strncasecmp(filename, l_name, sizeof(l_name))) {
-				debug("Mismatch: |%s|%s|\n",
-					s_name, l_name);
-				dentptr++;
-				if (is_next_clust(mydata, dentptr))
-					break;
-				continue;
-			}
+		else
+			return itr->dent;
+	}
 
-			memcpy(retdent, dentptr, sizeof(dir_entry));
+	if (!itr->dent && !itr->is_root && flush_dir_table(itr))
+		/* indicate that allocating dent failed */
+		itr->dent = NULL;
 
-			debug("DentName: %s", s_name);
-			debug(", start: 0x%x", START(dentptr));
-			debug(", size:  0x%x %s\n",
-			      FAT2CPU32(dentptr->size),
-			      (dentptr->attr & ATTR_DIR) ?
-			      "(DIR)" : "");
+	return NULL;
+}
 
-			return dentptr;
+static int split_filename(char *filename, char **dirname, char **basename)
+{
+	char *p, *last_slash, *last_slash_cont;
+
+again:
+	p = filename;
+	last_slash = NULL;
+	last_slash_cont = NULL;
+	while (*p) {
+		if (ISDIRDELIM(*p)) {
+			last_slash = p;
+			last_slash_cont = p;
+			/* continuous slashes */
+			while (ISDIRDELIM(*p))
+				last_slash_cont = p++;
+			if (!*p)
+				break;
 		}
+		p++;
+	}
 
-		/*
-		 * In FAT16/12, the root dir is locate before data area, shows
-		 * in following:
-		 * -------------------------------------------------------------
-		 * | Boot | FAT1 & 2 | Root dir | Data (start from cluster #2) |
-		 * -------------------------------------------------------------
-		 *
-		 * As a result if curclust is in Root dir, it is a negative
-		 * number or 0, 1.
-		 *
-		 */
-		if (mydata->fatsize != 32 && (int)curclust <= 1) {
-			/* Current clust is in root dir, set to next clust */
-			curclust++;
-			if ((int)curclust <= 1)
-				continue;	/* continue to find */
-
-			/* Reach the end of root dir */
-			empty_dentptr = dentptr;
-			return NULL;
+	if (last_slash) {
+		if (last_slash_cont == (filename + strlen(filename) - 1)) {
+			/* remove trailing slashes */
+			*last_slash = '\0';
+			goto again;
 		}
 
-		curclust = get_fatent(mydata, dir_curclust);
-		if (IS_LAST_CLUST(curclust, mydata->fatsize)) {
-			empty_dentptr = dentptr;
-			return NULL;
-		}
-		if (CHECK_CLUST(curclust, mydata->fatsize)) {
-			debug("curclust: 0x%x\n", curclust);
-			debug("Invalid FAT entry\n");
-			return NULL;
+		if (last_slash == filename) {
+			/* avoid ""(null) directory */
+			*dirname = "/";
+		} else {
+			*last_slash = '\0';
+			*dirname = filename;
 		}
+
+		*last_slash_cont = '\0';
+		*basename = last_slash_cont + 1;
+	} else {
+		*dirname = "/"; /* root by default */
+		*basename = filename;
 	}
 
-	return NULL;
+	return 0;
 }
 
 static int normalize_longname(char *l_filename, const char *filename)
@@ -940,86 +787,60 @@ static int normalize_longname(char *l_filename, const char *filename)
 static int do_fat_write(const char *filename, void *buffer, loff_t size,
 			loff_t *actwrite)
 {
-	dir_entry *dentptr, *retdent;
-	__u32 startsect;
+	dir_entry *retdent;
 	__u32 start_cluster;
-	boot_sector bs;
-	volume_info volinfo;
-	fsdata datablock;
+	fsdata datablock = { .fatbuf = NULL, };
 	fsdata *mydata = &datablock;
-	int cursect;
+	fat_itr *itr = NULL;
 	int ret = -1;
+	char *filename_copy, *parent, *basename;
 	char l_filename[VFAT_MAXLEN_BYTES];
 
-	*actwrite = size;
-	dir_curclust = 0;
+	filename_copy = strdup(filename);
+	if (!filename_copy)
+		return -ENOMEM;
 
-	if (read_bootsectandvi(&bs, &volinfo, &mydata->fatsize)) {
-		debug("error: reading boot sector\n");
-		return -EIO;
+	split_filename(filename_copy, &parent, &basename);
+	if (!strlen(basename)) {
+		ret = -EINVAL;
+		goto exit;
 	}
 
-	total_sector = bs.total_sect;
-	if (total_sector == 0)
-		total_sector = (int)cur_part_info.size; /* cast of lbaint_t */
-
-	if (mydata->fatsize == 32)
-		mydata->fatlength = bs.fat32_length;
-	else
-		mydata->fatlength = bs.fat_length;
-
-	mydata->fat_sect = bs.reserved;
-
-	cursect = mydata->rootdir_sect
-		= mydata->fat_sect + mydata->fatlength * bs.fats;
-	num_of_fats = bs.fats;
-
-	mydata->sect_size = (bs.sector_size[1] << 8) + bs.sector_size[0];
-	mydata->clust_size = bs.cluster_size;
-
-	if (mydata->fatsize == 32) {
-		mydata->data_begin = mydata->rootdir_sect -
-					(mydata->clust_size * 2);
-	} else {
-		int rootdir_size;
-
-		rootdir_size = ((bs.dir_entries[1]  * (int)256 +
-				 bs.dir_entries[0]) *
-				 sizeof(dir_entry)) /
-				 mydata->sect_size;
-		mydata->data_begin = mydata->rootdir_sect +
-					rootdir_size -
-					(mydata->clust_size * 2);
+	filename = basename;
+	if (normalize_longname(l_filename, filename)) {
+		printf("FAT: illegal filename (%s)\n", filename);
+		ret = -EINVAL;
+		goto exit;
 	}
 
-	mydata->fatbufnum = -1;
-	mydata->fat_dirty = 0;
-	mydata->fatbuf = memalign(ARCH_DMA_MINALIGN, FATBUFSIZE);
-	if (mydata->fatbuf == NULL) {
-		debug("Error: allocating memory\n");
-		return -ENOMEM;
+	itr = malloc_cache_aligned(sizeof(fat_itr));
+	if (!itr) {
+		ret = -ENOMEM;
+		goto exit;
 	}
 
-	if (disk_read(cursect,
-		(mydata->fatsize == 32) ?
-		(mydata->clust_size) :
-		PREFETCH_BLOCKS, do_fat_read_at_block) < 0) {
-		debug("Error: reading rootdir block\n");
-		ret = -EIO;
+	ret = fat_itr_root(itr, &datablock);
+	if (ret)
 		goto exit;
-	}
-	dentptr = (dir_entry *) do_fat_read_at_block;
 
-	if (normalize_longname(l_filename, filename)) {
-		printf("FAT: illegal filename (%s)\n", filename);
-		ret = -EINVAL;
+	total_sector = datablock.bs_total_sect;
+	if (total_sector == 0)
+		total_sector = (int)cur_part_info.size; /* cast of lbaint_t */
+
+	ret = fat_itr_resolve(itr, parent, TYPE_DIR);
+	if (ret) {
+		printf("%s: doesn't exist (%d)\n", parent, ret);
 		goto exit;
 	}
 
-	startsect = mydata->rootdir_sect;
-	retdent = find_directory_entry(mydata, startsect,
-				l_filename, dentptr, 0);
+	retdent = find_directory_entry(itr, l_filename);
+
 	if (retdent) {
+		if (fat_itr_isdir(itr)) {
+			ret = -EISDIR;
+			goto exit;
+		}
+
 		/* Update file size and start_cluster in a directory entry */
 		retdent->size = cpu_to_le32(size);
 		start_cluster = START(retdent);
@@ -1062,9 +883,31 @@ static int do_fat_write(const char *filename, void *buffer, loff_t size,
 			set_start_cluster(mydata, retdent, start_cluster);
 		}
 	} else {
+		/* Create a new file */
+
+		if (itr->is_root) {
+			/* root dir cannot have "." or ".." */
+			if (!strcmp(l_filename, ".") ||
+			    !strcmp(l_filename, "..")) {
+				ret = -EINVAL;
+				goto exit;
+			}
+		}
+
+		if (!itr->dent) {
+			printf("Error: allocating new dir entry\n");
+			ret = -EIO;
+			goto exit;
+		}
+
+		memset(itr->dent, 0, sizeof(*itr->dent));
+
 		/* Set short name to set alias checksum field in dir_slot */
-		set_name(empty_dentptr, filename);
-		fill_dir_slot(mydata, &empty_dentptr, filename);
+		set_name(itr->dent, filename);
+		if (fill_dir_slot(itr, filename)) {
+			ret = -EIO;
+			goto exit;
+		}
 
 		if (size) {
 			ret = start_cluster = find_empty_cluster(mydata);
@@ -1085,10 +928,10 @@ static int do_fat_write(const char *filename, void *buffer, loff_t size,
 		}
 
 		/* Set attribute as archieve for regular file */
-		fill_dentry(mydata, empty_dentptr, filename,
-			start_cluster, size, 0x20);
+		fill_dentry(itr->fsdata, itr->dent, filename,
+					start_cluster, size, 0x20);
 
-		retdent = empty_dentptr;
+		retdent = itr->dent;
 	}
 
 	ret = set_contents(mydata, retdent, buffer, size, actwrite);
@@ -1108,15 +951,17 @@ static int do_fat_write(const char *filename, void *buffer, loff_t size,
 	}
 
 	/* Write directory table to device */
-	ret = set_cluster(mydata, dir_curclust, get_dentfromdir_block,
-			mydata->clust_size * mydata->sect_size);
+	ret = set_cluster(mydata, itr->clust, itr->block,
+				mydata->clust_size * mydata->sect_size);
 	if (ret) {
 		printf("Error: writing directory entry\n");
 		ret = -EIO;
 	}
 
 exit:
+	free(filename_copy);
 	free(mydata->fatbuf);
+	free(itr);
 	return ret;
 }
 
-- 
2.17.0

  parent reply	other threads:[~2018-07-20  2:57 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-07-20  2:57 [U-Boot] [PATCH 00/17] fs: fat: extend FAT write operations AKASHI Takahiro
2018-07-20  2:57 ` [U-Boot] [PATCH 01/17] fs: fat: extend get_fs_info() for write use AKASHI Takahiro
2018-07-20 18:06   ` Heinrich Schuchardt
2018-07-22  7:43     ` Heinrich Schuchardt
2018-07-20  2:57 ` [U-Boot] [PATCH 02/17] fs: fat: handle "." and ".." of root dir correctly with fat_itr_resolve() AKASHI Takahiro
2018-07-20 18:09   ` Heinrich Schuchardt
2018-07-23  7:55     ` AKASHI Takahiro
2018-07-20  2:57 ` [U-Boot] [PATCH 03/17] fs: fat: make directory iterator global for write use AKASHI Takahiro
2018-07-20 18:02   ` Heinrich Schuchardt
2018-07-23  8:06     ` AKASHI Takahiro
2018-07-23  8:18       ` AKASHI Takahiro
2018-08-11 13:34   ` Heinrich Schuchardt
2018-08-20  4:45     ` AKASHI Takahiro
2018-07-20  2:57 ` [U-Boot] [PATCH 04/17] fs: fat: assure iterator's ->dent belongs to ->clust AKASHI Takahiro
2018-07-20  2:57 ` [U-Boot] [PATCH 05/17] fs: fat: check and normailze file name AKASHI Takahiro
2018-07-31  4:31   ` Heinrich Schuchardt
2018-07-20  2:57 ` [U-Boot] [PATCH 06/17] fs: fat: write returns error code instead of -1 AKASHI Takahiro
2018-07-20 17:55   ` Heinrich Schuchardt
2018-07-23  8:32     ` AKASHI Takahiro
2018-07-20  2:57 ` AKASHI Takahiro [this message]
2018-07-20  2:57 ` [U-Boot] [PATCH 08/17] fs: fat: refactor write interface for a file offset AKASHI Takahiro
2018-07-20  2:57 ` [U-Boot] [PATCH 09/17] fs: fat: support write with non-zero offset AKASHI Takahiro
2018-07-20 17:46   ` Heinrich Schuchardt
2018-07-23  8:41     ` AKASHI Takahiro
2018-07-20  2:57 ` [U-Boot] [PATCH 10/17] cmd: fat: add offset parameter to fatwrite AKASHI Takahiro
2018-07-20  2:57 ` [U-Boot] [PATCH 11/17] fs: add mkdir interface AKASHI Takahiro
2018-07-20 17:35   ` Heinrich Schuchardt
2018-07-23 23:48     ` Simon Glass
2018-07-23 23:56       ` Tom Rini
2018-07-24  1:45         ` AKASHI Takahiro
2018-07-25  2:45           ` Simon Glass
2018-07-24  0:56     ` AKASHI Takahiro
2018-07-20  2:57 ` [U-Boot] [PATCH 12/17] fs: fat: remember the starting cluster number of directory AKASHI Takahiro
2018-07-20  2:57 ` [U-Boot] [PATCH 13/17] fs: fat: support mkdir AKASHI Takahiro
2018-07-20 17:14   ` Heinrich Schuchardt
2018-07-24  2:01     ` AKASHI Takahiro
2018-07-20  2:57 ` [U-Boot] [PATCH 14/17] cmd: fat: add fatmkdir command AKASHI Takahiro
2018-07-20 17:09   ` Heinrich Schuchardt
2018-07-24  2:07     ` AKASHI Takahiro
2018-07-20  2:57 ` [U-Boot] [PATCH 15/17] efi_loader: file: support creating a directory AKASHI Takahiro
2018-07-20  2:57 ` [U-Boot] [PATCH 16/17] efi_loader: implement a pseudo "file delete" AKASHI Takahiro
2018-07-20  2:57 ` [U-Boot] [PATCH 17/17] fs-test: fix false positive error at Test Case 12 AKASHI Takahiro
2018-07-29  7:02   ` Heinrich Schuchardt
2018-07-31  7:55     ` AKASHI Takahiro
2018-07-20  9:48 ` [U-Boot] [PATCH 00/17] fs: fat: extend FAT write operations Heinrich Schuchardt
2018-07-22  6:44   ` Heinrich Schuchardt
2018-07-23  7:35     ` AKASHI Takahiro
2018-07-23 14:46     ` Tom Rini
2018-08-06 22:34       ` Heinrich Schuchardt
2018-08-07  5:38         ` AKASHI Takahiro
2018-08-07  5:52           ` AKASHI Takahiro
2018-08-07  5:53           ` Heinrich Schuchardt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180720025723.6736-8-takahiro.akashi@linaro.org \
    --to=takahiro.akashi@linaro.org \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.