/* link-tree.c:
 *
 ****************************************************************
 * Copyright (C) 2003 Tom Lord
 *
 * See the file "COPYING" for further information about
 * the copyright and warranty status of this work.
 */


#include "hackerlab/char/str.h"
#include "hackerlab/fs/file-names.h"
#include "hackerlab/vu/safe.h"
#include "tla/libfsutils/dir-listing.h"
#include "tla/libfsutils/copy-file.h"
#include "tla/libfsutils/link-target.h"
#include "tla/libfsutils/link-tree.h"



void
build_link_tree (t_uchar * from, t_uchar * to, int full_meta)
{
  struct stat statb;

  safe_lstat (from, &statb);

  if (S_ISDIR (statb.st_mode))
    {
      t_ulong desired_mode;
      rel_table contents = rel_table_nil;
      int x;

      if (full_meta)
        {
          desired_mode = (statb.st_mode & 07777);
        }
      else
        {
          desired_mode = (statb.st_mode & 0777);
        }

      safe_mkdir (to, desired_mode);
      safe_chmod (to, desired_mode);

      if (full_meta)
        {
          safe_chown (to, statb.st_uid, statb.st_gid);
        }

      contents = directory_files (from);

      for (x = 0; x < rel_n_records (contents); ++x)
        {
          if (str_cmp (".", rel_peek_str (contents, x, 0)) && str_cmp ("..", rel_peek_str (contents, x, 0)))
            {
              t_uchar * sub_from = 0;
              t_uchar * sub_to = 0;

              sub_from = file_name_in_vicinity (0, from, rel_peek_str (contents, x, 0));
              sub_to = file_name_in_vicinity (0, to, rel_peek_str (contents, x, 0));

              build_link_tree (sub_from, sub_to, full_meta);

              lim_free (0, sub_from);
              lim_free (0, sub_to);
            }
        }

      rel_free_table (contents);
    }
  else if (S_ISLNK (statb.st_mode))
    {
      copy_symlink (from, to);
    }
  else
    {
      safe_link (from, to);
    }
}


void
build_partial_link_tree (t_uchar * from,
                         t_uchar * to,
                         rel_table inventory,
                         int full_meta)
{
  int x;
  struct stat statb;

  /* inventory must be sorted and must include directories
   */

  for (x = -1; x < rel_n_records (inventory); ++x)
    {
      t_uchar * from_path = 0;
      t_uchar * to_path = 0;

      if (x == -1)
        {
          from_path = str_save (0, from);
          to_path = str_save (0, to);
        }
      else
        {
          const t_uchar * rel_path;

          rel_path = rel_peek_str (inventory, x, 0);
          from_path = file_name_in_vicinity (0, from, rel_path);
          to_path = file_name_in_vicinity (0, to, rel_path);
        }

      safe_lstat (from_path, &statb);

      if (S_ISDIR (statb.st_mode))
        {
          t_ulong desired_mode;

          if (full_meta)
            {
              desired_mode = (statb.st_mode & 07777);
            }
          else
            {
              desired_mode = (statb.st_mode & 0777);
            }

          safe_mkdir (to_path, desired_mode);
          safe_chmod (to_path, desired_mode);

          if (full_meta)
            {
              safe_chown (to_path, statb.st_uid, statb.st_gid);
            }
        }
      else if (S_ISLNK (statb.st_mode))
        {
          copy_symlink (from_path, to_path);
        }
      else
        {
          safe_link (from_path, to_path);
        }

      lim_free (0, from_path);
      lim_free (0, to_path);
    }
}



/* tag: Tom Lord Fri May 30 15:11:13 2003 (link-tree.c)
 */
