* grub-core/fs/bfs.c: Remove variable length arrays. Reduces afs.mod and
bfs.mod size by 556 resp 740 bytes (288 resp 334 compressed). * include/grub/types.h (grub_unaligned_uint64_t): New type.
This commit is contained in:
		
							parent
							
								
									e89c2d48a9
								
							
						
					
					
						commit
						d28e1163c3
					
				
					 3 changed files with 240 additions and 244 deletions
				
			
		|  | @ -1,3 +1,9 @@ | ||||||
|  | 2013-10-20  Vladimir Serbinenko  <phcoder@gmail.com> | ||||||
|  | 
 | ||||||
|  | 	* grub-core/fs/bfs.c: Remove variable length arrays. Reduces afs.mod and | ||||||
|  | 	bfs.mod size by 556 resp 740 bytes (288 resp 334 compressed). | ||||||
|  | 	* include/grub/types.h (grub_unaligned_uint64_t): New type. | ||||||
|  | 
 | ||||||
| 2013-10-19  Vladimir Serbinenko  <phcoder@gmail.com> | 2013-10-19  Vladimir Serbinenko  <phcoder@gmail.com> | ||||||
| 
 | 
 | ||||||
| 	Lift 255x255 erminal sie restriction to 65535x65535. Also change from | 	Lift 255x255 erminal sie restriction to 65535x65535. Also change from | ||||||
|  |  | ||||||
|  | @ -170,7 +170,7 @@ struct grub_bfs_btree_node | ||||||
| struct grub_bfs_data | struct grub_bfs_data | ||||||
| { | { | ||||||
|   struct grub_bfs_superblock sb; |   struct grub_bfs_superblock sb; | ||||||
|   struct grub_bfs_inode ino[0]; |   struct grub_bfs_inode ino; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /* Context for grub_bfs_dir.  */ | /* Context for grub_bfs_dir.  */ | ||||||
|  | @ -419,6 +419,63 @@ read_bfs_file (grub_disk_t disk, | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static grub_err_t | ||||||
|  | read_b_node (grub_disk_t disk, | ||||||
|  | 	     const struct grub_bfs_superblock *sb, | ||||||
|  | 	     const struct grub_bfs_inode *ino, | ||||||
|  | 	     grub_uint64_t node_off, | ||||||
|  | 	     struct grub_bfs_btree_node **node, | ||||||
|  | 	     char **key_data, grub_uint16_t **keylen_idx, | ||||||
|  | 	     grub_unaligned_uint64_t **key_values) | ||||||
|  | { | ||||||
|  |   void *ret; | ||||||
|  |   struct grub_bfs_btree_node node_head; | ||||||
|  |   grub_size_t total_size; | ||||||
|  |   grub_err_t err; | ||||||
|  | 
 | ||||||
|  |   *node = NULL; | ||||||
|  |   *key_data = NULL; | ||||||
|  |   *keylen_idx = NULL; | ||||||
|  |   *key_values = NULL; | ||||||
|  | 
 | ||||||
|  |   err = read_bfs_file (disk, sb, ino, node_off, &node_head, sizeof (node_head), | ||||||
|  | 		       0, 0); | ||||||
|  |   if (err) | ||||||
|  |     return err; | ||||||
|  | 
 | ||||||
|  |   total_size = ALIGN_UP (sizeof (node_head) + | ||||||
|  | 			 grub_bfs_to_cpu_treehead | ||||||
|  | 			 (node_head.total_key_len), | ||||||
|  | 			 BTREE_ALIGN) + | ||||||
|  |     grub_bfs_to_cpu_treehead (node_head.count_keys) * | ||||||
|  |     sizeof (grub_uint16_t) | ||||||
|  |     + grub_bfs_to_cpu_treehead (node_head.count_keys) * | ||||||
|  |     sizeof (grub_uint64_t); | ||||||
|  | 
 | ||||||
|  |   ret = grub_malloc (total_size); | ||||||
|  |   if (!ret) | ||||||
|  |     return grub_errno; | ||||||
|  | 
 | ||||||
|  |   err = read_bfs_file (disk, sb, ino, node_off, ret, total_size, 0, 0); | ||||||
|  |   if (err) | ||||||
|  |     { | ||||||
|  |       grub_free (ret); | ||||||
|  |       return err; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |   *node = ret; | ||||||
|  |   *key_data = (char *) ret + sizeof (node_head); | ||||||
|  |   *keylen_idx = (grub_uint16_t *) ret | ||||||
|  |     + ALIGN_UP (sizeof (node_head) + | ||||||
|  | 		grub_bfs_to_cpu_treehead (node_head.total_key_len), | ||||||
|  | 		BTREE_ALIGN) / 2; | ||||||
|  |   *key_values = (grub_unaligned_uint64_t *) | ||||||
|  |     (*keylen_idx + | ||||||
|  |      grub_bfs_to_cpu_treehead (node_head.count_keys)); | ||||||
|  | 
 | ||||||
|  |   return GRUB_ERR_NONE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static int | static int | ||||||
| iterate_in_b_tree (grub_disk_t disk, | iterate_in_b_tree (grub_disk_t disk, | ||||||
| 		   const struct grub_bfs_superblock *sb, | 		   const struct grub_bfs_superblock *sb, | ||||||
|  | @ -462,70 +519,52 @@ iterate_in_b_tree (grub_disk_t disk, | ||||||
| 
 | 
 | ||||||
|   while (1) |   while (1) | ||||||
|     { |     { | ||||||
|       struct grub_bfs_btree_node node; |       struct grub_bfs_btree_node *node; | ||||||
|       err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), |       char *key_data; | ||||||
| 			   0, 0); |       grub_uint16_t *keylen_idx; | ||||||
|       if (err) |       grub_unaligned_uint64_t *key_values; | ||||||
| 	return 0; |  | ||||||
|       { |  | ||||||
| 	char key_data[grub_bfs_to_cpu_treehead (node.total_key_len) + 1]; |  | ||||||
| 	grub_uint16_t keylen_idx[grub_bfs_to_cpu_treehead (node.count_keys)]; |  | ||||||
| 	grub_uint64_t key_values[grub_bfs_to_cpu_treehead (node.count_keys)]; |  | ||||||
|       unsigned i; |       unsigned i; | ||||||
|       grub_uint16_t start = 0, end = 0; |       grub_uint16_t start = 0, end = 0; | ||||||
| 
 | 
 | ||||||
| 	err = |       err = read_b_node (disk, sb, ino, | ||||||
| 	  read_bfs_file (disk, sb, ino, node_off + sizeof (node), key_data, | 			 node_off, | ||||||
| 			 grub_bfs_to_cpu_treehead (node.total_key_len), 0, 0); | 			 &node, | ||||||
| 	if (err) | 			 &key_data,  | ||||||
| 	  return 0; | 			 &keylen_idx, | ||||||
| 	key_data[grub_bfs_to_cpu_treehead (node.total_key_len)] = 0; | 			 &key_values); | ||||||
| 	err = read_bfs_file (disk, sb, ino, node_off | 
 | ||||||
| 			     + ALIGN_UP (sizeof (node) + |  | ||||||
| 					 grub_bfs_to_cpu_treehead |  | ||||||
| 					 (node.total_key_len), BTREE_ALIGN), |  | ||||||
| 			     keylen_idx, |  | ||||||
| 			     grub_bfs_to_cpu_treehead (node.count_keys) * |  | ||||||
| 			     sizeof (grub_uint16_t), 0, 0); |  | ||||||
| 	if (err) |  | ||||||
| 	  return 0; |  | ||||||
| 	err = read_bfs_file (disk, sb, ino, node_off |  | ||||||
| 			     + ALIGN_UP (sizeof (node) + |  | ||||||
| 					 grub_bfs_to_cpu_treehead |  | ||||||
| 					 (node.total_key_len), |  | ||||||
| 					 BTREE_ALIGN) + |  | ||||||
| 			     grub_bfs_to_cpu_treehead (node.count_keys) * |  | ||||||
| 			     sizeof (grub_uint16_t), key_values, |  | ||||||
| 			     grub_bfs_to_cpu_treehead (node.count_keys) * |  | ||||||
| 			     sizeof (grub_uint64_t), 0, 0); |  | ||||||
|       if (err) |       if (err) | ||||||
| 	return 0; | 	return 0; | ||||||
|        |        | ||||||
| 	for (i = 0; i < grub_bfs_to_cpu_treehead (node.count_keys); i++) |       for (i = 0; i < grub_bfs_to_cpu_treehead (node->count_keys); i++) | ||||||
| 	{ | 	{ | ||||||
| 	  char c; | 	  char c; | ||||||
| 	  start = end; | 	  start = end; | ||||||
| 	  end = grub_bfs_to_cpu16 (keylen_idx[i]); | 	  end = grub_bfs_to_cpu16 (keylen_idx[i]); | ||||||
| 	    if (grub_bfs_to_cpu_treehead (node.total_key_len) <= end) | 	  if (grub_bfs_to_cpu_treehead (node->total_key_len) <= end) | ||||||
| 	      end = grub_bfs_to_cpu_treehead (node.total_key_len); | 	    end = grub_bfs_to_cpu_treehead (node->total_key_len); | ||||||
| 	  c = key_data[end]; | 	  c = key_data[end]; | ||||||
| 	  key_data[end] = 0; | 	  key_data[end] = 0; | ||||||
| 	    if (hook (key_data + start, grub_bfs_to_cpu64 (key_values[i]), | 	  if (hook (key_data + start, grub_bfs_to_cpu64 (key_values[i].val), | ||||||
| 		    ctx)) | 		    ctx)) | ||||||
|  | 	    { | ||||||
|  | 	      grub_free (node); | ||||||
| 	      return 1; | 	      return 1; | ||||||
|  | 	    } | ||||||
| 	    key_data[end] = c; | 	    key_data[end] = c; | ||||||
| 	  } | 	  } | ||||||
| 	node_off = grub_bfs_to_cpu64 (node.right); | 	node_off = grub_bfs_to_cpu64 (node->right); | ||||||
|  | 	grub_free (node); | ||||||
| 	if (node_off == POINTER_INVALID) | 	if (node_off == POINTER_INVALID) | ||||||
| 	  return 0; | 	  return 0; | ||||||
|     } |     } | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int | static int | ||||||
| bfs_strcmp (const char *a, const char *b, grub_size_t alen) | bfs_strcmp (const char *a, const char *b, grub_size_t alen, grub_size_t blen) | ||||||
| { | { | ||||||
|   while (*b && alen) |   char ac, bc; | ||||||
|  |   while (blen && alen) | ||||||
|     { |     { | ||||||
|       if (*a != *b) |       if (*a != *b) | ||||||
| 	break; | 	break; | ||||||
|  | @ -533,18 +572,16 @@ bfs_strcmp (const char *a, const char *b, grub_size_t alen) | ||||||
|       a++; |       a++; | ||||||
|       b++; |       b++; | ||||||
|       alen--; |       alen--; | ||||||
|  |       blen--; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |   ac = alen ? *a : 0; | ||||||
|  |   bc = blen ? *b : 0; | ||||||
|  | 
 | ||||||
| #ifdef MODE_AFS | #ifdef MODE_AFS | ||||||
|   if (!alen) |   return (int) (grub_int8_t) ac - (int) (grub_int8_t) bc; | ||||||
|     return - (int) (grub_int8_t) *b; |  | ||||||
| 
 |  | ||||||
|   return (int) (grub_int8_t) *a - (int) (grub_int8_t) *b; |  | ||||||
| #else | #else | ||||||
|   if (!alen) |   return (int) (grub_uint8_t) ac - (int) (grub_uint8_t) bc; | ||||||
|     return - (int) (grub_uint8_t) *b; |  | ||||||
| 
 |  | ||||||
|   return (int) (grub_uint8_t) *a - (int) (grub_uint8_t) *b; |  | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -552,6 +589,7 @@ static grub_err_t | ||||||
| find_in_b_tree (grub_disk_t disk, | find_in_b_tree (grub_disk_t disk, | ||||||
| 		const struct grub_bfs_superblock *sb, | 		const struct grub_bfs_superblock *sb, | ||||||
| 		const struct grub_bfs_inode *ino, const char *name, | 		const struct grub_bfs_inode *ino, const char *name, | ||||||
|  | 		grub_size_t name_len, | ||||||
| 		grub_uint64_t * res) | 		grub_uint64_t * res) | ||||||
| { | { | ||||||
|   struct grub_bfs_btree_header head; |   struct grub_bfs_btree_header head; | ||||||
|  | @ -567,50 +605,25 @@ find_in_b_tree (grub_disk_t disk, | ||||||
|   level = grub_bfs_to_cpu32 (head.level) - 1; |   level = grub_bfs_to_cpu32 (head.level) - 1; | ||||||
|   while (1) |   while (1) | ||||||
|     { |     { | ||||||
|       struct grub_bfs_btree_node node; |       struct grub_bfs_btree_node *node; | ||||||
|       err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), |       char *key_data; | ||||||
| 			   0, 0); |       grub_uint16_t *keylen_idx; | ||||||
|  |       grub_unaligned_uint64_t *key_values; | ||||||
|  |       int lg, j; | ||||||
|  |       unsigned i; | ||||||
|  | 
 | ||||||
|  |       err = read_b_node (disk, sb, ino, node_off, &node, &key_data, &keylen_idx, &key_values); | ||||||
|       if (err) |       if (err) | ||||||
| 	return err; | 	return err; | ||||||
|       if (node.count_keys == 0) | 
 | ||||||
|  |       if (node->count_keys == 0) | ||||||
|  | 	{ | ||||||
|  | 	  grub_free (node); | ||||||
| 	  return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), | 	  return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), | ||||||
| 			     name); | 			     name); | ||||||
|       { | 	} | ||||||
| 	char key_data[grub_bfs_to_cpu_treehead (node.total_key_len) + 1]; |  | ||||||
| 	grub_uint16_t keylen_idx[grub_bfs_to_cpu_treehead (node.count_keys)]; |  | ||||||
| 	grub_uint64_t key_values[grub_bfs_to_cpu_treehead (node.count_keys)]; |  | ||||||
| 	unsigned i; |  | ||||||
| 	err = |  | ||||||
| 	  read_bfs_file (disk, sb, ino, node_off + sizeof (node), key_data, |  | ||||||
| 			 grub_bfs_to_cpu_treehead (node.total_key_len), 0, 0); |  | ||||||
| 	if (err) |  | ||||||
| 	  return err; |  | ||||||
| 	key_data[grub_bfs_to_cpu_treehead (node.total_key_len)] = 0; |  | ||||||
| 	err = read_bfs_file (disk, sb, ino, node_off |  | ||||||
| 			     + |  | ||||||
| 			     ALIGN_UP (sizeof (node) + |  | ||||||
| 				       grub_bfs_to_cpu_treehead (node. |  | ||||||
| 								 total_key_len), |  | ||||||
| 				       BTREE_ALIGN), keylen_idx, |  | ||||||
| 			     grub_bfs_to_cpu_treehead (node.count_keys) * |  | ||||||
| 			     sizeof (grub_uint16_t), 0, 0); |  | ||||||
| 	if (err) |  | ||||||
| 	  return err; |  | ||||||
| 	err = read_bfs_file (disk, sb, ino, node_off |  | ||||||
| 			     + ALIGN_UP (sizeof (node) + |  | ||||||
| 					 grub_bfs_to_cpu_treehead |  | ||||||
| 					 (node.total_key_len), |  | ||||||
| 					 BTREE_ALIGN) + |  | ||||||
| 			     grub_bfs_to_cpu_treehead (node.count_keys) * |  | ||||||
| 			     sizeof (grub_uint16_t), key_values, |  | ||||||
| 			     grub_bfs_to_cpu_treehead (node.count_keys) * |  | ||||||
| 			     sizeof (grub_uint64_t), 0, 0); |  | ||||||
| 	if (err) |  | ||||||
| 	  return err; |  | ||||||
| 
 | 
 | ||||||
| 	int lg, j; |       for (lg = 0; grub_bfs_to_cpu_treehead (node->count_keys) >> lg; lg++); | ||||||
| 
 |  | ||||||
| 	for (lg = 0; grub_bfs_to_cpu_treehead (node.count_keys) >> lg; lg++); |  | ||||||
| 
 | 
 | ||||||
|       i = 0; |       i = 0; | ||||||
| 
 | 
 | ||||||
|  | @ -618,16 +631,17 @@ find_in_b_tree (grub_disk_t disk, | ||||||
| 	{ | 	{ | ||||||
| 	  int cmp; | 	  int cmp; | ||||||
| 	  grub_uint16_t start = 0, end = 0; | 	  grub_uint16_t start = 0, end = 0; | ||||||
| 	    if ((i | (1 << j)) >= grub_bfs_to_cpu_treehead (node.count_keys)) | 	  if ((i | (1 << j)) >= grub_bfs_to_cpu_treehead (node->count_keys)) | ||||||
| 	    continue; | 	    continue; | ||||||
| 	  start = grub_bfs_to_cpu16 (keylen_idx[(i | (1 << j)) - 1]); | 	  start = grub_bfs_to_cpu16 (keylen_idx[(i | (1 << j)) - 1]); | ||||||
| 	  end = grub_bfs_to_cpu16 (keylen_idx[(i | (1 << j))]); | 	  end = grub_bfs_to_cpu16 (keylen_idx[(i | (1 << j))]); | ||||||
| 	    if (grub_bfs_to_cpu_treehead (node.total_key_len) <= end) | 	  if (grub_bfs_to_cpu_treehead (node->total_key_len) <= end) | ||||||
| 	      end = grub_bfs_to_cpu_treehead (node.total_key_len); | 	    end = grub_bfs_to_cpu_treehead (node->total_key_len); | ||||||
| 	    cmp = bfs_strcmp (key_data + start, name, end - start); | 	  cmp = bfs_strcmp (key_data + start, name, end - start, name_len); | ||||||
| 	  if (cmp == 0 && level == 0) | 	  if (cmp == 0 && level == 0) | ||||||
| 	    { | 	    { | ||||||
| 		*res = grub_bfs_to_cpu64 (key_values[i | (1 << j)]); | 	      *res = grub_bfs_to_cpu64 (key_values[i | (1 << j)].val); | ||||||
|  | 	      grub_free (node); | ||||||
| 	      return GRUB_ERR_NONE; | 	      return GRUB_ERR_NONE; | ||||||
| 	    } | 	    } | ||||||
| #ifdef MODE_AFS | #ifdef MODE_AFS | ||||||
|  | @ -642,12 +656,13 @@ find_in_b_tree (grub_disk_t disk, | ||||||
| 	  grub_uint16_t end = 0; | 	  grub_uint16_t end = 0; | ||||||
| 	  int cmp; | 	  int cmp; | ||||||
| 	  end = grub_bfs_to_cpu16 (keylen_idx[0]); | 	  end = grub_bfs_to_cpu16 (keylen_idx[0]); | ||||||
| 	    if (grub_bfs_to_cpu_treehead (node.total_key_len) <= end) | 	  if (grub_bfs_to_cpu_treehead (node->total_key_len) <= end) | ||||||
| 	      end = grub_bfs_to_cpu_treehead (node.total_key_len); | 	    end = grub_bfs_to_cpu_treehead (node->total_key_len); | ||||||
| 	    cmp = bfs_strcmp (key_data, name, end); | 	  cmp = bfs_strcmp (key_data, name, end, name_len); | ||||||
| 	  if (cmp == 0 && level == 0) | 	  if (cmp == 0 && level == 0) | ||||||
| 	    { | 	    { | ||||||
| 		*res = grub_bfs_to_cpu64 (key_values[0]); | 	      *res = grub_bfs_to_cpu64 (key_values[0].val); | ||||||
|  | 	      grub_free (node); | ||||||
| 	      return GRUB_ERR_NONE; | 	      return GRUB_ERR_NONE; | ||||||
| 	    } | 	    } | ||||||
| #ifdef MODE_AFS | #ifdef MODE_AFS | ||||||
|  | @ -656,42 +671,47 @@ find_in_b_tree (grub_disk_t disk, | ||||||
| 	    if (cmp >= 0 && level != 0) | 	    if (cmp >= 0 && level != 0) | ||||||
| #endif | #endif | ||||||
| 	      { | 	      { | ||||||
| 		node_off = grub_bfs_to_cpu64 (key_values[0]); | 		node_off = grub_bfs_to_cpu64 (key_values[0].val); | ||||||
| 		level--; | 		level--; | ||||||
|  | 		grub_free (node); | ||||||
| 		continue; | 		continue; | ||||||
| 	      } | 	      } | ||||||
| 	    else if (level != 0 | 	    else if (level != 0 | ||||||
| 		     && grub_bfs_to_cpu_treehead (node.count_keys) >= 2) | 		     && grub_bfs_to_cpu_treehead (node->count_keys) >= 2) | ||||||
| 	      { | 	      { | ||||||
| 		node_off = grub_bfs_to_cpu64 (key_values[1]); | 		node_off = grub_bfs_to_cpu64 (key_values[1].val); | ||||||
| 		level--; | 		level--; | ||||||
|  | 		grub_free (node); | ||||||
| 		continue; | 		continue; | ||||||
| 	      }	       | 	      }	       | ||||||
| 	  } | 	  } | ||||||
| 	else if (level != 0 | 	else if (level != 0 | ||||||
| 		 && i + 1 < grub_bfs_to_cpu_treehead (node.count_keys)) | 		 && i + 1 < grub_bfs_to_cpu_treehead (node->count_keys)) | ||||||
| 	  { | 	  { | ||||||
| 	    node_off = grub_bfs_to_cpu64 (key_values[i + 1]); | 	    node_off = grub_bfs_to_cpu64 (key_values[i + 1].val); | ||||||
| 	    level--; | 	    level--; | ||||||
|  | 	    grub_free (node); | ||||||
| 	    continue; | 	    continue; | ||||||
| 	  } | 	  } | ||||||
| 	if (node.overflow != POINTER_INVALID) | 	if (node->overflow != POINTER_INVALID) | ||||||
| 	  { | 	  { | ||||||
| 	    node_off = grub_bfs_to_cpu64 (node.overflow); | 	    node_off = grub_bfs_to_cpu64 (node->overflow); | ||||||
| 	    /* This level-- isn't specified but is needed.  */ | 	    /* This level-- isn't specified but is needed.  */ | ||||||
| 	    level--; | 	    level--; | ||||||
|  | 	    grub_free (node); | ||||||
| 	    continue; | 	    continue; | ||||||
| 	  } | 	  } | ||||||
|  | 	grub_free (node); | ||||||
| 	return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), | 	return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), | ||||||
| 			   name); | 			   name); | ||||||
|     } |     } | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static grub_err_t | static grub_err_t | ||||||
| hop_level (grub_disk_t disk, | hop_level (grub_disk_t disk, | ||||||
| 	   const struct grub_bfs_superblock *sb, | 	   const struct grub_bfs_superblock *sb, | ||||||
| 	   struct grub_bfs_inode *ino, const char *name) | 	   struct grub_bfs_inode *ino, const char *name, | ||||||
|  | 	   const char *name_end) | ||||||
| { | { | ||||||
|   grub_err_t err; |   grub_err_t err; | ||||||
|   grub_uint64_t res = 0; |   grub_uint64_t res = 0; | ||||||
|  | @ -699,38 +719,35 @@ hop_level (grub_disk_t disk, | ||||||
|   if (((grub_bfs_to_cpu32 (ino->mode) & ATTR_TYPE) != ATTR_DIR)) |   if (((grub_bfs_to_cpu32 (ino->mode) & ATTR_TYPE) != ATTR_DIR)) | ||||||
|     return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); |     return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); | ||||||
| 
 | 
 | ||||||
|   err = find_in_b_tree (disk, sb, ino, name, &res); |   err = find_in_b_tree (disk, sb, ino, name, name_end - name, &res); | ||||||
|   if (err) |   if (err) | ||||||
|     return err; |     return err; | ||||||
| 
 | 
 | ||||||
|   return grub_disk_read (disk, res |   return grub_disk_read (disk, res | ||||||
| 			 << (grub_bfs_to_cpu32 (sb->log2_bsize) | 			 << (grub_bfs_to_cpu32 (sb->log2_bsize) | ||||||
| 			     - GRUB_DISK_SECTOR_BITS), 0, | 			     - GRUB_DISK_SECTOR_BITS), 0, | ||||||
| 			 grub_bfs_to_cpu32 (sb->bsize), (char *) ino); | 			 sizeof (*ino), (char *) ino); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static grub_err_t | static grub_err_t | ||||||
| find_file (const char *path, grub_disk_t disk, | find_file (const char *path, grub_disk_t disk, | ||||||
| 	   const struct grub_bfs_superblock *sb, struct grub_bfs_inode *ino) | 	   const struct grub_bfs_superblock *sb, struct grub_bfs_inode *ino) | ||||||
| { | { | ||||||
|   char *ptr, *ptr2; |   const char *ptr, *next = path; | ||||||
|   char *alloc = NULL; |   char *alloc = NULL; | ||||||
|  |   char *wptr; | ||||||
|   grub_err_t err; |   grub_err_t err; | ||||||
|   union |   struct grub_bfs_inode old_ino; | ||||||
|   { |  | ||||||
|     struct grub_bfs_inode ino; |  | ||||||
|     grub_uint8_t raw[grub_bfs_to_cpu32 (sb->bsize)]; |  | ||||||
|   } old_ino; |  | ||||||
|   unsigned symlinks_max = 32; |   unsigned symlinks_max = 32; | ||||||
| 
 | 
 | ||||||
|   err = read_extent (disk, sb, &sb->root_dir, 0, 0, ino, |   err = read_extent (disk, sb, &sb->root_dir, 0, 0, ino, | ||||||
| 		     grub_bfs_to_cpu32 (sb->bsize)); | 		     sizeof (*ino)); | ||||||
|   if (err) |   if (err) | ||||||
|     return err; |     return err; | ||||||
| 
 | 
 | ||||||
|   ptr = (char *) path; |  | ||||||
|   while (1) |   while (1) | ||||||
|     { |     { | ||||||
|  |       ptr = next; | ||||||
|       while (*ptr == '/') |       while (*ptr == '/') | ||||||
| 	ptr++; | 	ptr++; | ||||||
|       if (*ptr == 0) |       if (*ptr == 0) | ||||||
|  | @ -738,17 +755,9 @@ find_file (const char *path, grub_disk_t disk, | ||||||
| 	  grub_free (alloc); | 	  grub_free (alloc); | ||||||
| 	  return GRUB_ERR_NONE; | 	  return GRUB_ERR_NONE; | ||||||
| 	} | 	} | ||||||
|       ptr2 = grub_strchr (ptr, '/'); |       for (next = ptr; *next && *next != '/'; next++); | ||||||
|       grub_memcpy (&old_ino, ino, grub_bfs_to_cpu32 (sb->bsize)); |       grub_memcpy (&old_ino, ino, sizeof (old_ino)); | ||||||
|       if (ptr2) |       err = hop_level (disk, sb, ino, ptr, next); | ||||||
| 	{ |  | ||||||
| 	  char component[ptr2 - ptr + 1]; |  | ||||||
| 	  grub_memcpy (component, ptr, ptr2 - ptr); |  | ||||||
| 	  component[ptr2 - ptr] = 0; |  | ||||||
| 	  err = hop_level (disk, sb, ino, component); |  | ||||||
| 	} |  | ||||||
|       else |  | ||||||
| 	err = hop_level (disk, sb, ino, ptr); |  | ||||||
|       if (err) |       if (err) | ||||||
| 	return err; | 	return err; | ||||||
| 
 | 
 | ||||||
|  | @ -767,7 +776,7 @@ find_file (const char *path, grub_disk_t disk, | ||||||
| #endif | #endif | ||||||
| 	    { | 	    { | ||||||
| 	      grub_size_t symsize = grub_bfs_to_cpu64 (ino->size); | 	      grub_size_t symsize = grub_bfs_to_cpu64 (ino->size); | ||||||
| 	      alloc = grub_malloc ((ptr2 ? grub_strlen (ptr2) : 0) | 	      alloc = grub_malloc (grub_strlen (next) | ||||||
| 				   + symsize + 1); | 				   + symsize + 1); | ||||||
| 	      if (!alloc) | 	      if (!alloc) | ||||||
| 		{ | 		{ | ||||||
|  | @ -786,7 +795,7 @@ find_file (const char *path, grub_disk_t disk, | ||||||
| #ifndef MODE_AFS | #ifndef MODE_AFS | ||||||
| 	  else | 	  else | ||||||
| 	    { | 	    { | ||||||
| 	      alloc = grub_malloc ((ptr2 ? grub_strlen (ptr2) : 0) | 	      alloc = grub_malloc (grub_strlen (next) | ||||||
| 				   + sizeof (ino->inplace_link) + 1); | 				   + sizeof (ino->inplace_link) + 1); | ||||||
| 	      if (!alloc) | 	      if (!alloc) | ||||||
| 		{ | 		{ | ||||||
|  | @ -802,7 +811,7 @@ find_file (const char *path, grub_disk_t disk, | ||||||
| 	  if (alloc[0] == '/') | 	  if (alloc[0] == '/') | ||||||
| 	    { | 	    { | ||||||
| 	      err = read_extent (disk, sb, &sb->root_dir, 0, 0, ino, | 	      err = read_extent (disk, sb, &sb->root_dir, 0, 0, ino, | ||||||
| 				 grub_bfs_to_cpu32 (sb->bsize)); | 				 sizeof (*ino)); | ||||||
| 	      if (err) | 	      if (err) | ||||||
| 		{ | 		{ | ||||||
| 		  grub_free (alloc); | 		  grub_free (alloc); | ||||||
|  | @ -810,21 +819,14 @@ find_file (const char *path, grub_disk_t disk, | ||||||
| 		} | 		} | ||||||
| 	    } | 	    } | ||||||
| 	  else | 	  else | ||||||
| 	    grub_memcpy (ino, &old_ino, grub_bfs_to_cpu32 (sb->bsize)); | 	    grub_memcpy (ino, &old_ino, sizeof (old_ino)); | ||||||
| 	  ptr = alloc + grub_strlen (alloc); | 	  wptr = alloc + grub_strlen (alloc); | ||||||
| 	  if (ptr2) | 	  if (next) | ||||||
| 	    ptr = grub_stpcpy (ptr, ptr2); | 	    wptr = grub_stpcpy (wptr, next); | ||||||
| 	  *ptr = 0; | 	  *wptr = 0; | ||||||
| 	  ptr = ptr2 = alloc; | 	  next = alloc; | ||||||
| 	  continue; | 	  continue; | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
|       if (!ptr2) |  | ||||||
| 	{ |  | ||||||
| 	  grub_free (alloc); |  | ||||||
| 	  return GRUB_ERR_NONE; |  | ||||||
| 	} |  | ||||||
|       ptr = ptr2 + 1; |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -866,17 +868,13 @@ grub_bfs_dir_iter (const char *name, grub_uint64_t value, | ||||||
| 		   struct grub_bfs_dir_ctx *ctx) | 		   struct grub_bfs_dir_ctx *ctx) | ||||||
| { | { | ||||||
|   grub_err_t err2; |   grub_err_t err2; | ||||||
|   union |  | ||||||
|   { |  | ||||||
|   struct grub_bfs_inode ino; |   struct grub_bfs_inode ino; | ||||||
|     grub_uint8_t raw[grub_bfs_to_cpu32 (ctx->sb.bsize)]; |  | ||||||
|   } ino; |  | ||||||
|   struct grub_dirhook_info info; |   struct grub_dirhook_info info; | ||||||
| 
 | 
 | ||||||
|   err2 = grub_disk_read (ctx->device->disk, value |   err2 = grub_disk_read (ctx->device->disk, value | ||||||
| 			 << (grub_bfs_to_cpu32 (ctx->sb.log2_bsize) | 			 << (grub_bfs_to_cpu32 (ctx->sb.log2_bsize) | ||||||
| 			     - GRUB_DISK_SECTOR_BITS), 0, | 			     - GRUB_DISK_SECTOR_BITS), 0, | ||||||
| 			 grub_bfs_to_cpu32 (ctx->sb.bsize), (char *) ino.raw); | 			 sizeof (ino), (char *) &ino); | ||||||
|   if (err2) |   if (err2) | ||||||
|     { |     { | ||||||
|       grub_print_error (); |       grub_print_error (); | ||||||
|  | @ -886,11 +884,11 @@ grub_bfs_dir_iter (const char *name, grub_uint64_t value, | ||||||
|   info.mtimeset = 1; |   info.mtimeset = 1; | ||||||
| #ifdef MODE_AFS | #ifdef MODE_AFS | ||||||
|   info.mtime = |   info.mtime = | ||||||
|     grub_divmod64 (grub_bfs_to_cpu64 (ino.ino.mtime), 1000000, 0); |     grub_divmod64 (grub_bfs_to_cpu64 (ino.mtime), 1000000, 0); | ||||||
| #else | #else | ||||||
|   info.mtime = grub_bfs_to_cpu64 (ino.ino.mtime) >> 16; |   info.mtime = grub_bfs_to_cpu64 (ino.mtime) >> 16; | ||||||
| #endif | #endif | ||||||
|   info.dir = ((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) == ATTR_DIR); |   info.dir = ((grub_bfs_to_cpu32 (ino.mode) & ATTR_TYPE) == ATTR_DIR); | ||||||
|   return ctx->hook (name, &info, ctx->hook_data); |   return ctx->hook (name, &info, ctx->hook_data); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -909,18 +907,14 @@ grub_bfs_dir (grub_device_t device, const char *path, | ||||||
|   if (err) |   if (err) | ||||||
|     return err; |     return err; | ||||||
| 
 | 
 | ||||||
|   { |  | ||||||
|     union |  | ||||||
|   { |   { | ||||||
|     struct grub_bfs_inode ino; |     struct grub_bfs_inode ino; | ||||||
|       grub_uint8_t raw[grub_bfs_to_cpu32 (ctx.sb.bsize)]; |     err = find_file (path, device->disk, &ctx.sb, &ino); | ||||||
|     } ino; |  | ||||||
|     err = find_file (path, device->disk, &ctx.sb, &ino.ino); |  | ||||||
|     if (err) |     if (err) | ||||||
|       return err; |       return err; | ||||||
|     if (((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) != ATTR_DIR)) |     if (((grub_bfs_to_cpu32 (ino.mode) & ATTR_TYPE) != ATTR_DIR)) | ||||||
|       return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); |       return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); | ||||||
|     iterate_in_b_tree (device->disk, &ctx.sb, &ino.ino, grub_bfs_dir_iter, |     iterate_in_b_tree (device->disk, &ctx.sb, &ino, grub_bfs_dir_iter, | ||||||
| 		       &ctx); | 		       &ctx); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | @ -937,27 +931,22 @@ grub_bfs_open (struct grub_file *file, const char *name) | ||||||
|   if (err) |   if (err) | ||||||
|     return err; |     return err; | ||||||
| 
 | 
 | ||||||
|   { |  | ||||||
|     union |  | ||||||
|   { |   { | ||||||
|     struct grub_bfs_inode ino; |     struct grub_bfs_inode ino; | ||||||
|       grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)]; |  | ||||||
|     } ino; |  | ||||||
|     struct grub_bfs_data *data; |     struct grub_bfs_data *data; | ||||||
|     err = find_file (name, file->device->disk, &sb, &ino.ino); |     err = find_file (name, file->device->disk, &sb, &ino); | ||||||
|     if (err) |     if (err) | ||||||
|       return err; |       return err; | ||||||
|     if (((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) != ATTR_REG)) |     if (((grub_bfs_to_cpu32 (ino.mode) & ATTR_TYPE) != ATTR_REG)) | ||||||
|       return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); |       return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); | ||||||
| 
 | 
 | ||||||
|     data = grub_zalloc (sizeof (struct grub_bfs_data) |     data = grub_zalloc (sizeof (struct grub_bfs_data)); | ||||||
| 			+ grub_bfs_to_cpu32 (sb.bsize)); |  | ||||||
|     if (!data) |     if (!data) | ||||||
|       return grub_errno; |       return grub_errno; | ||||||
|     data->sb = sb; |     data->sb = sb; | ||||||
|     grub_memcpy (&data->ino, &ino, grub_bfs_to_cpu32 (sb.bsize)); |     grub_memcpy (&data->ino, &ino, sizeof (data->ino)); | ||||||
|     file->data = data; |     file->data = data; | ||||||
|     file->size = grub_bfs_to_cpu64 (ino.ino.size); |     file->size = grub_bfs_to_cpu64 (ino.size); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   return GRUB_ERR_NONE; |   return GRUB_ERR_NONE; | ||||||
|  | @ -978,7 +967,7 @@ grub_bfs_read (grub_file_t file, char *buf, grub_size_t len) | ||||||
|   struct grub_bfs_data *data = file->data; |   struct grub_bfs_data *data = file->data; | ||||||
| 
 | 
 | ||||||
|   err = read_bfs_file (file->device->disk, &data->sb, |   err = read_bfs_file (file->device->disk, &data->sb, | ||||||
| 		       data->ino, file->offset, buf, len, | 		       &data->ino, file->offset, buf, len, | ||||||
| 		       file->read_hook, file->read_hook_data); | 		       file->read_hook, file->read_hook_data); | ||||||
|   if (err) |   if (err) | ||||||
|     return -1; |     return -1; | ||||||
|  | @ -1005,7 +994,7 @@ grub_bfs_label (grub_device_t device, char **label) | ||||||
| static grub_ssize_t | static grub_ssize_t | ||||||
| read_bfs_attr (grub_disk_t disk, | read_bfs_attr (grub_disk_t disk, | ||||||
| 	       const struct grub_bfs_superblock *sb, | 	       const struct grub_bfs_superblock *sb, | ||||||
| 	       const struct grub_bfs_inode *ino, | 	       struct grub_bfs_inode *ino, | ||||||
| 	       const char *name, void *buf, grub_size_t len) | 	       const char *name, void *buf, grub_size_t len) | ||||||
| { | { | ||||||
|   grub_uint8_t *ptr = (grub_uint8_t *) ino->small_data; |   grub_uint8_t *ptr = (grub_uint8_t *) ino->small_data; | ||||||
|  | @ -1036,32 +1025,27 @@ read_bfs_attr (grub_disk_t disk, | ||||||
| 
 | 
 | ||||||
|   if (ino->attr.len != 0) |   if (ino->attr.len != 0) | ||||||
|     { |     { | ||||||
|       union |  | ||||||
|       { |  | ||||||
| 	struct grub_bfs_inode ino; |  | ||||||
| 	grub_uint8_t raw[grub_bfs_to_cpu32 (sb->bsize)]; |  | ||||||
|       } ino2; |  | ||||||
|       grub_size_t read; |       grub_size_t read; | ||||||
|       grub_err_t err; |       grub_err_t err; | ||||||
|       grub_uint64_t res; |       grub_uint64_t res; | ||||||
| 
 | 
 | ||||||
|       err = read_extent (disk, sb, &ino->attr, 0, 0, ino2.raw, |       err = read_extent (disk, sb, &ino->attr, 0, 0, ino, | ||||||
| 			 grub_bfs_to_cpu32 (sb->bsize)); | 			 grub_bfs_to_cpu32 (sb->bsize)); | ||||||
|       if (err) |       if (err) | ||||||
| 	return -1; | 	return -1; | ||||||
| 
 | 
 | ||||||
|       err = find_in_b_tree (disk, sb, &ino2.ino, name, &res); |       err = find_in_b_tree (disk, sb, ino, name, grub_strlen (name), &res); | ||||||
|       if (err) |       if (err) | ||||||
| 	return -1; | 	return -1; | ||||||
|       grub_disk_read (disk, res |       grub_disk_read (disk, res | ||||||
| 		      << (grub_bfs_to_cpu32 (sb->log2_bsize) | 		      << (grub_bfs_to_cpu32 (sb->log2_bsize) | ||||||
| 			  - GRUB_DISK_SECTOR_BITS), 0, | 			  - GRUB_DISK_SECTOR_BITS), 0, | ||||||
| 		      grub_bfs_to_cpu32 (sb->bsize), (char *) &ino2); | 		      grub_bfs_to_cpu32 (sb->bsize), (char *) ino); | ||||||
|       read = grub_bfs_to_cpu64 (ino2.ino.size); |       read = grub_bfs_to_cpu64 (ino->size); | ||||||
|       if (read > len) |       if (read > len) | ||||||
| 	read = len; | 	read = len; | ||||||
| 
 | 
 | ||||||
|       err = read_bfs_file (disk, sb, &ino2.ino, 0, buf, read, 0, 0); |       err = read_bfs_file (disk, sb, ino, 0, buf, read, 0, 0); | ||||||
|       if (err) |       if (err) | ||||||
| 	return -1; | 	return -1; | ||||||
|       return read; |       return read; | ||||||
|  | @ -1074,6 +1058,8 @@ grub_bfs_uuid (grub_device_t device, char **uuid) | ||||||
| { | { | ||||||
|   struct grub_bfs_superblock sb; |   struct grub_bfs_superblock sb; | ||||||
|   grub_err_t err; |   grub_err_t err; | ||||||
|  |   struct grub_bfs_inode *ino; | ||||||
|  |   grub_uint64_t vid; | ||||||
| 
 | 
 | ||||||
|   *uuid = 0; |   *uuid = 0; | ||||||
| 
 | 
 | ||||||
|  | @ -1081,23 +1067,24 @@ grub_bfs_uuid (grub_device_t device, char **uuid) | ||||||
|   if (err) |   if (err) | ||||||
|     return err; |     return err; | ||||||
| 
 | 
 | ||||||
|   { |   ino = grub_malloc (grub_bfs_to_cpu32 (sb.bsize)); | ||||||
|     union |   if (!ino) | ||||||
|     { |     return grub_errno; | ||||||
|       struct grub_bfs_inode ino; |  | ||||||
|       grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)]; |  | ||||||
|     } ino; |  | ||||||
|     grub_uint64_t vid; |  | ||||||
| 
 | 
 | ||||||
|   err = read_extent (device->disk, &sb, &sb.root_dir, 0, 0, |   err = read_extent (device->disk, &sb, &sb.root_dir, 0, 0, | ||||||
| 		       &ino, grub_bfs_to_cpu32 (sb.bsize)); | 		     ino, grub_bfs_to_cpu32 (sb.bsize)); | ||||||
|   if (err) |   if (err) | ||||||
|  |     { | ||||||
|  |       grub_free (ino); | ||||||
|       return err; |       return err; | ||||||
|     if (read_bfs_attr (device->disk, &sb, &ino.ino, "be:volume_id", |     } | ||||||
|  |   if (read_bfs_attr (device->disk, &sb, ino, "be:volume_id", | ||||||
| 		     &vid, sizeof (vid)) == sizeof (vid)) | 		     &vid, sizeof (vid)) == sizeof (vid)) | ||||||
|     *uuid = |     *uuid = | ||||||
|       grub_xasprintf ("%016" PRIxGRUB_UINT64_T, grub_bfs_to_cpu64 (vid)); |       grub_xasprintf ("%016" PRIxGRUB_UINT64_T, grub_bfs_to_cpu64 (vid)); | ||||||
|   } | 
 | ||||||
|  |   grub_free (ino); | ||||||
|  | 
 | ||||||
|   return GRUB_ERR_NONE; |   return GRUB_ERR_NONE; | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -291,15 +291,18 @@ static inline void grub_set_unaligned32 (void *ptr, grub_uint32_t val) | ||||||
|   dd->d = val; |   dd->d = val; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | struct grub_unaligned_uint64 | ||||||
|  | { | ||||||
|  |   grub_uint64_t val; | ||||||
|  | } __attribute__ ((packed)); | ||||||
|  | 
 | ||||||
|  | typedef struct grub_unaligned_uint64 grub_unaligned_uint64_t; | ||||||
|  | 
 | ||||||
| static inline grub_uint64_t grub_get_unaligned64 (const void *ptr) | static inline grub_uint64_t grub_get_unaligned64 (const void *ptr) | ||||||
| { | { | ||||||
|   struct grub_unaligned_uint64_t |   const struct grub_unaligned_uint64 *dd | ||||||
|   { |     = (const struct grub_unaligned_uint64 *) ptr; | ||||||
|     grub_uint64_t d; |   return dd->val; | ||||||
|   } __attribute__ ((packed)); |  | ||||||
|   const struct grub_unaligned_uint64_t *dd |  | ||||||
|     = (const struct grub_unaligned_uint64_t *)ptr; |  | ||||||
|   return dd->d; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline void grub_set_unaligned64 (void *ptr, grub_uint64_t val) | static inline void grub_set_unaligned64 (void *ptr, grub_uint64_t val) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue