Пример #1
0
static int
max_backup_version(char *file, char *dir)
{
  DIR *dirp;
  struct dirent *dp;
  int highest_version;
  int this_version;
  int file_name_length;

  dirp = opendir (dir);
  if (!dirp)
    return 0;

  highest_version = 0;
  file_name_length = strlen (file);

  while ((dp = readdir (dirp)) != 0)
    {
      if (!REAL_DIR_ENTRY (dp) || NLENGTH (dp) <= file_name_length)
	continue;

      this_version = version_number (file, dp->d_name, file_name_length);
      if (this_version > highest_version)
	highest_version = this_version;
    }
  closedir (dirp);
  return highest_version;
}
Пример #2
0
TaskButton::TaskButton(IPane *parent, IPainter *backgroundPainter, IPainter *textPainter,
    IEventHandler *eventHandler, HWND window, TaskData &taskData)
  : mEventHandler(eventHandler)
  , mIconPainter(nullptr)
  , mMenu(nullptr)
  , mMenuWindow(nullptr)
  , mOverlayIconPainter(nullptr)
  , mTaskData(taskData)
  , mFlashInterval(0)
  , mWindow(window)
{
  mIconPosition = NRECT(NLENGTH(0, 0, 0), NLENGTH(0, 0, 0), NLENGTH(0, 0, 32), NLENGTH(0, 0, 32));
  mIconPainter = nCore::CreateImagePainter();
  mIconPainter->SetPosition(mIconPosition, nullptr);
  mIconPainter->SetImage(nCore::GetWindowIcon(window, 32));

  mOverlayIconPosition =
    NRECT(NLENGTH(0, 0, 16), NLENGTH(0, 0, 16), NLENGTH(0, 0, 32), NLENGTH(0, 0, 32));
  mOverlayIconPainter = nCore::CreateImagePainter();
  mOverlayIconPainter->SetPosition(mOverlayIconPosition, nullptr);

  PaneInitData initData;
  ZeroMemory(&initData, sizeof(PaneInitData));
  initData.cbSize = sizeof(PaneInitData);
  initData.messageHandler = this;
  IPainter *painters[] = { backgroundPainter, textPainter, mIconPainter, mOverlayIconPainter };
  initData.painters = painters;
  initData.numPainters = _countof(painters);
  initData.states = gButtonStates;
  initData.numStates = gNumButtonStates;
  mPane = parent->CreateChild(&initData);

  if (IsIconic(window)) {
    ActivateState(State::Minimized);
  }
  if (window == gActiveWindow) {
    ActivateState(State::Active);
  }

  wchar_t windowText[256];
  GetWindowText(window, windowText, 256);
  mPane->SetText(windowText);

  // Reset the system menu for the window
  mMenu = GetSystemMenu(mWindow, FALSE);
  if (!IsMenu(mMenu)) {
    GetSystemMenu(mWindow, TRUE);
    mMenu = GetSystemMenu(mWindow, FALSE);
  }
}
Пример #3
0
Файл: dir.c Проект: Chainie/mc
static int
handle_dirent (dir_list * list, const char *fltr, struct dirent *dp,
               struct stat *buf1, int next_free, int *link_to_dir, int *stale_link)
{
    vfs_path_t *vpath;

    if (dp->d_name[0] == '.' && dp->d_name[1] == 0)
        return 0;
    if (dp->d_name[0] == '.' && dp->d_name[1] == '.' && dp->d_name[2] == 0)
        return 0;
    if (!panels_options.show_dot_files && (dp->d_name[0] == '.'))
        return 0;
    if (!panels_options.show_backups && dp->d_name[NLENGTH (dp) - 1] == '~')
        return 0;

    vpath = vfs_path_from_str (dp->d_name);
    if (mc_lstat (vpath, buf1) == -1)
    {
        /*
         * lstat() fails - such entries should be identified by
         * buf1->st_mode being 0.
         * It happens on QNX Neutrino for /fs/cd0 if no CD is inserted.
         */
        memset (buf1, 0, sizeof (*buf1));
    }

    if (S_ISDIR (buf1->st_mode))
        tree_store_mark_checked (dp->d_name);

    /* A link to a file or a directory? */
    *link_to_dir = 0;
    *stale_link = 0;
    if (S_ISLNK (buf1->st_mode))
    {
        struct stat buf2;
        if (mc_stat (vpath, &buf2) == 0)
            *link_to_dir = S_ISDIR (buf2.st_mode) != 0;
        else
            *stale_link = 1;
    }
    vfs_path_free (vpath);
    if (!(S_ISDIR (buf1->st_mode) || *link_to_dir) && (fltr != NULL)
        && !mc_search (fltr, dp->d_name, MC_SEARCH_T_GLOB))
        return 0;

    /* Need to grow the *list? */
    if (next_free == list->size && !grow_list (list))
        return -1;

    return 1;
}
Пример #4
0
// Taken from tsid
uint32_t recurse(FILE *fmatched, char *dir)
{
    uint32_t matches = 0;
    dirent *dp;
    struct stat st;
    DIR    *dirp;
    char   nbuf[MAX_PATH_LEN];
    size_t len;

    SDEBUG("Recurse into directory " << dir << endl);

    dirp=opendir(dir);

    if (dirp==NULL)
    {
        SDEBUG(dir << " unreadable\n");
        return 0;
    }

    while ((dp=readdir(dirp)) != NULL)
    {
        if (!strcmp(dp->d_name,".") || !strcmp(dp->d_name,".."))
            continue;

        len=strlen(dir);
        if (len+NLENGTH(dp)+1 < MAX_PATH_LEN-1)
        {
            strcpy(nbuf,dir);
            if (len != 0) // dir = "" means current dir on Amiga
                nbuf[len++]='/';
            strcpy(nbuf+len, dp->d_name);

            stat(nbuf, &st);

            if (S_ISDIR(st.st_mode))
                matches += recurse(fmatched, nbuf); // recurse into directory

            if (S_ISREG(st.st_mode))
                matches += analyse(fmatched, nbuf); // add the file
        }
        else
        {
            SDEBUG(dir << "/" << dp->d_name << ": pathname too long\n");
        }
    }
    closedir(dirp);
    return matches;
}
Пример #5
0
/* Sends the complete directory listing, as well as the stat information */
static void
do_readdir (void)
{
    struct dirent *dirent;
    struct stat st;
    int handle, n;

    rpc_get (msock, RPC_INT, &handle, RPC_END);

    if (!handle) {
	rpc_send (msock, RPC_INT, 0, RPC_END);
	return;
    }

    /* We incremented it in opendir */
    handle--;

    while ((dirent = readdir (mcfs_DIR.dirs[handle]))) {
	int fname_len;
	char *fname;
	int length = NLENGTH (dirent);

	rpc_send (msock, RPC_INT, length, RPC_END);
	rpc_send (msock, RPC_BLOCK, length, dirent->d_name, RPC_END);
	fname_len =
	    strlen (mcfs_DIR.names[handle]) + strlen (dirent->d_name) + 2;
	fname = malloc (fname_len);
	snprintf (fname, fname_len, "%s/%s", mcfs_DIR.names[handle],
		  dirent->d_name);
	n = lstat (fname, &st);
	g_free (fname);
	send_status (n, errno);
	if (n >= 0)
	    send_stat_info (&st);
    }
    rpc_send (msock, RPC_INT, 0, RPC_END);
}
Пример #6
0
static char *
filename_completion_function (const char *text, int state, input_complete_t flags)
{
    static DIR *directory = NULL;
    static char *filename = NULL;
    static char *dirname = NULL;
    static char *users_dirname = NULL;
    static size_t filename_len;
    int isdir = 1, isexec = 0;
    static vfs_path_t *dirname_vpath = NULL;

    struct dirent *entry = NULL;

    SHOW_C_CTX ("filename_completion_function");

    if (text && (flags & INPUT_COMPLETE_SHELL_ESC))
    {
        char *u_text;
        char *result;
        char *e_result;

        u_text = strutils_shell_unescape (text);

        result = filename_completion_function (u_text, state, flags & (~INPUT_COMPLETE_SHELL_ESC));
        g_free (u_text);

        e_result = strutils_shell_escape (result);
        g_free (result);

        return e_result;
    }

    /* If we're starting the match process, initialize us a bit. */
    if (state == 0)
    {
        const char *temp;

        g_free (dirname);
        g_free (filename);
        g_free (users_dirname);
        vfs_path_free (dirname_vpath);

        if ((*text != '\0') && (temp = strrchr (text, PATH_SEP)) != NULL)
        {
            filename = g_strdup (++temp);
            dirname = g_strndup (text, temp - text);
        }
        else
        {
            dirname = g_strdup (".");
            filename = g_strdup (text);
        }

        /* We aren't done yet.  We also support the "~user" syntax. */

        /* Save the version of the directory that the user typed. */
        users_dirname = dirname;
        dirname = tilde_expand (dirname);
        canonicalize_pathname (dirname);
        dirname_vpath = vfs_path_from_str (dirname);

        /* Here we should do something with variable expansion
           and `command`.
           Maybe a dream - UNIMPLEMENTED yet. */

        directory = mc_opendir (dirname_vpath);
        filename_len = strlen (filename);
    }

    /* Now that we have some state, we can read the directory. */

    while (directory && (entry = mc_readdir (directory)))
    {
        if (!str_is_valid_string (entry->d_name))
            continue;

        /* Special case for no filename.
           All entries except "." and ".." match. */
        if (filename_len == 0)
        {
            if (DIR_IS_DOT (entry->d_name) || DIR_IS_DOTDOT (entry->d_name))
                continue;
        }
        else
        {
            /* Otherwise, if these match up to the length of filename, then
               it may be a match. */
            if ((entry->d_name[0] != filename[0]) ||
                ((NLENGTH (entry)) < filename_len) ||
                strncmp (filename, entry->d_name, filename_len))
                continue;
        }
        isdir = 1;
        isexec = 0;
        {
            struct stat tempstat;
            vfs_path_t *tmp_vpath;

            tmp_vpath = vfs_path_build_filename (dirname, entry->d_name, (char *) NULL);

            /* Unix version */
            if (mc_stat (tmp_vpath, &tempstat) == 0)
            {
                uid_t my_uid = getuid ();
                gid_t my_gid = getgid ();

                if (!S_ISDIR (tempstat.st_mode))
                {
                    isdir = 0;
                    if ((!my_uid && (tempstat.st_mode & 0111)) ||
                        (my_uid == tempstat.st_uid && (tempstat.st_mode & 0100)) ||
                        (my_gid == tempstat.st_gid && (tempstat.st_mode & 0010)) ||
                        (tempstat.st_mode & 0001))
                        isexec = 1;
                }
            }
            else
            {
                /* stat failed, strange. not a dir in any case */
                isdir = 0;
            }
            vfs_path_free (tmp_vpath);
        }
        if ((flags & INPUT_COMPLETE_COMMANDS) && (isexec || isdir))
            break;
        if ((flags & INPUT_COMPLETE_CD) && isdir)
            break;
        if (flags & (INPUT_COMPLETE_FILENAMES))
            break;
    }

    if (entry == NULL)
    {
        if (directory)
        {
            mc_closedir (directory);
            directory = NULL;
        }
        g_free (dirname);
        dirname = NULL;
        vfs_path_free (dirname_vpath);
        dirname_vpath = NULL;
        g_free (filename);
        filename = NULL;
        g_free (users_dirname);
        users_dirname = NULL;
        return NULL;
    }

    {
        GString *temp;

        temp = g_string_sized_new (16);

        if (users_dirname != NULL && (users_dirname[0] != '.' || users_dirname[1] != '\0'))
        {
            g_string_append (temp, users_dirname);

            /* We need a '/' at the end. */
            if (temp->str[temp->len - 1] != PATH_SEP)
                g_string_append_c (temp, PATH_SEP);
        }
        g_string_append (temp, entry->d_name);
        if (isdir)
            g_string_append_c (temp, PATH_SEP);

        return g_string_free (temp, FALSE);
    }
}
Пример #7
0
static enum numbered_backup_result
numbered_backup (char **buffer, size_t buffer_size, size_t filelen)
{
  enum numbered_backup_result result = BACKUP_IS_NEW;
  DIR *dirp;
  struct dirent *dp;
  char *buf = *buffer;
  size_t versionlenmax = 1;
  char *base = base_name (buf);
  size_t base_offset = base - buf;
  size_t baselen = base_len (base);

  /* Temporarily modify the buffer into its parent directory name,
     open the directory, and then restore the buffer.  */
  char tmp[sizeof "."];
  memcpy (tmp, base, sizeof ".");
  strcpy (base, ".");
  dirp = opendir (buf);
  memcpy (base, tmp, sizeof ".");
  strcpy (base + baselen, ".~1~");

  if (!dirp)
    return result;

  while ((dp = readdir (dirp)) != NULL)
    {
      char const *p;
      char *q;
      bool all_9s;
      size_t versionlen;
      size_t new_buflen;

      if (! REAL_DIR_ENTRY (dp) || NLENGTH (dp) < baselen + 4)
	continue;

      if (memcmp (buf + base_offset, dp->d_name, baselen + 2) != 0)
	continue;

      p = dp->d_name + baselen + 2;

      /* Check whether this file has a version number and if so,
	 whether it is larger.  Use string operations rather than
	 integer arithmetic, to avoid problems with integer overflow.  */

      if (! ('1' <= *p && *p <= '9'))
	continue;
      all_9s = (*p == '9');
      for (versionlen = 1; ISDIGIT (p[versionlen]); versionlen++)
	all_9s &= (p[versionlen] == '9');

      if (! (p[versionlen] == '~' && !p[versionlen + 1]
	     && (versionlenmax < versionlen
		 || (versionlenmax == versionlen
		     && memcmp (buf + filelen + 2, p, versionlen) <= 0))))
	continue;

      /* This directory has the largest version number seen so far.
	 Append this highest numbered extension to the file name,
	 prepending '0' to the number if it is all 9s.  */

      versionlenmax = all_9s + versionlen;
      result = (all_9s ? BACKUP_IS_LONGER : BACKUP_IS_SAME_LENGTH);
      new_buflen = filelen + 2 + versionlenmax + 1;
      if (buffer_size <= new_buflen)
	{
	  buf = xnrealloc (buf, 2, new_buflen);
	  buffer_size = new_buflen * 2;
	}
      q = buf + filelen;
      *q++ = '.';
      *q++ = '~';
      *q = '0';
      q += all_9s;
      memcpy (q, p, versionlen + 2);

      /* Add 1 to the version number.  */

      q += versionlen;
      while (*--q == '9')
	*q = '0';
      ++*q;
    }

  closedir (dirp);
  *buffer = buf;
  return result;
}
Пример #8
0
static char *
filename_completion_function (char *text, int state)
{
    static DIR *directory;
    static char *filename = NULL;
    static char *dirname = NULL;
    static char *users_dirname = NULL;
    static size_t filename_len;
    int isdir = 1, isexec = 0;

    struct dirent *entry = NULL;

    /* If we're starting the match process, initialize us a bit. */
    if (!state){
        const char *temp;

        g_free (dirname);
        g_free (filename);
        g_free (users_dirname);

	if ((*text) && (temp = strrchr (text, PATH_SEP))){
	    filename = g_strdup (++temp);
	    dirname = g_strndup (text, temp - text);
	} else {
	    dirname = g_strdup (".");
	    filename = g_strdup (text);
	}

        /* We aren't done yet.  We also support the "~user" syntax. */

        /* Save the version of the directory that the user typed. */
        users_dirname = dirname;
        {
	    dirname = tilde_expand (dirname);
	    canonicalize_pathname (dirname);
	    /* Here we should do something with variable expansion
	       and `command`.
	       Maybe a dream - UNIMPLEMENTED yet. */
        }
        directory = mc_opendir (dirname);
        filename_len = strlen (filename);
    }

    /* Now that we have some state, we can read the directory. */

    while (directory && (entry = mc_readdir (directory))){
        /* Special case for no filename.
	   All entries except "." and ".." match. */
        if (!filename_len){
	    if (!strcmp (entry->d_name, ".") || !strcmp (entry->d_name, ".."))
	        continue;
	} else {
	    /* Otherwise, if these match up to the length of filename, then
	       it may be a match. */
	    if ((entry->d_name[0] != filename[0]) ||
	        ((NLENGTH (entry)) < filename_len) ||
		strncmp (filename, entry->d_name, filename_len))
	        continue;
	}
	isdir = 1; isexec = 0;
	{
	    char *tmp = g_malloc (3 + strlen (dirname) + NLENGTH (entry));
	    struct stat tempstat;
	    
	    strcpy (tmp, dirname);
	    strcat (tmp, PATH_SEP_STR);
	    strcat (tmp, entry->d_name);
	    canonicalize_pathname (tmp);
	    /* Unix version */
	    if (!mc_stat (tmp, &tempstat)){
	    	uid_t my_uid = getuid ();
	    	gid_t my_gid = getgid ();
	    	
	        if (!S_ISDIR (tempstat.st_mode)){
	            isdir = 0;
	            if ((!my_uid && (tempstat.st_mode & 0111)) ||
	                (my_uid == tempstat.st_uid && (tempstat.st_mode & 0100)) ||
	                (my_gid == tempstat.st_gid && (tempstat.st_mode & 0010)) ||
	                (tempstat.st_mode & 0001))
	                isexec = 1;
	        }
	    }
	   g_free (tmp);
	}
	switch (look_for_executables)
	{
	    case 2: if (!isexec)
	    	        continue;
	    	    break;
	    case 1: if (!isexec && !isdir)
	    	        continue;
	    	    break;
	}
	if (ignore_filenames && !isdir)
	    continue;
	break;
    }

    if (!entry){
        if (directory){
	    mc_closedir (directory);
	    directory = NULL;
	}
	g_free (dirname);
	dirname = NULL;
	g_free (filename);
	filename = NULL;
	g_free (users_dirname);
	users_dirname = NULL;
        return NULL;
    } else {
        char *temp;

        if (users_dirname && (users_dirname[0] != '.' || users_dirname[1])){
	    int dirlen = strlen (users_dirname);
	    temp = g_malloc (3 + dirlen + NLENGTH (entry));
	    strcpy (temp, users_dirname);
	    /* We need a `/' at the end. */
	    if (users_dirname[dirlen - 1] != PATH_SEP){
	        temp[dirlen] = PATH_SEP;
	        temp[dirlen + 1] = 0;
	    }
	    strcat (temp, entry->d_name);
	} else {
	    temp = g_malloc (2 + NLENGTH (entry));
	    strcpy (temp, entry->d_name);
	}
	if (isdir)
	    strcat (temp, PATH_SEP_STR);
        return temp;
    }
}
Пример #9
0
Файл: dir.c Проект: Chainie/mc
int
do_reload_dir (const vfs_path_t * vpath, dir_list * list, sortfn * sort, int count,
               gboolean lc_reverse, gboolean lc_case_sensitive, gboolean exec_ff, const char *fltr)
{
    DIR *dirp;
    struct dirent *dp;
    int next_free = 0;
    int i, status, link_to_dir, stale_link;
    struct stat st;
    int marked_cnt;
    GHashTable *marked_files;
    const char *tmp_path;

    dirp = mc_opendir (vpath);
    if (dirp == NULL)
    {
        message (D_ERROR, MSG_ERROR, _("Cannot read directory contents"));
        clean_dir (list, count);
        return set_zero_dir (list) ? 1 : 0;
    }

    tree_store_start_check (vpath);

    marked_files = g_hash_table_new (g_str_hash, g_str_equal);
    alloc_dir_copy (list->size);
    for (marked_cnt = i = 0; i < count; i++)
    {
        dir_copy.list[i].fnamelen = list->list[i].fnamelen;
        dir_copy.list[i].fname = list->list[i].fname;
        dir_copy.list[i].f.marked = list->list[i].f.marked;
        dir_copy.list[i].f.dir_size_computed = list->list[i].f.dir_size_computed;
        dir_copy.list[i].f.link_to_dir = list->list[i].f.link_to_dir;
        dir_copy.list[i].f.stale_link = list->list[i].f.stale_link;
        dir_copy.list[i].sort_key = NULL;
        dir_copy.list[i].second_sort_key = NULL;
        if (list->list[i].f.marked)
        {
            g_hash_table_insert (marked_files, dir_copy.list[i].fname, &dir_copy.list[i]);
            marked_cnt++;
        }
    }

    /* Add ".." except to the root directory. The ".." entry
       (if any) must be the first in the list. */
    tmp_path = vfs_path_get_by_index (vpath, 0)->path;
    if (!
        (vfs_path_elements_count (vpath) == 1 && (tmp_path[0] == PATH_SEP)
         && (tmp_path[1] == '\0')))
    {
        if (!set_zero_dir (list))
        {
            clean_dir (list, count);
            clean_dir (&dir_copy, count);
            return next_free;
        }

        if (get_dotdot_dir_stat (vpath, &st))
            list->list[next_free].st = st;

        next_free++;
    }

    while ((dp = mc_readdir (dirp)))
    {
        status = handle_dirent (list, fltr, dp, &st, next_free, &link_to_dir, &stale_link);
        if (status == 0)
            continue;
        if (status == -1)
        {
            mc_closedir (dirp);
            /* Norbert (Feb 12, 1997):
               Just in case someone finds this memory leak:
               -1 means big trouble (at the moment no memory left),
               I don't bother with further cleanup because if one gets to
               this point he will have more problems than a few memory
               leaks and because one 'clean_dir' would not be enough (and
               because I don't want to spent the time to make it working,
               IMHO it's not worthwhile).
               clean_dir (&dir_copy, count);
             */
            tree_store_end_check ();
            g_hash_table_destroy (marked_files);
            return next_free;
        }

        list->list[next_free].f.marked = 0;

        /*
         * If we have marked files in the copy, scan through the copy
         * to find matching file.  Decrease number of remaining marks if
         * we copied one.
         */
        if (marked_cnt > 0)
        {
            if ((g_hash_table_lookup (marked_files, dp->d_name)))
            {
                list->list[next_free].f.marked = 1;
                marked_cnt--;
            }
        }

        list->list[next_free].fnamelen = NLENGTH (dp);
        list->list[next_free].fname = g_strndup (dp->d_name, list->list[next_free].fnamelen);
        list->list[next_free].f.link_to_dir = link_to_dir;
        list->list[next_free].f.stale_link = stale_link;
        list->list[next_free].f.dir_size_computed = 0;
        list->list[next_free].st = st;
        list->list[next_free].sort_key = NULL;
        list->list[next_free].second_sort_key = NULL;
        next_free++;
        if (!(next_free % 16))
            rotate_dash ();
    }
    mc_closedir (dirp);
    tree_store_end_check ();
    g_hash_table_destroy (marked_files);
    if (next_free)
    {
        do_sort (list, sort, next_free - 1, lc_reverse, lc_case_sensitive, exec_ff);
    }
    clean_dir (&dir_copy, count);
    return next_free;
}
Пример #10
0
Файл: dir.c Проект: Chainie/mc
int
do_load_dir (const vfs_path_t * vpath, dir_list * list, sortfn * sort, gboolean lc_reverse,
             gboolean lc_case_sensitive, gboolean exec_ff, const char *fltr)
{
    DIR *dirp;
    struct dirent *dp;
    int status, link_to_dir, stale_link;
    int next_free = 0;
    struct stat st;
    char *path;

    /* ".." (if any) must be the first entry in the list */
    if (!set_zero_dir (list))
        return next_free;

    if (get_dotdot_dir_stat (vpath, &st))
        list->list[next_free].st = st;
    next_free++;

    dirp = mc_opendir (vpath);
    if (dirp == NULL)
    {
        message (D_ERROR, MSG_ERROR, _("Cannot read directory contents"));
        return next_free;
    }

    tree_store_start_check (vpath);

    /* Do not add a ".." entry to the root directory */
    path = vfs_path_to_str (vpath);
    if ((path[0] == PATH_SEP) && (path[1] == '\0'))
        next_free--;
    g_free (path);

    while ((dp = mc_readdir (dirp)) != NULL)
    {
        status = handle_dirent (list, fltr, dp, &st, next_free, &link_to_dir, &stale_link);
        if (status == 0)
            continue;
        if (status == -1)
            goto ret;

        list->list[next_free].fnamelen = NLENGTH (dp);
        list->list[next_free].fname = g_strndup (dp->d_name, list->list[next_free].fnamelen);
        list->list[next_free].f.marked = 0;
        list->list[next_free].f.link_to_dir = link_to_dir;
        list->list[next_free].f.stale_link = stale_link;
        list->list[next_free].f.dir_size_computed = 0;
        list->list[next_free].st = st;
        list->list[next_free].sort_key = NULL;
        list->list[next_free].second_sort_key = NULL;
        next_free++;

        if ((next_free & 31) == 0)
            rotate_dash ();
    }

    if (next_free != 0)
        do_sort (list, sort, next_free - 1, lc_reverse, lc_case_sensitive, exec_ff);

  ret:
    mc_closedir (dirp);
    tree_store_end_check ();
    return next_free;
}