Complete.Org: Mailing Lists: Archives: discussion: March 2006:
[aclug-L] Re: C questions
Home

[aclug-L] Re: C questions

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: discussion@xxxxxxxxx
Subject: [aclug-L] Re: C questions
From: Tom Hull <thull2@xxxxxxx>
Date: Sun, 12 Mar 2006 19:47:53 -0600
Reply-to: discussion@xxxxxxxxx

Olwe Bottorff wrote:
> Yes, that's true and once you take 755 to decimal you
> can give it to a mode_t variable, then feed it to
> open, mkdir, etc. But I guess I'm still wondering how
> 
> mkdir("dirname", 0755);
> 
> gets converted.

the declaration is:

   int mkdir(const char *pathname, mode_t mode);

mode_t is a typedef (cf. <bits/types.h>) for unsigned int.
your usage above specifies an unsigned int value as octal;
this converts to the declared type (mode_t), so it works.
there's nothing magical about it being octal -- could be
493 or 0x1ed, which all mean the same, as does:

   (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)

see man 2 chmod for an explanation of that.

calling mkdir("dirname", "0755") doesn't work, because
"0755" is a string literal, i.e., a const char*, i.e.,
a pointer, and that's not compatible, so you get an
error.

if you have a string (e.g., from argv[1]) you need to call
a function to convert it to an unsigned int (mode_t). if
you know it's in octal (e.g., "0755") the easiest one to
use is:

   mode_t mode = (mode_t) strtoul("0755", 0, 8);

this leaves out a bunch of error checking you might want
to do; e.g., this will return 0 if the string isn't a
number. one way to do this would be:

   char *p, *q = "0755";
   mode_t mode = (mode_t) strtoul(q, &p, 8);
   if (p == q || mode > 07777) {
     fprintf(stderr, "bad mode string argument: %s\n", q);
     exit(1);
   }

also note that the process umask affects mkdir modes.

> The issue is I'm writing my own tar utility. The mtime
> gets stored as an 11-digit char string that's supposed
> to be an octal number, so you have to turn it back
> into a decimal. I had to do an atoll() on the 11-digit
> char string, assigning to a long long variable, then
> convert that from octal to decimal to get the utime's
> time_t variable fed properly. That can't be the most
> elegant way to do this....

11 octal digits specifies 33 bits. time_t values are 32
bits, so you're never actually going to see an octal
value >= 040000000000. therefore using a long long
function is unnecessary; however, you should be using
an unsigned function where you can specify that the
base is octal. again, this leads you back to:

   strtoul(3)

rtfm. the typedefs for mode_t, time_t, etc., used to be
easy to find, but the gcc folks "fixed" that. the easiest
way to figure out where they are is to run cc -E on your
file, capture the output, and work your way back; e.g.,
the first reference of mode_t is in <bits/types.h>:

   typedef __u_int mode_t;

the first reference of __u_int is also in <bits/types.h>:

   typedef unsigned int __u_int;

> LB

-- 
/*
  *  Tom Hull * http://tomhull.com/ * http://notesoneverydaylife.com/
  */


-- This is the discussion@xxxxxxxxx list.  To unsubscribe,
visit http://www.complete.org/cgi-bin/listargate-aclug.cgi


[Prev in Thread] Current Thread [Next in Thread]