<commit_before>/* SPDX-License-Identifier: BSD-2-Clause */

static filesystem *
get_retained_fs_at(const char *path, const char **fs_path_ref)
{
   mountpoint *mp, *best_match = NULL;
   u32 len, pl, best_match_len = 0;
   filesystem *fs = NULL;
   mp_cursor cur;

   *fs_path_ref = NULL;
   pl = (u32)strlen(path);

   mountpoint_iter_begin(&cur);

   while ((mp = mountpoint_get_next(&cur))) {

      len = mp_check_match(mp->path, mp->path_len, path, pl);

      if (len > best_match_len) {
         best_match = mp;
         best_match_len = len;
      }
   }

   if (best_match) {
      *fs_path_ref = (best_match_len < pl) ? path + best_match_len - 1 : "/";
      fs = best_match->fs;
      retain_obj(fs);
   }

   mountpoint_iter_end(&cur);
   return fs;
}

STATIC const char *
__vfs_res_handle_dot_slash(const char *path)
{
   /* Handle the case of multiple slashes. */
   while (path[1] == '/')
      path++;

   /* Handle the case of a single '.' */
   if (path[1] == '.') {

      if (!path[2])
         return NULL; /* NULL means return 0 in the caller */

      if (path[2] == '/') {
         path += 2;   /* just skip the "/." substring */
      }
   }

   return path;
}

typedef struct {

   func_get_entry get_entry;
   vfs_path *rp;              /* pointer to the out-parameter vfs_path */
   const char *orig_path;     /* original path (used for offsets) */
   vfs_inode_ptr_t idir[32];  /* directory inodes */
   u8 pc_offs[32];            /* path component offset (from orig_path) */
   uptr ss;                   /* stack size */

} vfs_resolve_int_ctx;

STATIC inline void
__vfs_resolve_get_entry(vfs_resolve_int_ctx *ctx, const char *path)
{
   vfs_path *rp = ctx->rp;
   const uptr ss = ctx->ss;
   const char *pc = ctx->orig_path + (sptr) ctx->pc_offs[ss - 1];
   ASSERT(path - pc > 0);
   ctx->get_entry(rp->fs, ctx->idir[ss - 1], pc, path - pc, &rp->fs_path);
   rp->last_comp = pc;
}

STATIC inline int
__vfs_resolve_stack_push(vfs_resolve_int_ctx *ctx,
                         const char *path,
                         vfs_inode_ptr_t idir)
{
   if (ctx->ss == ARRAY_SIZE(ctx->idir))
      return -ENAMETOOLONG;

   ctx->pc_offs[ctx->ss] = (u8) (path - ctx->orig_path);
   ctx->idir[ctx->ss] = idir;
   ctx->ss++;
   return 0;
}

STATIC inline bool
__vfs_res_hit_dot_dot(const char *path)
{
   return path[0] == '.' && path[1] == '.' && (!path[2] || path[2] == '/');
}

STATIC int
__vfs_resolve(func_get_entry get_entry,
              const char *path,
              vfs_path *rp,
              bool res_last_sl)
{
   const fs_path_struct orig_fs_path = rp->fs_path;

   vfs_resolve_int_ctx ctx = {
      .get_entry = get_entry,
      .rp = rp,
      .orig_path = path,
      .ss = 0,
   };

   /* the vfs_path `rp` is assumed to be valid */
   ASSERT(rp->fs != NULL);
   ASSERT(rp->fs_path.inode != NULL);

   if (!*path)
      return -ENOENT;

   rp->last_comp = path;

   if (!(path = __vfs_res_handle_dot_slash(path - 1)))
      return 0;

   ++path;
   __vfs_resolve_stack_push(&ctx, path, rp->fs_path.inode);

   if (!*path) {
      /* path was just "/" */
      rp->last_comp = path;
      return 0;
   }

   while (*path) {

      if (__vfs_res_hit_dot_dot(path)) {

         if (ctx.ss > 2) {

            ctx.ss--;
            const char *pc = ctx.orig_path + (sptr) ctx.pc_offs[ctx.ss - 1];
            const char *oldpc = ctx.orig_path + (sptr) ctx.pc_offs[ctx.ss - 2];
            get_entry(rp->fs, ctx.idir[ctx.ss-2], oldpc, pc-oldpc-1, &rp->fs_path);
            rp->last_comp = oldpc;

         } else {

            rp->fs_path = orig_fs_path;

            if (ctx.ss > 1)
               ctx.ss--;
         }

         path += 2;

         if (!path[0] || (path[0] == '/' && !path[1]))
            return 0;

         path++;
         continue;
      }

      if (*path != '/') {
         path++;
         continue;
      }

      __vfs_resolve_get_entry(&ctx, path);
<commit_msg>[vfs][resolve] Extract __vfs_res_handle_dot_dot() from the main func<commit_after>/* SPDX-License-Identifier: BSD-2-Clause */

static filesystem *
get_retained_fs_at(const char *path, const char **fs_path_ref)
{
   mountpoint *mp, *best_match = NULL;
   u32 len, pl, best_match_len = 0;
   filesystem *fs = NULL;
   mp_cursor cur;

   *fs_path_ref = NULL;
   pl = (u32)strlen(path);

   mountpoint_iter_begin(&cur);

   while ((mp = mountpoint_get_next(&cur))) {

      len = mp_check_match(mp->path, mp->path_len, path, pl);

      if (len > best_match_len) {
         best_match = mp;
         best_match_len = len;
      }
   }

   if (best_match) {
      *fs_path_ref = (best_match_len < pl) ? path + best_match_len - 1 : "/";
      fs = best_match->fs;
      retain_obj(fs);
   }

   mountpoint_iter_end(&cur);
   return fs;
}

STATIC const char *
__vfs_res_handle_dot_slash(const char *path)
{
   /* Handle the case of multiple slashes. */
   while (path[1] == '/')
      path++;

   /* Handle the case of a single '.' */
   if (path[1] == '.') {

      if (!path[2])
         return NULL; /* NULL means return 0 in the caller */

      if (path[2] == '/') {
         path += 2;   /* just skip the "/." substring */
      }
   }

   return path;
}

typedef struct {

   func_get_entry get_entry;
   vfs_path *rp;                /* pointer to the out-parameter vfs_path */
   const char *orig_path;       /* original path (used for offsets) */
   fs_path_struct orig_fs_path; /* original value of rp->fs_path */
   vfs_inode_ptr_t idir[32];    /* directory inodes */
   u8 pc_offs[32];              /* path component offset (from orig_path) */
   uptr ss;                     /* stack size */

} vfs_resolve_int_ctx;

STATIC inline void
__vfs_resolve_get_entry(vfs_resolve_int_ctx *ctx, const char *path)
{
   vfs_path *rp = ctx->rp;
   const uptr ss = ctx->ss;
   const char *pc = ctx->orig_path + (sptr) ctx->pc_offs[ss - 1];
   ASSERT(path - pc > 0);
   ctx->get_entry(rp->fs, ctx->idir[ss - 1], pc, path - pc, &rp->fs_path);
   rp->last_comp = pc;
}

STATIC inline int
__vfs_resolve_stack_push(vfs_resolve_int_ctx *ctx,
                         const char *path,
                         vfs_inode_ptr_t idir)
{
   if (ctx->ss == ARRAY_SIZE(ctx->idir))
      return -ENAMETOOLONG;

   ctx->pc_offs[ctx->ss] = (u8) (path - ctx->orig_path);
   ctx->idir[ctx->ss] = idir;
   ctx->ss++;
   return 0;
}

STATIC inline bool
__vfs_res_hit_dot_dot(const char *path)
{
   return path[0] == '.' && path[1] == '.' && (!path[2] || path[2] == '/');
}

STATIC inline bool
__vfs_res_does_path_end_here(const char *path)
{
   return !path[0] || (path[0] == '/' && !path[1]);
}

/*
 * Returns `true` if the caller has to return 0, or `false` if the caller should
 * continue the loop.
 */
STATIC bool
__vfs_res_handle_dot_dot(vfs_resolve_int_ctx *ctx,
                         const char **path_ref)
{
   vfs_path *rp = ctx->rp;
   const char *orig_path = ctx->orig_path;

   if (ctx->ss > 2) {

      const uptr ss = --ctx->ss;
      const char *pc = orig_path + (sptr) ctx->pc_offs[ss - 1];
      const char *oldpc = orig_path + (sptr) ctx->pc_offs[ss - 2];
      ctx->get_entry(rp->fs, ctx->idir[ss-2], oldpc, pc-oldpc-1, &rp->fs_path);
      rp->last_comp = oldpc;

   } else {

      rp->fs_path = ctx->orig_fs_path;

      if (ctx->ss > 1)
         ctx->ss--;
   }

   *path_ref += 2;

   if (__vfs_res_does_path_end_here(*path_ref))
      return true;

   (*path_ref)++;
   return false;
}

STATIC int
__vfs_resolve(func_get_entry get_entry,
              const char *path,
              vfs_path *rp,
              bool res_last_sl)
{
   vfs_resolve_int_ctx ctx = {
      .get_entry = get_entry,
      .rp = rp,
      .orig_path = path,
      .orig_fs_path = rp->fs_path,
      .ss = 0,
   };

   /* the vfs_path `rp` is assumed to be valid */
   ASSERT(rp->fs != NULL);
   ASSERT(rp->fs_path.inode != NULL);

   if (!*path)
      return -ENOENT;

   rp->last_comp = path;

   if (!(path = __vfs_res_handle_dot_slash(path - 1)))
      return 0;

   ++path;
   __vfs_resolve_stack_push(&ctx, path, rp->fs_path.inode);

   if (!*path) {
      /* path was just "/" */
      rp->last_comp = path;
      return 0;
   }

   while (*path) {

      if (__vfs_res_hit_dot_dot(path)) {
         if (__vfs_res_handle_dot_dot(&ctx, &path))
            return 0;
         continue;
      }

      if (*path != '/') {
         path++;
         continue;
      }

      __vfs_resolve_get_entry(&ctx, path);

{'fraction_non_alphanumeric': 0.14948943243885063, 'fraction_numerical': 0.010092614580859654, 'mean_word_length': 2.197798025816249, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 83, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1658303', 'n_tokens_mistral': 3235, 'n_tokens_neox': 3094, 'n_words': 702}