direc.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include <libsec.h>
  5. #include "iso9660.h"
  6. void
  7. mkdirec(Direc *direc, XDir *d)
  8. {
  9. memset(direc, 0, sizeof(Direc));
  10. direc->name = atom(d->name);
  11. direc->uid = atom(d->uid);
  12. direc->gid = atom(d->gid);
  13. direc->uidno = d->uidno;
  14. direc->gidno = d->gidno;
  15. direc->mode = d->mode;
  16. direc->length = d->length;
  17. direc->mtime = d->mtime;
  18. direc->atime = d->atime;
  19. direc->ctime = d->ctime;
  20. direc->symlink = d->symlink;
  21. }
  22. static int
  23. strecmp(char *a, char *ea, char *b)
  24. {
  25. int r;
  26. if((r = strncmp(a, b, ea-a)) != 0)
  27. return r;
  28. if(b[ea-a] == '\0')
  29. return 0;
  30. return 1;
  31. }
  32. /*
  33. * Binary search a list of directories for the
  34. * entry with name name.
  35. * If no entry is found, return a pointer to
  36. * where a new such entry would go.
  37. */
  38. static Direc*
  39. dbsearch(char *name, int nname, Direc *d, int n)
  40. {
  41. int i;
  42. while(n > 0) {
  43. i = strecmp(name, name+nname, d[n/2].name);
  44. if(i < 0)
  45. n = n/2;
  46. else if(i > 0) {
  47. d += n/2+1;
  48. n -= (n/2+1);
  49. } else
  50. return &d[n/2];
  51. }
  52. return d;
  53. }
  54. /*
  55. * Walk to name, starting at d.
  56. */
  57. Direc*
  58. walkdirec(Direc *d, char *name)
  59. {
  60. char *p, *nextp, *slashp;
  61. Direc *nd;
  62. for(p=name; p && *p; p=nextp) {
  63. if((slashp = strchr(p, '/')) != nil)
  64. nextp = slashp+1;
  65. else
  66. nextp = slashp = p+strlen(p);
  67. nd = dbsearch(p, slashp-p, d->child, d->nchild);
  68. if(nd >= d->child+d->nchild || strecmp(p, slashp, nd->name) != 0)
  69. return nil;
  70. d = nd;
  71. }
  72. return d;
  73. }
  74. /*
  75. * Add the file ``name'' with attributes d to the
  76. * directory ``root''. Name may contain multiple
  77. * elements; all but the last must exist already.
  78. *
  79. * The child lists are kept sorted by utfname.
  80. */
  81. Direc*
  82. adddirec(Direc *root, char *name, XDir *d)
  83. {
  84. char *p;
  85. Direc *nd;
  86. int off;
  87. if(name[0] == '/')
  88. name++;
  89. if((p = strrchr(name, '/')) != nil) {
  90. *p = '\0';
  91. root = walkdirec(root, name);
  92. if(root == nil) {
  93. sysfatal("error in proto file: no entry for /%s but /%s/%s\n", name, name, p+1);
  94. return nil;
  95. }
  96. *p = '/';
  97. p++;
  98. } else
  99. p = name;
  100. nd = dbsearch(p, strlen(p), root->child, root->nchild);
  101. off = nd - root->child;
  102. if(off < root->nchild && strcmp(nd->name, p) == 0) {
  103. if ((d->mode & DMDIR) == 0)
  104. fprint(2, "warning: proto lists %s twice\n", name);
  105. return nil;
  106. }
  107. if(root->nchild%Ndirblock == 0) {
  108. root->child = erealloc(root->child, (root->nchild+Ndirblock)*sizeof(Direc));
  109. nd = root->child + off;
  110. }
  111. memmove(nd+1, nd, (root->nchild - off)*sizeof(Direc));
  112. mkdirec(nd, d);
  113. nd->name = atom(p);
  114. root->nchild++;
  115. return nd;
  116. }
  117. /*
  118. * Copy the tree src into dst.
  119. */
  120. void
  121. copydirec(Direc *dst, Direc *src)
  122. {
  123. int i, n;
  124. *dst = *src;
  125. if((src->mode & DMDIR) == 0)
  126. return;
  127. n = (src->nchild + Ndirblock - 1);
  128. n -= n%Ndirblock;
  129. dst->child = emalloc(n*sizeof(Direc));
  130. n = dst->nchild;
  131. for(i=0; i<n; i++)
  132. copydirec(&dst->child[i], &src->child[i]);
  133. }
  134. /*
  135. * Turn the Dbadname flag on for any entries
  136. * that have non-conforming names.
  137. */
  138. static void
  139. _checknames(Direc *d, int (*isbadname)(char*), int isroot)
  140. {
  141. int i;
  142. if(!isroot && isbadname(d->name))
  143. d->flags |= Dbadname;
  144. if(strcmp(d->name, "_conform.map") == 0)
  145. d->flags |= Dbadname;
  146. for(i=0; i<d->nchild; i++)
  147. _checknames(&d->child[i], isbadname, 0);
  148. }
  149. void
  150. checknames(Direc *d, int (*isbadname)(char*))
  151. {
  152. _checknames(d, isbadname, 1);
  153. }
  154. /*
  155. * Set the names to conform to 8.3
  156. * by changing them to numbers.
  157. * Plan 9 gets the right names from its
  158. * own directory entry.
  159. *
  160. * We used to write a _conform.map file to translate
  161. * names. Joliet should take care of most of the
  162. * interoperability with other systems now.
  163. */
  164. void
  165. convertnames(Direc *d, char* (*cvt)(char*, char*))
  166. {
  167. int i;
  168. char new[1024];
  169. if(d->flags & Dbadname)
  170. cvt(new, conform(d->name, d->mode & DMDIR));
  171. else
  172. cvt(new, d->name);
  173. d->confname = atom(new);
  174. for(i=0; i<d->nchild; i++)
  175. convertnames(&d->child[i], cvt);
  176. }
  177. /*
  178. * Sort a directory with a given comparison function.
  179. * After this is called on a tree, adddirec should not be,
  180. * since the entries may no longer be sorted as adddirec expects.
  181. */
  182. void
  183. dsort(Direc *d, int (*cmp)(const void*, const void*))
  184. {
  185. int i, n;
  186. n = d->nchild;
  187. qsort(d->child, n, sizeof(d[0]), cmp);
  188. for(i=0; i<n; i++)
  189. dsort(&d->child[i], cmp);
  190. }