THIS IS A TEST INSTANCE ONLY! REPOSITORIES CAN BE DELETED AT ANY TIME!

Git Source Code Mirror - This is a publish-only repository and all pull requests are ignored. Please follow Documentation/SubmittingPatches procedure for any of your improvements.
git
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

324 lines
9.3KB

  1. #include "cache.h"
  2. static int threaded_check_leading_path(struct cache_def *cache, const char *name, int len);
  3. static int threaded_has_dirs_only_path(struct cache_def *cache, const char *name, int len, int prefix_len);
  4. /*
  5. * Returns the length (on a path component basis) of the longest
  6. * common prefix match of 'name_a' and 'name_b'.
  7. */
  8. static int longest_path_match(const char *name_a, int len_a,
  9. const char *name_b, int len_b,
  10. int *previous_slash)
  11. {
  12. int max_len, match_len = 0, match_len_prev = 0, i = 0;
  13. max_len = len_a < len_b ? len_a : len_b;
  14. while (i < max_len && name_a[i] == name_b[i]) {
  15. if (name_a[i] == '/') {
  16. match_len_prev = match_len;
  17. match_len = i;
  18. }
  19. i++;
  20. }
  21. /*
  22. * Is 'name_b' a substring of 'name_a', the other way around,
  23. * or is 'name_a' and 'name_b' the exact same string?
  24. */
  25. if (i >= max_len && ((len_a > len_b && name_a[len_b] == '/') ||
  26. (len_a < len_b && name_b[len_a] == '/') ||
  27. (len_a == len_b))) {
  28. match_len_prev = match_len;
  29. match_len = i;
  30. }
  31. *previous_slash = match_len_prev;
  32. return match_len;
  33. }
  34. static struct cache_def default_cache = CACHE_DEF_INIT;
  35. static inline void reset_lstat_cache(struct cache_def *cache)
  36. {
  37. strbuf_reset(&cache->path);
  38. cache->flags = 0;
  39. /*
  40. * The track_flags and prefix_len_stat_func members is only
  41. * set by the safeguard rule inside lstat_cache()
  42. */
  43. }
  44. #define FL_DIR (1 << 0)
  45. #define FL_NOENT (1 << 1)
  46. #define FL_SYMLINK (1 << 2)
  47. #define FL_LSTATERR (1 << 3)
  48. #define FL_ERR (1 << 4)
  49. #define FL_FULLPATH (1 << 5)
  50. /*
  51. * Check if name 'name' of length 'len' has a symlink leading
  52. * component, or if the directory exists and is real, or not.
  53. *
  54. * To speed up the check, some information is allowed to be cached.
  55. * This can be indicated by the 'track_flags' argument, which also can
  56. * be used to indicate that we should check the full path.
  57. *
  58. * The 'prefix_len_stat_func' parameter can be used to set the length
  59. * of the prefix, where the cache should use the stat() function
  60. * instead of the lstat() function to test each path component.
  61. */
  62. static int lstat_cache_matchlen(struct cache_def *cache,
  63. const char *name, int len,
  64. int *ret_flags, int track_flags,
  65. int prefix_len_stat_func)
  66. {
  67. int match_len, last_slash, last_slash_dir, previous_slash;
  68. int save_flags, ret;
  69. struct stat st;
  70. if (cache->track_flags != track_flags ||
  71. cache->prefix_len_stat_func != prefix_len_stat_func) {
  72. /*
  73. * As a safeguard rule we clear the cache if the
  74. * values of track_flags and/or prefix_len_stat_func
  75. * does not match with the last supplied values.
  76. */
  77. reset_lstat_cache(cache);
  78. cache->track_flags = track_flags;
  79. cache->prefix_len_stat_func = prefix_len_stat_func;
  80. match_len = last_slash = 0;
  81. } else {
  82. /*
  83. * Check to see if we have a match from the cache for
  84. * the 2 "excluding" path types.
  85. */
  86. match_len = last_slash =
  87. longest_path_match(name, len, cache->path.buf,
  88. cache->path.len, &previous_slash);
  89. *ret_flags = cache->flags & track_flags & (FL_NOENT|FL_SYMLINK);
  90. if (!(track_flags & FL_FULLPATH) && match_len == len)
  91. match_len = last_slash = previous_slash;
  92. if (*ret_flags && match_len == cache->path.len)
  93. return match_len;
  94. /*
  95. * If we now have match_len > 0, we would know that
  96. * the matched part will always be a directory.
  97. *
  98. * Also, if we are tracking directories and 'name' is
  99. * a substring of the cache on a path component basis,
  100. * we can return immediately.
  101. */
  102. *ret_flags = track_flags & FL_DIR;
  103. if (*ret_flags && len == match_len)
  104. return match_len;
  105. }
  106. /*
  107. * Okay, no match from the cache so far, so now we have to
  108. * check the rest of the path components.
  109. */
  110. *ret_flags = FL_DIR;
  111. last_slash_dir = last_slash;
  112. if (len > cache->path.len)
  113. strbuf_grow(&cache->path, len - cache->path.len);
  114. while (match_len < len) {
  115. do {
  116. cache->path.buf[match_len] = name[match_len];
  117. match_len++;
  118. } while (match_len < len && name[match_len] != '/');
  119. if (match_len >= len && !(track_flags & FL_FULLPATH))
  120. break;
  121. last_slash = match_len;
  122. cache->path.buf[last_slash] = '\0';
  123. if (last_slash <= prefix_len_stat_func)
  124. ret = stat(cache->path.buf, &st);
  125. else
  126. ret = lstat(cache->path.buf, &st);
  127. if (ret) {
  128. *ret_flags = FL_LSTATERR;
  129. if (errno == ENOENT)
  130. *ret_flags |= FL_NOENT;
  131. } else if (S_ISDIR(st.st_mode)) {
  132. last_slash_dir = last_slash;
  133. continue;
  134. } else if (S_ISLNK(st.st_mode)) {
  135. *ret_flags = FL_SYMLINK;
  136. } else {
  137. *ret_flags = FL_ERR;
  138. }
  139. break;
  140. }
  141. /*
  142. * At the end update the cache. Note that max 3 different
  143. * path types, FL_NOENT, FL_SYMLINK and FL_DIR, can be cached
  144. * for the moment!
  145. */
  146. save_flags = *ret_flags & track_flags & (FL_NOENT|FL_SYMLINK);
  147. if (save_flags && last_slash > 0) {
  148. cache->path.buf[last_slash] = '\0';
  149. cache->path.len = last_slash;
  150. cache->flags = save_flags;
  151. } else if ((track_flags & FL_DIR) && last_slash_dir > 0) {
  152. /*
  153. * We have a separate test for the directory case,
  154. * since it could be that we have found a symlink or a
  155. * non-existing directory and the track_flags says
  156. * that we cannot cache this fact, so the cache would
  157. * then have been left empty in this case.
  158. *
  159. * But if we are allowed to track real directories, we
  160. * can still cache the path components before the last
  161. * one (the found symlink or non-existing component).
  162. */
  163. cache->path.buf[last_slash_dir] = '\0';
  164. cache->path.len = last_slash_dir;
  165. cache->flags = FL_DIR;
  166. } else {
  167. reset_lstat_cache(cache);
  168. }
  169. return match_len;
  170. }
  171. static int lstat_cache(struct cache_def *cache, const char *name, int len,
  172. int track_flags, int prefix_len_stat_func)
  173. {
  174. int flags;
  175. (void)lstat_cache_matchlen(cache, name, len, &flags, track_flags,
  176. prefix_len_stat_func);
  177. return flags;
  178. }
  179. #define USE_ONLY_LSTAT 0
  180. /*
  181. * Return non-zero if path 'name' has a leading symlink component
  182. */
  183. int threaded_has_symlink_leading_path(struct cache_def *cache, const char *name, int len)
  184. {
  185. return lstat_cache(cache, name, len, FL_SYMLINK|FL_DIR, USE_ONLY_LSTAT) & FL_SYMLINK;
  186. }
  187. /*
  188. * Return non-zero if path 'name' has a leading symlink component
  189. */
  190. int has_symlink_leading_path(const char *name, int len)
  191. {
  192. return threaded_has_symlink_leading_path(&default_cache, name, len);
  193. }
  194. /*
  195. * Return zero if path 'name' has a leading symlink component or
  196. * if some leading path component does not exists.
  197. *
  198. * Return -1 if leading path exists and is a directory.
  199. *
  200. * Return path length if leading path exists and is neither a
  201. * directory nor a symlink.
  202. */
  203. int check_leading_path(const char *name, int len)
  204. {
  205. return threaded_check_leading_path(&default_cache, name, len);
  206. }
  207. /*
  208. * Return zero if path 'name' has a leading symlink component or
  209. * if some leading path component does not exists.
  210. *
  211. * Return -1 if leading path exists and is a directory.
  212. *
  213. * Return path length if leading path exists and is neither a
  214. * directory nor a symlink.
  215. */
  216. static int threaded_check_leading_path(struct cache_def *cache, const char *name, int len)
  217. {
  218. int flags;
  219. int match_len = lstat_cache_matchlen(cache, name, len, &flags,
  220. FL_SYMLINK|FL_NOENT|FL_DIR, USE_ONLY_LSTAT);
  221. if (flags & FL_NOENT)
  222. return 0;
  223. else if (flags & FL_DIR)
  224. return -1;
  225. else
  226. return match_len;
  227. }
  228. /*
  229. * Return non-zero if all path components of 'name' exists as a
  230. * directory. If prefix_len > 0, we will test with the stat()
  231. * function instead of the lstat() function for a prefix length of
  232. * 'prefix_len', thus we then allow for symlinks in the prefix part as
  233. * long as those points to real existing directories.
  234. */
  235. int has_dirs_only_path(const char *name, int len, int prefix_len)
  236. {
  237. return threaded_has_dirs_only_path(&default_cache, name, len, prefix_len);
  238. }
  239. /*
  240. * Return non-zero if all path components of 'name' exists as a
  241. * directory. If prefix_len > 0, we will test with the stat()
  242. * function instead of the lstat() function for a prefix length of
  243. * 'prefix_len', thus we then allow for symlinks in the prefix part as
  244. * long as those points to real existing directories.
  245. */
  246. static int threaded_has_dirs_only_path(struct cache_def *cache, const char *name, int len, int prefix_len)
  247. {
  248. return lstat_cache(cache, name, len,
  249. FL_DIR|FL_FULLPATH, prefix_len) &
  250. FL_DIR;
  251. }
  252. static struct strbuf removal = STRBUF_INIT;
  253. static void do_remove_scheduled_dirs(int new_len)
  254. {
  255. while (removal.len > new_len) {
  256. removal.buf[removal.len] = '\0';
  257. if (rmdir(removal.buf))
  258. break;
  259. do {
  260. removal.len--;
  261. } while (removal.len > new_len &&
  262. removal.buf[removal.len] != '/');
  263. }
  264. removal.len = new_len;
  265. }
  266. void schedule_dir_for_removal(const char *name, int len)
  267. {
  268. int match_len, last_slash, i, previous_slash;
  269. match_len = last_slash = i =
  270. longest_path_match(name, len, removal.buf, removal.len,
  271. &previous_slash);
  272. /* Find last slash inside 'name' */
  273. while (i < len) {
  274. if (name[i] == '/')
  275. last_slash = i;
  276. i++;
  277. }
  278. /*
  279. * If we are about to go down the directory tree, we check if
  280. * we must first go upwards the tree, such that we then can
  281. * remove possible empty directories as we go upwards.
  282. */
  283. if (match_len < last_slash && match_len < removal.len)
  284. do_remove_scheduled_dirs(match_len);
  285. /*
  286. * If we go deeper down the directory tree, we only need to
  287. * save the new path components as we go down.
  288. */
  289. if (match_len < last_slash)
  290. strbuf_add(&removal, &name[match_len], last_slash - match_len);
  291. }
  292. void remove_scheduled_dirs(void)
  293. {
  294. do_remove_scheduled_dirs(0);
  295. }