(candidate string)
| 181 | } |
| 182 | |
| 183 | func resolveFFmpegExecutableCandidate(candidate string) (string, error) { |
| 184 | candidate = filepath.Clean(strings.TrimSpace(candidate)) |
| 185 | if candidate == "" { |
| 186 | return "", errors.New("empty candidate") |
| 187 | } |
| 188 | |
| 189 | info, err := ffmpegToolchainStat(candidate) |
| 190 | if err != nil { |
| 191 | return "", err |
| 192 | } |
| 193 | if info.IsDir() { |
| 194 | nested := filepath.Join(candidate, filepath.Base(candidate)) |
| 195 | nestedInfo, nestedErr := ffmpegToolchainStat(nested) |
| 196 | if nestedErr != nil { |
| 197 | return "", nestedErr |
| 198 | } |
| 199 | if nestedInfo.Mode().IsRegular() && nestedInfo.Mode().Perm()&0o111 != 0 { |
| 200 | return nested, nil |
| 201 | } |
| 202 | return "", fmt.Errorf("%s is a directory without executable binary", candidate) |
| 203 | } |
| 204 | if !info.Mode().IsRegular() { |
| 205 | return "", fmt.Errorf("%s is not a regular file", candidate) |
| 206 | } |
| 207 | if info.Mode().Perm()&0o111 == 0 { |
| 208 | return "", fmt.Errorf("%s is not executable", candidate) |
| 209 | } |
| 210 | return candidate, nil |
| 211 | } |
| 212 | |
| 213 | // resolveExecutableCandidate 保留给同包旧测试使用。 |
| 214 | func resolveExecutableCandidate(candidate string) string { |
no test coverage detected