Bug: chmod() doesn't understand permissions as symbolic attributes (like "u+x")


#1

Hi,

Here’s a small test program:

#!/usr/local/bin/L

#lang L

void main() {
	FILE f;
	int ret;

	unlink("test_chmod");

	f=open("test_chmod", "w");
	close(f);
	puts("After creation:");
	system("ls -l test_chmod");

	ret=chmod("test_chmod", "u+x");
	puts("ret=${ret}");
	puts("After L chmod u+x:");
	system("ls -l test_chmod");

	ret=chmod("test_chmod", "744");
	puts("ret=${ret}");
	puts("After L chmod 744:");
	system("ls -l test_chmod");
}

The result is:

After creation:
-rw-r--r-- 1 GNX 1000 0 25 mars  16:07 test_chmod
ret=-1
After L chmod u+x:
-rw-r--r-- 1 GNX 1000 0 25 mars  16:07 test_chmod
ret=0
After L chmod 744:
-rwxr--r-- 1 GNX 1000 0 25 mars  16:07 test_chmod

OK, so when we pass the permissions as numerical octal, it works, but it fails when we use symbolic string as the documentation claims:

Permissions can be the octal code that chmod(1) uses, or symbolic attributes that chmod(1) uses of the form [ugo]?[[±=][rwxst],[…]], where multiple symbolic attributes can be separated by commas (example: u+s,go-rw add sticky bit for user, remove read and write permissions for group and other).

If I look at the source file tcl/libl.tcl (I guess that’s the one involved):

int
chmod(string path, string permissions)
{
	string	err;

	try {
		File_attributes(path, permissions: "0${permissions}");
		return (0);
	} catch (&err) {
		stdio_lasterr = err;
		return (-1);
	}
}

This extra “0”, probably intended to force octal interpretation of the number (but is it really needed?) doesn’t look good when permissions is symbolic…


#2

Hi GNX,

Fantastic bug report, you are right.

Seems like something like

if (permissions =~ /^\d/) {
    File_attributes(path, permissions: "0${permissions}");
} else {
   File_attributes(path, permissions: "${permissions}");
}

would fix it. Want to try that?


#3

It seems OK, thank you.

I guess the string interpolation is not needed in the else, I just did:

} else {
    File_attributes(path, permissions: permissions);
}

By the way, unlike what Little and Tcl documentations say, both Little and Tcl do support the a specifier (meaning all: equivalent to ugo) in addition to [ugo].

If you are in touch with Tcl people, perhaps you can let them know? It is just one letter to add in the documentations:

This command does also has limited support for setting using the symbolic attributes for chmod(1), of the form [ugo]?[[±=][rwxst],[…]],

=>

This command does also has limited support for setting using the symbolic attributes for chmod(1), of the form [ugoa]?[[±=][rwxst],[…]],