Please add it to Go.
---------------
// Thess constants shoud be in 'os' package.
const (
PERM_X = 1
PERM_W = 2
PERM_R = 4
)
func PermToInt(perm_const []int) (perm_num int) {
var perm string
for i := 0; i < len(perm_const); i++ {
perm += strconv.Itoa(perm_const[i])
}
perm_num, _ = strconv.Atoi(perm)
return perm_num
}
---------------
To use it:
perm := PermToInt([]int {PERM_W+PERM_R, PERM_R, PERM_R}) // Should
have 644
Could be:
... PERM_W|PERM_R ...
rather than +; seems to be more canonical.
I like the idea, but there's probably a better implementation. The
function should probably look more like:
func PermToInt(all, group, user int) (perm int) {
return (all * 100) + (group * 10) + user
}
Or even use the variadic argument list '...' if you don't want more
than just three (not sure what the use case for that is, though).
--
Samuel Baldwin - logik.li
On 24 mar, 13:24, Samuel Baldwin <recursive.for...@gmail.com> wrote:
> 2010/3/24 Joan Miller <pelok...@gmail.com>:
>
> > perm := PermToInt([]int {PERM_W+PERM_R, PERM_R, PERM_R}) // Should
>
> Could be:
>
> ... PERM_W|PERM_R ...
>
> rather than +; seems to be more canonical.
>
> I like the idea, but there's probably a better implementation. The
> function should probably look more like:
>
> func PermToInt(all, group, user int) (perm int) {
> return (all * 100) + (group * 10) + user
>
> }
Your implementation is better. Down is the correct name used for the
permissions:
func PermToInt(owner, group, others int) (perm int) {
return (owner * 100) + (group * 10) + others
}
And could be checked if the arguments has any of the values in
permissions constants
Anything as (for each argument):
if perm_const != os.PERM_X || perm_const != PERM_W || perm_const !=
PERM_R {*error*}
func PermToInt(owner, group, others int) (perm int) {
if owner > 7 || owner owner < 0 || group > 7 || group < 0 ||
others > 7 || others < 0 {
return -1
}
return (owner * 100) + (group * 10) + others
}
--
Samuel Baldwin - logik.li
And could be checked if the arguments has any of the values in
permissions constants
Anything as (for each argument):
if perm_const != os.PERM_X || perm_const != PERM_W || perm_const !=
PERM_R {*error*}
On 24 mar, 13:12, Joan Miller <pelok...@gmail.com> wrote:
> This function will be very useful to working with permissions. Instead
> of to write a number you could use constants to define it.
>
> Please add it to Go.
>
> ---------------
> // Thess constants shoud be in 'os' package.
> const (
> PERM_X = 1
> PERM_W = 2
> PERM_R = 4
> )
I forgot myself of that there is another constant; for '-' which is 0:
It could be defined as:
PERM_N = 0
or
PERM_Z = 0
or simply
PERM_ = 0
On 24 mar, 13:49, chris dollin <ehog.he...@googlemail.com> wrote:
If you see in os package [1] the functions that use perm as parameter,
you'll see that perm is an integer.
----------------
const (
PERM_ = 0
PERM_X = 1
PERM_W = 2
PERM_R = 4
)
// 'PermToInt' convert permissions defined with constants to an
integer.
func PermToInt(owner, group, others int) (perm int) {
// Check if the permissions are correct.
if (owner &^ 7) != 0 || (group &^ 7) != 0 || (others &^ 7) != 0 {
return -1
}
return (owner * 100) + (group * 10) + others
----------------
It returns correctly the integer; to checking it:
----------------
perm := PermToInt(PERM_W|PERM_R, PERM_R, PERM_R)
if 644 != perm {
fmt.Println("error")
}
----------------
On 24 mar, 14:16, chris dollin <ehog.he...@googlemail.com> wrote:
Cann't be passed a permission as 644 else that there is to prepend a 0
(if it's a file), else the permissions will be wrond created.
Then, if you pass directly 0644 to any function in os package will
works ok because it reads that 0 too, but if you save a permission as
0644 into a variable then that 0 is deleted.
So, one solution would be use that the parameter 'perm' (in os package
and another ones) were as string instead of integer.
Resuming code:
----------------
const (
PERM_ = 0
PERM_X = 1// 'PermToInt' convert permissions defined with constants to an
PERM_W = 2
PERM_R = 4
)
integer.
func PermToInt(owner, group, others int) (perm int) {// Check if the permissions are correct.
if (owner &^ 7) != 0 || (group &^ 7) != 0 || (others &^ 7) != 0 {
return -1
}----------------
return (owner * 100) + (group * 10) + others
It returns correctly the integer; to checking it:
----------------
perm := PermToInt(PERM_W|PERM_R, PERM_R, PERM_R)
if 644 != perm {
fmt.Println("error")
}
To unsubscribe from this group, send email to golang-nuts+unsubscribegooglegroups.com or reply to this email with the words "REMOVE ME" as the subject.
There is a bug.
Then, if you pass directly 0644 to any function in os package will
works ok because it reads that 0 too,
but if you save a permission as
0644 into a variable then that 0 is deleted.
So, one solution would be use that the parameter 'perm' (in os package
and another ones) were as string instead of integer.
----------------
const (
PERM_ = 0 // No permission
PERM_X = 1 // Execute (for files); go through (for directories)
PERM_W = 2 // Write
PERM_R = 4 // Read
)
// 'PermToInt' convert permissions defined with constants to an
integer.
func PermToInt(owner, group, others int) (perm int) {
// Check if the permissions are correct.
if (owner &^ 7) != 0 || (group &^ 7) != 0 || (others &^ 7) != 0 {
fmt.Fprintf(os.Stderr, "Permission is not octal: %d%d%d\n", owner,
group, others)
os.Exit(1)
}
// Since the constants of permissions are in octal, there is to do
// the multiplication in octal, and get the value in decimal.
return (owner * 64) + (group * 8) + others
----------------
The Go syscall package already has the standard *nix mode_t constants.
Why not use them to construct or test permissions?
S_IEXEC = 0x40
S_IREAD = 0x100
S_IRGRP = 0x20
S_IROTH = 0x4
S_IRUSR = 0x100
S_IRWXG = 0x38
S_IRWXO = 0x7
S_IRWXU = 0x1c0
S_IWGRP = 0x10
S_IWOTH = 0x2
S_IWRITE = 0x80
S_IWUSR = 0x80
S_IXGRP = 0x8
S_IXOTH = 0x1
S_IXUSR = 0x40
For example, for full permissions:
perm := syscall.S_IRWXU | syscall.S_IRWXG | syscall.S_IRWXO.
which avoids octal magic numbers:
perm := (07 << (2 * 3)) + (07 << (1 * 3)) + (07 << (0 * 3))
Peter
Nothing in syscall is guaranteed to be present from
system to system; os is the portable interface.
Why not just write octal constants?
This is almost the only reason they're in the language.
0755 is far clearer, to people who read that kind of code, than
S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH.
Russ
Having a function that converts constants to octal (for permissions)
doesn't hurt to anybody. Whatever could follow using octal constants.
Having a constants as
const (
P_READ = 4
P_WRITE = 2
P_EXEC = 1
)
it's far clearer, when you read the code
perm := PermToInt(os.P_READ|os.P_WRITE|os.P_EXEC, os.P_READ,
os.P_READ)
than 0755, overall because a developer doesn't have to know how works
the permissions in octal.
Althought it been more verbose but its meaning remains enough clear
for everybody.
On 25 mar, 08:22, Joan Miller <pelok...@gmail.com> wrote:
> Having a constants as
> const (
> P_READ = 4
> P_WRITE = 2
> P_EXEC = 1
> )
>
> it's far clearer, when you read the code
> perm := PermToInt(os.P_READ|os.P_WRITE|os.P_EXEC, os.P_READ,
> os.P_READ)
>
> than 0755, overall because a developer doesn't have to know how works
> the permissions in octal.
For 0755, it should be:
perm := PermToInt(os.P_READ|os.P_WRITE|os.P_EXEC, os.P_READ|P_EXEC,
os.P_READ|P_EXEC)
> perm := PermToInt(os.P_READ|os.P_WRITE|os.P_EXEC, os.P_READ,
> os.P_READ)
is much harder to read than 0755 for anybody that understands octal
permissions. And since octal permissions are relatively trivial to
learn, I see no reason why we should encourage developers to be
unnecessarily verbose.
-Kevin Ballard
> To unsubscribe from this group, send email to golang-nuts+unsubscribegooglegroups.com or reply to this email with the words "REMOVE ME" as the subject.
>
--
Kevin Ballard
http://kevin.sb.org
kbal...@gmail.com
I assume that 0752 should give the same permissions as `chmod 0752
FPERM_test`
package main
import "os"
func main(){
file, _ := os.Open("FPERM_test", os.O_CREATE, 0652)
file.Close()
}
0755 :
chmod : -rwxr-xr-x
prog : -rwxr-xr-x
0752 :
chmod : -rwxr-x-w-
prog: -rw-r-x---
So is it a difference between chmod and os.Open permission values?
Regards,
Dmytro
I assume that 0752 should give the same permissions as `chmod 0752
FPERM_test`
file, _ := os.Open("FPERM_test", os.O_CREATE, 0652)
no, because os.Open will be subject to umask
(often 022) which can mask out some bits of the
file's permissions on create. it looks like that's what has
happened in your case: (0652 &^ 022) == 0650
(N.B. your code has 0652, not 0752)
if you use os.Chmod instead, you should see the answer
you were expecting.
In change, you are forcing to them to use octal when anybody could
want to use those constants.
const (
P_RWX = 7
P_RW = 6
P_RX = 5
P_R = 4
P_WX = 3
P_W = 2
P_X = 1
)
so,
perm := PermToInt(os.P_RWX, os.P_R, os.P_R)
On 25 mar, 11:53, Dmitry Panchenko <mcybe...@gmail.com> wrote:
> Thank you guys,
>
> I forgot about umask. After I set it to 0000 I got the correct permissions.
>
> > it's far clearer, when you read the code
> > perm := PermToInt(os.P_READ|os.P_WRITE|os.P_EXEC, os.P_READ,
> > os.P_READ)
>
> As for me this looks better:
> UnixPerm("rwx","rx","r")
To use it as string there would be to implement it through switch for
each argument which affects to its performance.
In change, anything as the next one has greater performance and its
readable for whatever.
UnixPerm(os.P_RWX, os.P_RX, os.P_R)
or removing thath "P_" to get it less verbose
UnixPerm(os.RWX, os.RX, os.R)
Agree,
os.RWX
os.R
os.W
os.WX
os.RW
os.RX
os.X
looks simple
----------------------
// Permissions in octal
const (
RWX = 7
RW = 6
RX = 5
R = 4
WX = 3
W = 2
X = 1
)
/* Convert permissions defined with constants to an integer.
Return the value in decimal.
*/
func UnixPerm(owner, group, others int) (perm int) {
// Check if the permissions are correct.
if (owner &^ 7) != 0 || (group &^ 7) != 0 || (others &^ 7) != 0 {
fmt.Fprintf(os.Stderr, "(UnixPerm) permission is not octal: %d%d%d
\n",
owner, group, others)
os.Exit(1)
}
// Since the constants of permissions are in octal, there is to do
// the multiplication in octal.
return (owner * 64) + (group * 8) + others
}
----------------------
If I'm not wrong those multiplications could be made through bits
which would be a lot of faster. I believe that was using '<<'.
/* Convert permissions defined with constants to an integer.
Return the value in decimal.
fmt.Fprintf(os.Stderr, "(UnixPerm) permission is not octal: %d%d%d
\n",
// the multiplication in octal.
// Since the constants of permissions are in octal, there is to do
return (owner * 64) + (group * 8) + others
If I'm not wrong those multiplications could be made through bits
which would be a lot of faster.
--------------------
/* Convert permissions defined with constants to an integer.
Return the permission as integer.
*/
func UnixPerm(owner, group, others int) (perm int, err os.Error) {
// Check if the permissions are correct.
if (owner &^ 7) != 0 || (group &^ 7) != 0 || (others &^ 7) != 0 {
err := fmt.Sprintf("(UnixPerm) permission is not octal: %d%d%d\n",
owner, group, others)
return 0, os.NewError(err)
}
// In octal, numerals each place is a power with base 8.
return (owner * 64) + (group * 8) + others, nil
}
On 25 mar, 14:12, chris dollin <ehog.he...@googlemail.com> wrote:
----------------------
// Permissions in octal
const (
RWX = 7
RW = 6
RX = 5
R = 4
WX = 3
W = 2
X = 1
)
/* Convert permissions defined in octal with constants to an integer.
Unix file permissions are nine bits of information (3 types x 3 type
of users),
each of them may have just one of two values: allowed or denied.
Return the permission as integer.
*/
func UnixPerm(owner, group, other int) (perm int, err os.Error) {
// Check if the permissions are correct.
if (owner &^ 7) != 0 || (group &^ 7) != 0 || (other &^ 7) != 0 {
err := fmt.Sprintf("[UnixPerm] wrong permission: %d (owner), %d
(group), %d (other)\n",
owner, group, other)
return 0, os.NewError(err)
}
// In octal, numerals each place is a power with base 8.
return (owner << (2*3)) + (group << (1*3)) + other, nil
}
On 25 mar, 14:12, chris dollin <ehog.he...@googlemail.com> wrote:
This error message could be better:
err := fmt.Sprintf("[UnixPerm] permission with any non-octal
value: %d (owner), %d (group), %d (other)\n", owner, group, other)
I've been trying to stay out of this discussion, but 2c is now
inisting on being heard.
First up: I think the proposal is far too modest. I challenge
you to find a real, live, Unix programmer who is happier with
the named constants than they are with actual octal values,
and who can't write the necessary bit shifts (and get them
right) off the top of their head.
(OK, the second or third time they write them at least. We
all played the decimal v. ocatal game once or twice early
on. ;-)
Secondly, you are missing three of the twelve permissions
bits: the "sticky" bit (so called, now generally used on /tmp
et al to control deletion permissions on directories), the
setgid bit, and the setuid bit.
If you're going to continue to spend time on this effort, I'd
recommend creating something that does more than replace the
one line of very obvious bit-shifting and or-ing or and-ing
that most programmers will still write instead of using this
proposed function.
Of course, what you do for your own interest, in your own
time, and what you promote is up to you, and your 2c counts
for as much as mine. (Possibly more, if your 2c is in $USD, €
(Euros), or 2p in £ (UKP); my AUD$ is still worth less than
1:1 against any of those currencies for the moment.)
A more interesting option might be to look into supporting not
the current three arguments you have, but instead a string of
the format of the full symbolic syntax accepted by chmod(1).
Translating chmod's symbolic modes to an integer value isn't
terribly difficult, but it's more complex than most people are
aware and getting it right for the complex cases (and creating
tests for them) would offer more of a challenge:
http://www.opengroup.org/onlinepubs/009695399/utilities/chmod.html
n.b. While the format is documented in the chmod(1)
description, at least a couple of other utilities use it too,
so there's a limited argument for making it a package
function.
The idea has the additional advantage of being targeted at
users, who typically in my experience have a less solid
understanding of Unix permissions than programmers, who
usually either are up to speed already or who can be brought
up to speed very quickly.
(Except, off course, nobody can be brought up to speed on
Access Control Lists (ACLs) very quickly, as every vendor of
Unix-like systems does them differently, if they support
them at all.)
The reverse of the chmod-style symbolic mode (translating
integer permissions to something like ls(1) output), is, of
course, much easier:
http://www.opengroup.org/onlinepubs/009695399/utilities/ls.html
Now, some general comments on your code: as well as the
missing functionality mentioned above (twelve permissions
bits, not nine) he code itself I find less clear than it could
be.
Joan Miller <pelo...@gmail.com> wrote:
> Fixed:
>
> ----------------------
> // Permissions in octal
> const (
> RWX = 7
> RW = 6
> RX = 5
> R = 4
> WX = 3
> W = 2
> X = 1
> )
What about the sticky bit, the setgid bit, and the setuid bit?
They're part of the permissions too:
http://www.opengroup.org/onlinepubs/007908799/xsh/sysstat.h.html
...
S_ISUID
set-user-ID on execution
S_ISGID
set-group-ID on execution
S_ISVTX
on directories, restricted deletion flag
...
From:
http://golang.org/pkg/syscall/
S_ISGID = 0x400
S_ISUID = 0x800
S_ISVTX = 0x200
Note how unobvious those values become in hexadecimal.
Wouldn't the following using octal be clearer?
S_ISGID = 02000
S_ISUID = 04000
S_ISVTX = 01000
> ...
> Unix file permissions are nine bits of information (3 types x 3 type
> of users),
> ...
s/nine/twelve/ and the reset of the sentence then needs changing.
> func UnixPerm(owner, group, other int) (perm int, err os.Error) {
> // Check if the permissions are correct.
> if (owner &^ 7) != 0 || (group &^ 7) != 0 || (other &^ 7) != 0 {
> err := fmt.Sprintf("[UnixPerm] wrong permission: %d (owner), %d
> (group), %d (other)\n",
> owner, group, other)
> return 0, os.NewError(err)
> }
Not sure where you'd choose to put the extra three bits I
mentioned, but one way would be to make each of these values
four bits; another would be to add a fourth argument; another
would be to take a single string argument a la chmod(1) as I
suggested above.
Further, you might as well go ahead and make the error message
specific about which argument(s) are outside their allowed
domain. (It's usually helpful to specify what the acceptable
domain is too: someone who has got it wrong other than through
a simple typo will appreciate the extra help.)
I would use octal output in any error message too: even I
don't read decimal permissions values fluently. Based on a
comment of Russ's, Unix permissions are the main reason octal
constants are supported in Go: that's how strongly they've
fixed themselves in people's minds since the time Unix
introduced its permissions style decades ago.
> // In octal, numerals each place is a power with base 8.
Er ... 'add one to a'? Octal _is_ base 8.
> return (owner << (2*3)) + (group << (1*3)) + other, nil
Again, needs enhancement for the missing bits, and the
multiplications don't add anything to make this readable IMHO:
indeed they make it less so; pure bit shifts are the more
usual way of writing this code in all the Unix utilities and
application code I've seen.
In summary, I'd recommend either taking on the chmod(1)
symbolic mode representation translation, or just dropping
this quietly. Given the resistance we're starting to see
about expanding the standard library, I don't expect either
function to make the Go core distribution.
You may, of course, disagree with me (and probably will), and
I'll shut up from this point on unless you ask for comment
after taking the idea in the direction of the POSIX symbolic
permisssions.
Regards,
Giles
P.S. If you do carry on with this, you'd want to figure how to
document the influence of umask, and whether it should be an
option to your function to see the effect of the current umask
or whether you should have two functions.
Either way I suggest it's interesting to get the integer that
represents the permissions you're about to ask for, or the
permisssions you'll actually get (race conditions with Umask()
calls in other goroutines allowing).
Happily, at least someone arranged to fix Umask() for the
platforms for which it was broken and that fix has been in the
last couple of releases at minimum. :-)
It's possible that Unix programmers been happier using the octal
values, but I'm sure that there are another programmers (overall
coming from dynamic languages) that will be happier using constants.
and who can't write the necessary bit shifts (and get them
right) off the top of their head.
http://bitbucket.org/ares/go-osutil/src/tip/osutil/posixperm.go#cl-63
On 25 mar, 11:53, Dmitry Panchenko <mcybe...@gmail.com> wrote:
Russ
2) It's more readable 'UnixPerm("rw","r","r")' than '0644'
3) I don't pretend that it been added to the Go core. It will be into
an external package together to all functions related to operations on
Posix paths where I'm working.