Thanks for the review. There's a lot of things you mention that I either didn't see (staring blind, you know) or that I didn't know of. On Tue, Dec 6, 2011 at 11:35 PM, Junio C Hamano <gitster@xxxxxxxxx> wrote: > Frans Klaver <fransklaver@xxxxxxxxx> writes: > >> +#ifndef WIN32 >> +static int is_in_group(gid_t gid) >> ... >> +static int have_read_execute_permissions(const char *path) >> +{ >> + struct stat s; >> + trace_printf("checking '%s'\n", path); >> + >> + if (stat(path, &s) < 0) { >> + ... >> + /* check world permissions */ >> + if ((s.st_mode&(S_IXOTH|S_IROTH)) == (S_IXOTH|S_IROTH)) >> + return 1; > > Hmm, do you need to do this with stat(2)? > > Wouldn't access(2) with R_OK|X_OK give you exactly what you want without > this much trouble? Probably. I'll use access instead in a reroll. > I also think that your permission check is incorrectly implemented. > > $ cd /var/tmp && date >j && chmod 044 j && ls -l j > ----r--r-- 1 junio junio 29 Dec 6 14:32 j > $ cat j > cat: j: Permission denied > $ su pogo > Password: > $ cat j > Tue Dec 6 14:32:23 PST 2011 > > That's a world-readable but unreadable-only-to-me file. Hmm, this is a case that didn't fit my expectations. Thanks for catching. >> +static void diagnose_execvp_eacces(const char *cmd, const char **argv) >> +{ >> + /* man 2 execve states that EACCES is returned for: > > /* > * Just a style, but we tend to write multi-line comment like > * this, without anything else on opening and closing lines of > * the comment block. > */ > >> + * - The file system is mounted noexec >> + */ >> + struct strbuf sb = STRBUF_INIT; >> + char *path = getenv("PATH"); >> + char *next; >> + >> + if (strchr(cmd, '/')) { >> + if (!have_read_execute_permissions(cmd)) >> + error("no read/execute permissions on '%s'\n", cmd); >> + return; >> + } > > Ok, execvp() failed and "cmd" has at least one slash, so we know we did > not look for it in $PATH. We check only one and return (did you need > getenv() in that case?). Obviously not. Missed that. > >> + for (;;) { >> + next = strchrnul(path, ':'); >> + if (path < next) >> + strbuf_add(&sb, path, next - path); >> + else >> + strbuf_addch(&sb, '.'); > > Nice touch that you did not forget an empty component on $PATH. Yes, that's a relic from me starting work based on one of your proposed patches[1]. So that one goes to you. [1] http://article.gmane.org/gmane.comp.version-control.git/171838 >> + if (!have_read_execute_permissions(sb.buf)) >> + error("no read/execute permissions on '%s'\n", sb.buf); > > Don't you want to continue here upon error, after resetting sb? You just > saw the directory is unreadble, so you know next file_exists() will fail > before you try it. Yes. I thought about that. I didn't do that because of the fact that I had to do more than just resetting sb. The path variable has to be updated as well. I had the choice of adding a level of indentation {}, duplicating the code, or just do a check I know before will fail. There's probably something to say for each one of them. I'll probably refactor that a bit more. >> + if (sb.len && sb.buf[sb.len - 1] != '/') >> + strbuf_addch(&sb, '/'); >> + strbuf_addstr(&sb, cmd); >> + >> + if (file_exists(sb.buf)) { >> + if (!have_read_execute_permissions(sb.buf)) >> + error("no read/execute permissions on '%s'\n", >> + sb.buf); >> + else >> + warn("file '%s' exists and permissions " >> + "seem OK.\nIf this is a script, see if you " >> + "have sufficient privileges to run the " >> + "interpreter", sb.buf); > > Does "warn()" do the right thing for multi-line strings like this? I don't know/remember. It seemed like a natural thing to do, but I'll find out. -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html