yaffs_nameval.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /*
  2. * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  3. *
  4. * Copyright (C) 2002-2010 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 values and fits
  15. * into a small finite buffer.
  16. *
  17. * Each attribute is stored as a record:
  18. * sizeof(int) bytes record size.
  19. * 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 (strncmp
  36. ((YCHAR *) (xb + pos + sizeof(int)), name, size) == 0) {
  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 -1;
  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. /* Find size, shift rest over this record, then zero out the rest of buffer */
  71. memcpy(&size, xb + pos, sizeof(int));
  72. memcpy(xb + pos, xb + pos + size, xb_size - (pos + size));
  73. memset(xb + (xb_size - size), 0, size);
  74. return 0;
  75. } else
  76. return -ENODATA;
  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 = 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. 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. else
  139. return -ENODATA;
  140. }
  141. int nval_list(const char *xb, int xb_size, char *buf, int bsize)
  142. {
  143. int pos = 0;
  144. int size;
  145. int name_len;
  146. int ncopied = 0;
  147. int filled = 0;
  148. memcpy(&size, xb + pos, sizeof(int));
  149. while (size > sizeof(int) && size <= xb_size && (pos + size) < xb_size
  150. && !filled) {
  151. pos += sizeof(int);
  152. size -= sizeof(int);
  153. name_len = strnlen((YCHAR *) (xb + pos), size);
  154. if (ncopied + name_len + 1 < bsize) {
  155. memcpy(buf, xb + pos, name_len * sizeof(YCHAR));
  156. buf += name_len;
  157. *buf = '\0';
  158. buf++;
  159. if (sizeof(YCHAR) > 1) {
  160. *buf = '\0';
  161. buf++;
  162. }
  163. ncopied += (name_len + 1);
  164. } else
  165. filled = 1;
  166. pos += size;
  167. if (pos < xb_size - sizeof(int))
  168. memcpy(&size, xb + pos, sizeof(int));
  169. else
  170. size = 0;
  171. }
  172. return ncopied;
  173. }
  174. int nval_hasvalues(const char *xb, int xb_size)
  175. {
  176. return nval_used(xb, xb_size) > 0;
  177. }