mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-11 17:26:57 +02:00
Windows : comparer les chemins canonises, pas les chaines brutes
Windows expose le meme fichier sous plusieurs ecritures (forme courte 8.3 « ADMINI~1 » contre « Administrateur », casse, liens). Les deux comparaisons de chemins du premier lancement le supposaient identique des deux cotes : - runningPIDs ratait l'instance en cours -> on remplacait le binaire en croyant l'application arretee, elle continuait de tourner en ancienne version sans que rien ne l'indique. C'est le bug corrige en 0.6.12, revenu par une autre porte. - appFirstRun : l'application installee se serait prise pour une copie telechargee et se serait relancee, en BOUCLE INFINIE. Constate sur banc d'essai Windows (JEAN_HOME sous un chemin en forme courte).
This commit is contained in:
1 parent
1d58a7b1b9
commit
5728abf93e
1 file changed
+39
-10
@@ -82,11 +82,11 @@ func appFirstRun() bool {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if resolved, err := filepath.EvalSymlinks(exe); err == nil {
|
|
||||||
exe = resolved
|
|
||||||
}
|
|
||||||
target := installedExePath()
|
target := installedExePath()
|
||||||
if strings.EqualFold(exe, target) {
|
// canonPath des DEUX côtés : si l'égalité rate parce que les chemins sont
|
||||||
|
// écrits différemment (forme courte 8.3, casse, lien), l'application installée
|
||||||
|
// se prend pour une copie téléchargée et se relance… en boucle infinie.
|
||||||
|
if canonPath(exe) == canonPath(target) {
|
||||||
// On EST l'application installée. On en profite pour garantir que les
|
// On EST l'application installée. On en profite pour garantir que les
|
||||||
// raccourcis existent : sans ça, quelqu'un qui perd son raccourci ne
|
// raccourcis existent : sans ça, quelqu'un qui perd son raccourci ne
|
||||||
// retrouve plus AJEAN, et n'a aucune raison de relancer le fichier
|
// retrouve plus AJEAN, et n'a aucune raison de relancer le fichier
|
||||||
@@ -248,25 +248,54 @@ func replaceInstalled(target string) error {
|
|||||||
// runningPIDs liste les processus qui exécutent exactement ce fichier. On compare
|
// runningPIDs liste les processus qui exécutent exactement ce fichier. On compare
|
||||||
// le CHEMIN, pas le nom : tuer par nom d'image (« jean.exe ») emporterait aussi
|
// le CHEMIN, pas le nom : tuer par nom d'image (« jean.exe ») emporterait aussi
|
||||||
// le processus courant et toute autre copie sans rapport.
|
// le processus courant et toute autre copie sans rapport.
|
||||||
|
//
|
||||||
|
// La comparaison se fait ICI, sur des chemins canonisés, et non dans le script
|
||||||
|
// PowerShell : Windows expose le même fichier sous plusieurs écritures (forme
|
||||||
|
// courte 8.3 « ADMINI~1 » contre « Administrateur », casse variable, liens). Un
|
||||||
|
// simple -ieq entre chaînes rate alors l'instance en cours, et on remplace le
|
||||||
|
// binaire en croyant l'application arrêtée : elle continue de tourner en
|
||||||
|
// ancienne version, sans que rien ne l'indique. Constaté sur banc d'essai.
|
||||||
func runningPIDs(target string) []int {
|
func runningPIDs(target string) []int {
|
||||||
ps := fmt.Sprintf(`$t=%s
|
want := canonPath(target)
|
||||||
Get-Process -ErrorAction SilentlyContinue | ForEach-Object {
|
ps := `Get-Process -ErrorAction SilentlyContinue | ForEach-Object {
|
||||||
try { if ($_.Path -ieq $t) { $_.Id } } catch { }
|
try { if ($_.Path) { "$($_.Id)|$($_.Path)" } } catch { }
|
||||||
}`, psQuote(target))
|
}`
|
||||||
out, err := hideCmd(exec.Command("powershell", "-NoProfile", "-NonInteractive", "-Command", ps)).Output()
|
out, err := hideCmd(exec.Command("powershell", "-NoProfile", "-NonInteractive", "-Command", ps)).Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var pids []int
|
var pids []int
|
||||||
self := os.Getpid()
|
self := os.Getpid()
|
||||||
for _, line := range strings.Fields(string(out)) {
|
for _, line := range strings.Split(string(out), "\n") {
|
||||||
if n, err := strconv.Atoi(line); err == nil && n != self {
|
i := strings.IndexByte(line, '|')
|
||||||
|
if i < 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
n, err := strconv.Atoi(strings.TrimSpace(line[:i]))
|
||||||
|
if err != nil || n == self {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if canonPath(strings.TrimSpace(line[i+1:])) == want {
|
||||||
pids = append(pids, n)
|
pids = append(pids, n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pids
|
return pids
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// canonPath ramène un chemin Windows à une écriture unique et comparable :
|
||||||
|
// résolution des liens et de la forme courte 8.3 quand le fichier existe, puis
|
||||||
|
// minuscules (le système de fichiers est insensible à la casse).
|
||||||
|
func canonPath(p string) string {
|
||||||
|
p = strings.TrimSpace(p)
|
||||||
|
if p == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if long, err := filepath.EvalSymlinks(p); err == nil {
|
||||||
|
p = long
|
||||||
|
}
|
||||||
|
return strings.ToLower(filepath.Clean(p))
|
||||||
|
}
|
||||||
|
|
||||||
// stopProcesses arrête les instances listées, puis laisse le port se libérer :
|
// stopProcesses arrête les instances listées, puis laisse le port se libérer :
|
||||||
// sans cette attente, l'instance qu'on relance trouve :8090 encore occupé et se
|
// sans cette attente, l'instance qu'on relance trouve :8090 encore occupé et se
|
||||||
// contente d'ouvrir le navigateur sur une application en train de mourir.
|
// contente d'ouvrir le navigateur sur une application en train de mourir.
|
||||||
|
|||||||
Reference in new issue
Block a user