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); }