next up previous contents
suivant: arch/i386/kernel/ monter: La résolution des liens précédent: La résolution des liens   Table des matières

fs/


$\bullet$ namei.c :


/*
** fonction partagée par les deux systèmes de résolution
*/
int execute_alink(struct s_readalink *li, char *buf, int buflen)
{
  char c = ' ';
  mm_segment_t old_fs;
  int len, pid, error, pid_waited, exit_status;

  error = do_pipe(li->pipe);
  if (error < 0) {
    return error;
  }

  /*
  ** nous lançons un nouveau thread kernel qui exécutera la fonction
  ** passée en premier argument
  */
  error = (pid = kernel_thread(fn_readalink, (void *)li, SIGCHLD));

  old_fs = get_fs();
  set_fs(KERNEL_DS);

  if (pid <= 0)
    goto out_error;
  if ((error = sys_close(li->pipe[1])) != 0)
    goto out_error;

  /*
  ** nous recopions la sortie standard du thread kernel à partir
  ** du pipe dans le buffer prévu à cet effet
  */
  error = 0;
  for (len = 0; (len < buflen) && (c != '\0'); ++len) {
    if ((error = sys_read(li->pipe[0], &c, 1)) > 0) {
      buf[len] = c;
    }
    else {
      if (error == -EINTR) {
        --len;
      }
      else {
        if (error < 0)
          goto out_error;
        break ;
      }
    }
  }

  /*
  ** nous attendons la fin de l'exécution du fils
  */
  pid_waited = -EINTR;
  while ((pid_waited == -EINTR) ||
         ((pid_waited > 0) && (pid_waited != pid))) {
    pid_waited = sys_wait4(pid, &exit_status, 0, NULL);
  }

  /*
  ** nous récupérons son exit_status afin de s'assurer qu'il
  ** a terminé sans problème
  */
  exit_status = (((unsigned int)exit_status) >> 8) & 0x0ff;
  if (exit_status == 0)
    error = len;
  else
    error = -EIO;

  goto out_result;

out_error:
  sys_close(li->pipe[1]);

out_result:
  sys_close(li->pipe[0]);
  set_fs(old_fs);
  return error;
}

La fonction fn_readalink peut se résumer avec le code suivant (la gestion des retours d'erreur à été supprimée pour plus de clarté) :

int                     fn_readalink(struct s_readalink *linkinfo)
{
  char                  *argv[] = { (char *)(linkinfo->linkvalue),
                                    (char *)(linkinfo->linkpath),
				    NULL };
  char                  *envp[linkinfo->sizeenvp];


  /* for sur linkinfo->bufenvp pour remplir envp */
  ...
  sys_close(0);
  sys_close(linkinfo->pipe[0]);
  sys_dup2(linkinfo->pipe[1], 1);
  ...
  return execve(argv[0], argv, envp);
}


next up previous contents
suivant: arch/i386/kernel/ monter: La résolution des liens précédent: La résolution des liens   Table des matières