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

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…

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?

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],[…]],