pathname.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /* $Source: /u/mark/src/pax/RCS/pathname.c,v $
  2. *
  3. * $Revision: 1.2 $
  4. *
  5. * pathname.c - directory/pathname support functions
  6. *
  7. * DESCRIPTION
  8. *
  9. * These functions provide directory/pathname support for PAX
  10. *
  11. * AUTHOR
  12. *
  13. * Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
  14. *
  15. * Sponsored by The USENIX Association for public distribution.
  16. *
  17. * Copyright (c) 1989 Mark H. Colburn.
  18. * All rights reserved.
  19. *
  20. * Redistribution and use in source and binary forms are permitted
  21. * provided that the above copyright notice is duplicated in all such
  22. * forms and that any documentation, advertising materials, and other
  23. * materials related to such distribution and use acknowledge that the
  24. * software was developed * by Mark H. Colburn and sponsored by The
  25. * USENIX Association.
  26. *
  27. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  28. * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  29. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  30. *
  31. * $Log: pathname.c,v $
  32. * Revision 1.2 89/02/12 10:05:13 mark
  33. * 1.2 release fixes
  34. *
  35. * Revision 1.1 88/12/23 18:02:21 mark
  36. * Initial revision
  37. *
  38. */
  39. #ifndef lint
  40. static char *ident = "$Id: pathname.c,v 1.2 89/02/12 10:05:13 mark Exp $";
  41. static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
  42. #endif /* ! lint */
  43. /* Headers */
  44. #include "pax.h"
  45. /* dirneed - checks for the existance of directories and possibly create
  46. *
  47. * DESCRIPTION
  48. *
  49. * Dirneed checks to see if a directory of the name pointed to by name
  50. * exists. If the directory does exist, then dirneed returns 0. If
  51. * the directory does not exist and the f_dir_create flag is set,
  52. * then dirneed will create the needed directory, recursively creating
  53. * any needed intermediate directory.
  54. *
  55. * If f_dir_create is not set, then no directories will be created
  56. * and a value of -1 will be returned if the directory does not
  57. * exist.
  58. *
  59. * PARAMETERS
  60. *
  61. * name - name of the directory to create
  62. *
  63. * RETURNS
  64. *
  65. * Returns a 0 if the creation of the directory succeeded or if the
  66. * directory already existed. If the f_dir_create flag was not set
  67. * and the named directory does not exist, or the directory creation
  68. * failed, a -1 will be returned to the calling routine.
  69. */
  70. #ifdef __STDC__
  71. int dirneed(char *name)
  72. #else
  73. int dirneed(name)
  74. char *name;
  75. #endif
  76. {
  77. char *cp;
  78. char *last;
  79. int ok;
  80. static Stat sb;
  81. last = (char *)NULL;
  82. for (cp = name; *cp;) {
  83. if (*cp++ == '/') {
  84. last = cp;
  85. }
  86. }
  87. if (last == (char *)NULL) {
  88. return (STAT(".", &sb));
  89. }
  90. *--last = '\0';
  91. ok = STAT(*name ? name : ".", &sb) == 0
  92. ? ((sb.sb_mode & S_IFMT) == S_IFDIR)
  93. : (f_dir_create && dirneed(name) == 0 && dirmake(name, &sb) == 0);
  94. *last = '/';
  95. return (ok ? 0 : -1);
  96. }
  97. /* nameopt - optimize a pathname
  98. *
  99. * DESCRIPTION
  100. *
  101. * Confused by "<symlink>/.." twistiness. Returns the number of final
  102. * pathname elements (zero for "/" or ".") or -1 if unsuccessful.
  103. *
  104. * PARAMETERS
  105. *
  106. * char *begin - name of the path to optimize
  107. *
  108. * RETURNS
  109. *
  110. * Returns 0 if successful, non-zero otherwise.
  111. *
  112. */
  113. #ifdef __STDC__
  114. int nameopt(char *begin)
  115. #else
  116. int nameopt(begin)
  117. char *begin;
  118. #endif
  119. {
  120. char *name;
  121. char *item;
  122. int idx;
  123. int absolute;
  124. char *element[PATHELEM];
  125. absolute = (*(name = begin) == '/');
  126. idx = 0;
  127. for (;;) {
  128. if (idx == PATHELEM) {
  129. warn(begin, "Too many elements");
  130. return (-1);
  131. }
  132. while (*name == '/') {
  133. ++name;
  134. }
  135. if (*name == '\0') {
  136. break;
  137. }
  138. element[idx] = item = name;
  139. while (*name && *name != '/') {
  140. ++name;
  141. }
  142. if (*name) {
  143. *name++ = '\0';
  144. }
  145. if (strcmp(item, "..") == 0) {
  146. if (idx == 0) {
  147. if (!absolute) {
  148. ++idx;
  149. }
  150. } else if (strcmp(element[idx - 1], "..") == 0) {
  151. ++idx;
  152. } else {
  153. --idx;
  154. }
  155. } else if (strcmp(item, ".") != 0) {
  156. ++idx;
  157. }
  158. }
  159. if (idx == 0) {
  160. element[idx++] = absolute ? "" : ".";
  161. }
  162. element[idx] = (char *)NULL;
  163. name = begin;
  164. if (absolute) {
  165. *name++ = '/';
  166. }
  167. for (idx = 0; item = element[idx]; ++idx, *name++ = '/') {
  168. while (*item) {
  169. *name++ = *item++;
  170. }
  171. }
  172. *--name = '\0';
  173. return (idx);
  174. }
  175. /* dirmake - make a directory
  176. *
  177. * DESCRIPTION
  178. *
  179. * Dirmake makes a directory with the appropritate permissions.
  180. *
  181. * PARAMETERS
  182. *
  183. * char *name - Name of directory make
  184. * Stat *asb - Stat structure of directory to make
  185. *
  186. * RETURNS
  187. *
  188. * Returns zero if successful, -1 otherwise.
  189. *
  190. */
  191. #ifdef __STDC__
  192. int dirmake(char *name, Stat *asb)
  193. #else
  194. int dirmake(name, asb)
  195. char *name;
  196. Stat *asb;
  197. #endif
  198. {
  199. if (mkdir(name, (int) (asb->sb_mode & S_IPOPN)) < 0) {
  200. return (-1);
  201. }
  202. if (asb->sb_mode & S_IPEXE) {
  203. chmod(name, (int) (asb->sb_mode & S_IPERM));
  204. }
  205. if (f_owner) {
  206. chown(name, (int) asb->sb_uid, (int) asb->sb_gid);
  207. }
  208. return (0);
  209. }