free(tmp_path);
}
+/* ls3_get_trimmed_path_and_depth - Trims the desired path.
+ * For example, when we have a “path” filter, it contains a path,
+ * but this does not mean that the resulting path from the attribute
+ * will not contain this path, so we need to trim the path from the
+ * filter and leave only the final path.
+ *
+ * ex: (/path/from/filter/dir1/dir11/dir111/file -> dir1/dir11/dir111/file)
+ */
+static void
+ ls3_stats_get_trimmed_path_and_depth(struct ls3_object_attrs *loa_all,
+ char *path, char **trimmed_path,
+ int *depth)
+{
+ char *sub_path = NULL;
+ const char *original_sub_path;
+ const char *last_slash;
+ const char *last_sub_path_slash = NULL;
+ size_t offset_from_start;
+ int count = 0;
+
+ if (!path || !dir_stats->lsdg_start_path)
+ LS3_FATAL("path name or start path is NULL\n");
+
+ /* Find the last slash in dir_stats->lsdg_start_path */
+ last_slash = strrchr(dir_stats->lsdg_start_path, '/');
+
+ /* if there is no slash, then simply cut it off to the beginning
+ * of dir_stats->lsdg_start_path
+ */
+ if (!last_slash) {
+ sub_path = path;
+ } else {
+ offset_from_start = last_slash - dir_stats->lsdg_start_path + 1;
+ sub_path = path + offset_from_start;
+ }
+
+ original_sub_path = sub_path;
+
+ /* Calculate the depth and at the same time look
+ * for the last slash in sub_path (for subsequent cutting)
+ */
+ while (*sub_path) {
+ if (*sub_path == '/') {
+ count++;
+ last_sub_path_slash = sub_path;
+ }
+ sub_path++;
+ }
+
+ if ((loa_all->loa_mode & S_IFDIR) &&
+ (last_sub_path_slash != sub_path + strlen(sub_path) - 1))
+ count++;
+ else if (last_sub_path_slash == sub_path + strlen(sub_path) - 1)
+ count--;
+
+ *depth = (count == 0) ? 0 : count;
+
+ /* Trim the path to the last slash, if it exists */
+ if (loa_all->loa_mode & S_IFDIR)
+ *trimmed_path = xstrdup(original_sub_path);
+ else if (last_sub_path_slash)
+ *trimmed_path = xstrndup(original_sub_path,
+ last_sub_path_slash -
+ original_sub_path);
+ else
+ *trimmed_path = xstrdup(original_sub_path);
+}
+
+/* ls3_stats_dir_split_path - Splits a path into an array of names.
+ * Ex: dir1/dir11/dir111/dir1111/file -> ["dir1", "dir11", "dir111"]
+ * This is necessary in order to track the entire chain of pointers
+ * and increase the size counters in the future, but not more than
+ * the maximum specified depth.
+ */
+static char** ls3_stats_dir_split_path(const char *path, int *count)
+{
+ const char *tmp_patch = path;
+ int max_depth = dir_stats->lsdg_max_depth;
+ int dir_count = 0;
+ char **result;
+ int i;
+
+ *count = 0;
+ if (!path || max_depth <= 0)
+ return NULL;
+
+ if (strlen(path) == 0)
+ return NULL;
+
+
+ while (*tmp_patch) {
+ if (*tmp_patch == '/')
+ dir_count++;
+
+ tmp_patch++;
+ }
+
+ tmp_patch = path; /* pointer reset */
+ dir_count++;
+
+ if (dir_count < max_depth)
+ max_depth = dir_count;
+
+ result = (char**)xcalloc(max_depth, sizeof(char*));
+ for (i = 0; i < max_depth; i++) {
+ const char *next_slash = strchr(tmp_patch, '/');
+ size_t length = next_slash ? (next_slash - tmp_patch) :
+ (path + strlen(path) - tmp_patch);
+
+ result[i] = (char*) xcalloc(length + 1, sizeof(char));
+ strncpy(result[i], tmp_patch, length);
+ result[i][length] = '\0';
+
+ if (!next_slash)
+ break;
+
+ tmp_patch = next_slash + 1;
+ }
+
+ *count = max_depth;
+ return result;
+}
+
void ls3_stats_dir_init(void)
{
int rc;