yaffs_nameval.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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. }
  79. int nval_set(char *xb, int xb_size, const YCHAR * name, const char *buf,
  80. int bsize, int flags)
  81. {
  82. int pos;
  83. int namelen = strnlen(name, xb_size);
  84. int reclen;
  85. int size_exist = 0;
  86. int space;
  87. int start;
  88. pos = nval_find(xb, xb_size, name, &size_exist);
  89. if (flags & XATTR_CREATE && pos >= 0)
  90. return -EEXIST;
  91. if (flags & XATTR_REPLACE && pos < 0)
  92. return -ENODATA;
  93. start = nval_used(xb, xb_size);
  94. space = xb_size - start + size_exist;
  95. reclen = (sizeof(int) + namelen + 1 + bsize);
  96. if (reclen > space)
  97. return -ENOSPC;
  98. if (pos >= 0) {
  99. nval_del(xb, xb_size, name);
  100. start = nval_used(xb, xb_size);
  101. }
  102. pos = start;
  103. memcpy(xb + pos, &reclen, sizeof(int));
  104. pos += sizeof(int);
  105. strncpy((YCHAR *) (xb + pos), name, reclen);
  106. pos += (namelen + 1);
  107. memcpy(xb + pos, buf, bsize);
  108. return 0;
  109. }
  110. int nval_get(const char *xb, int xb_size, const YCHAR * name, char *buf,
  111. int bsize)
  112. {
  113. int pos = nval_find(xb, xb_size, name, NULL);
  114. int size;
  115. if (pos >= 0 && pos < xb_size) {
  116. memcpy(&size, xb + pos, sizeof(int));
  117. pos += sizeof(int); /* advance past record length */
  118. size -= sizeof(int);
  119. /* Advance over name string */
  120. while (xb[pos] && size > 0 && pos < xb_size) {
  121. pos++;
  122. size--;
  123. }
  124. /*Advance over NUL */
  125. pos++;
  126. size--;
  127. if (size <= bsize) {
  128. memcpy(buf, xb + pos, size);
  129. return size;
  130. }
  131. }
  132. if (pos >= 0)
  133. return -ERANGE;
  134. else
  135. return -ENODATA;
  136. }
  137. int nval_list(const char *xb, int xb_size, char *buf, int bsize)
  138. {
  139. int pos = 0;
  140. int size;
  141. int name_len;
  142. int ncopied = 0;
  143. int filled = 0;
  144. memcpy(&size, xb + pos, sizeof(int));
  145. while (size > sizeof(int) && size <= xb_size && (pos + size) < xb_size
  146. && !filled) {
  147. pos += sizeof(int);
  148. size -= sizeof(int);
  149. name_len = strnlen((YCHAR *) (xb + pos), size);
  150. if (ncopied + name_len + 1 < bsize) {
  151. memcpy(buf, xb + pos, name_len * sizeof(YCHAR));
  152. buf += name_len;
  153. *buf = '\0';
  154. buf++;
  155. if (sizeof(YCHAR) > 1) {
  156. *buf = '\0';
  157. buf++;
  158. }
  159. ncopied += (name_len + 1);
  160. } else {
  161. filled = 1;
  162. }
  163. pos += size;
  164. if (pos < xb_size - sizeof(int))
  165. memcpy(&size, xb + pos, sizeof(int));
  166. else
  167. size = 0;
  168. }
  169. return ncopied;
  170. }
  171. int nval_hasvalues(const char *xb, int xb_size)
  172. {
  173. return nval_used(xb, xb_size) > 0;
  174. }