yaffs_nameval.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /*
  2. * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  3. *
  4. * Copyright (C) 2002-2011 Aleph One Ltd.
  5. * for Toby Churchill Ltd and Brightstar Engineering
  6. *
  7. * Created by Charles Manning <charles@aleph1.co.uk>
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2 as
  11. * published by the Free Software Foundation.
  12. */
  13. /*
  14. * This simple implementation of a name-value store assumes a small number of
  15. * values and fits into a small finite buffer.
  16. *
  17. * Each attribute is stored as a record:
  18. * sizeof(int) bytes record size.
  19. * yaffs_strnlen+1 bytes name null terminated.
  20. * nbytes value.
  21. * ----------
  22. * total size stored in record size
  23. *
  24. * This code has not been tested with unicode yet.
  25. */
  26. #include "yaffs_nameval.h"
  27. #include "yportenv.h"
  28. static int nval_find(const char *xb, int xb_size, const YCHAR *name,
  29. int *exist_size)
  30. {
  31. int pos = 0;
  32. int size;
  33. memcpy(&size, xb, sizeof(int));
  34. while (size > 0 && (size < xb_size) && (pos + size < xb_size)) {
  35. if (!yaffs_strncmp((YCHAR *) (xb + pos + sizeof(int)),
  36. name, size)) {
  37. if (exist_size)
  38. *exist_size = size;
  39. return pos;
  40. }
  41. pos += size;
  42. if (pos < xb_size - sizeof(int))
  43. memcpy(&size, xb + pos, sizeof(int));
  44. else
  45. size = 0;
  46. }
  47. if (exist_size)
  48. *exist_size = 0;
  49. return -ENODATA;
  50. }
  51. static int nval_used(const char *xb, int xb_size)
  52. {
  53. int pos = 0;
  54. int size;
  55. memcpy(&size, xb + pos, sizeof(int));
  56. while (size > 0 && (size < xb_size) && (pos + size < xb_size)) {
  57. pos += size;
  58. if (pos < xb_size - sizeof(int))
  59. memcpy(&size, xb + pos, sizeof(int));
  60. else
  61. size = 0;
  62. }
  63. return pos;
  64. }
  65. int nval_del(char *xb, int xb_size, const YCHAR *name)
  66. {
  67. int pos = nval_find(xb, xb_size, name, NULL);
  68. int size;
  69. if (pos < 0 || pos >= xb_size)
  70. return -ENODATA;
  71. /* Find size, shift rest over this record,
  72. * then zero out the rest of buffer */
  73. memcpy(&size, xb + pos, sizeof(int));
  74. memcpy(xb + pos, xb + pos + size, xb_size - (pos + size));
  75. memset(xb + (xb_size - size), 0, size);
  76. return 0;
  77. }
  78. int nval_set(char *xb, int xb_size, const YCHAR *name, const char *buf,
  79. int bsize, int flags)
  80. {
  81. int pos;
  82. int namelen = yaffs_strnlen(name, xb_size);
  83. int reclen;
  84. int size_exist = 0;
  85. int space;
  86. int start;
  87. pos = nval_find(xb, xb_size, name, &size_exist);
  88. if (flags & XATTR_CREATE && pos >= 0)
  89. return -EEXIST;
  90. if (flags & XATTR_REPLACE && pos < 0)
  91. return -ENODATA;
  92. start = nval_used(xb, xb_size);
  93. space = xb_size - start + size_exist;
  94. reclen = (sizeof(int) + namelen + 1 + bsize);
  95. if (reclen > space)
  96. return -ENOSPC;
  97. if (pos >= 0) {
  98. nval_del(xb, xb_size, name);
  99. start = nval_used(xb, xb_size);
  100. }
  101. pos = start;
  102. memcpy(xb + pos, &reclen, sizeof(int));
  103. pos += sizeof(int);
  104. yaffs_strncpy((YCHAR *) (xb + pos), name, reclen);
  105. pos += (namelen + 1);
  106. memcpy(xb + pos, buf, bsize);
  107. return 0;
  108. }
  109. int nval_get(const char *xb, int xb_size, const YCHAR * name, char *buf,
  110. int bsize)
  111. {
  112. int pos = nval_find(xb, xb_size, name, NULL);
  113. int size;
  114. if (pos >= 0 && pos < xb_size) {
  115. memcpy(&size, xb + pos, sizeof(int));
  116. pos += sizeof(int); /* advance past record length */
  117. size -= sizeof(int);
  118. /* Advance over name string */
  119. while (xb[pos] && size > 0 && pos < xb_size) {
  120. pos++;
  121. size--;
  122. }
  123. /*Advance over NUL */
  124. pos++;
  125. size--;
  126. /* If bsize is zero then this is a size query.
  127. * Return the size, but don't copy.
  128. */
  129. if (!bsize)
  130. return size;
  131. if (size <= bsize) {
  132. memcpy(buf, xb + pos, size);
  133. return size;
  134. }
  135. }
  136. if (pos >= 0)
  137. return -ERANGE;
  138. return -ENODATA;
  139. }
  140. int nval_list(const char *xb, int xb_size, char *buf, int bsize)
  141. {
  142. int pos = 0;
  143. int size;
  144. int name_len;
  145. int ncopied = 0;
  146. int filled = 0;
  147. memcpy(&size, xb + pos, sizeof(int));
  148. while (size > sizeof(int) &&
  149. size <= xb_size &&
  150. (pos + size) < xb_size &&
  151. !filled) {
  152. pos += sizeof(int);
  153. size -= sizeof(int);
  154. name_len = yaffs_strnlen((YCHAR *) (xb + pos), size);
  155. if (ncopied + name_len + 1 < bsize) {
  156. memcpy(buf, xb + pos, name_len * sizeof(YCHAR));
  157. buf += name_len;
  158. *buf = '\0';
  159. buf++;
  160. if (sizeof(YCHAR) > 1) {
  161. *buf = '\0';
  162. buf++;
  163. }
  164. ncopied += (name_len + 1);
  165. } else {
  166. filled = 1;
  167. }
  168. pos += size;
  169. if (pos < xb_size - sizeof(int))
  170. memcpy(&size, xb + pos, sizeof(int));
  171. else
  172. size = 0;
  173. }
  174. return ncopied;
  175. }
  176. int nval_hasvalues(const char *xb, int xb_size)
  177. {
  178. return nval_used(xb, xb_size) > 0;
  179. }