Solved

Problems with STAT

Posted on 2006-06-13
18
1,116 Views
Last Modified: 2008-01-09
Why doesn't my code recognize:

S_IRUSR
S_IRGRP
S_IROTH
S_IWUSR
S_IWGRP
S_IWOTH
S_IXUSR
S_IXGRP
S_IXOTH

I have seen numerous answers to this problem but the solutions are not working for me.

Here is my code:

/* STAT.C: This program uses the _stat function to
 * report information about the file named STAT.C.
 */

#include <time.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>

char *getmode(char val);

void main( void )
{
   struct stat buf;
       int i;
       int j;
       int result;
       char *strMode;
       char buff[20];

       strMode = (char*)calloc(10,sizeof(char));

   /* Get data associated with "stat.c": */
   result = stat( "c:\\user\\base_new_revised.txt", &buf );

   /* Check if statistics are valid: */
   if( result != 0 )
      perror( "Problem getting information" );
   else
   {
      /* Output some of the statistics: */
      printf( "Numeric id                      (st_gid): %d\n", buf.st_gid );
      printf( "Last Time accessed            (st_atime): %s\n", ctime( &buf.st_atime ) );
      printf( "Time of creation              (st_ctime): %s\n", ctime( &buf.st_ctime ) );
      printf( "Drive                           (st_dev): %c:\n", buf.st_dev + 'A' );
      printf( "Number of the info node (unix)  (st_ino): %d\n", buf.st_size );
      printf( "St_mode Results                (st_mode): %o\n", buf.st_mode);

sprintf(buff,"%o",buf.st_mode);

j = strlen(buff);

for(i=0;i < j;i++)
{
strMode=getmode(buff[i]);
printf("%s\n",strMode); /* eg: rw-*/
}

/*
File mask type:       (_S_IFMT)
Directory:               (_S_IFDIR)
Character special:   (_S_IFCHR)
Regular:                 (_S_IFREG)
Read permission:    (_S_IREAD)
Write permission:    (_S_IWRITE)
Exec permission:     (_S_IEXEC)
*/


if (buf.st_mode &S_IREAD)
     printf("r");
else
     printf("-");

if (buf.st_mode &S_IWRITE)
     printf("w");
else
     printf("-");

if (buf.st_mode &S_IEXEC)
     printf("x\n");
else
     printf("-\n");

/* ================ This Section Does not Work ===========================
   ================ Get undeclared identifier for S_IRUSR ================

if ( buf.st_mode & S_IRUSR) {
   printf ("readable by group");
// readable by "group"
}



if (buf.st_mode &S_IRUSR)
     printf ("others have execute permissions");


if (buf.st_mode &S_IRUSR)
     printf("r");
else
     printf("-");

if (buf.st_mode &S_IWUSR)
     printf("w");
else
printf("-");

if (buf.st_mode &S_IXUSR)
     printf("x\n");
else
printf("-");

if (buf.st_mode &S_IRGRP)
     printf("r");
else
printf("-");

if (buf.st_mode &S_IWGRP)
     printf("w");
else
printf("-");

if (buf.st_mode &S_IXGRP)
     printf("x\n");
else
printf("-");

if (buf.st_mode &S_IROTH)
     printf("r");
else
printf("-");

if (buf.st_mode &S_IWOTH)
     printf("w");
else
printf("-");

if (buf.st_mode &S_IXOTH)
     printf("x\n");
else
printf("-");

*/

      printf( "Last Time modified:           (st_mtime): %s\n", ctime( &buf.st_mtime ) );
      printf( "Is Link                       (st_nlink): %d\n", buf.st_nlink );
      printf( "Drive                          (st_rdev): %c:\n", buf.st_rdev + 'A' );
      printf( "File size                      (st_size): %ld\n", buf.st_size );
      printf( "UID                             (st_uid): %ld\n", buf.st_uid );
   }
}

char *getmode(char val)
{
char *smode;
char perm[]="rwx";
int ival=val-'0';
int i,count=0;

smode = (char*)calloc(4,sizeof(char));

for(i=1;i<8;i<<=1,count++)
{
if((ival & i) == 1)
smode[2-count]=perm[2-count]; /* bcoz 001 ==> x and 010 ==> w */
else
smode[2-count]='-';
}
return smode;
}
0
Comment
Question by:scuzz1
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 5
  • 4
  • +2
18 Comments
 
LVL 86

Accepted Solution

by:
jkr earned 500 total points
ID: 16897834
>>result = stat( "c:\\user\\base_new_revised.txt", &buf );
>>Get undeclared identifier for S_IRUSR

These constants and the information they represent simply aren't available on Windows, that's why this does not work.
0
 
LVL 45

Expert Comment

by:Kent Olsen
ID: 16897838
It compiles fine for me, except for your redefinition of main().  (The return type should be int, not void).

Check to make sure that you have access to /usr/include/sys/stat.h.  That's the file where these items should be defined.


Kent
0
 
LVL 86

Expert Comment

by:jkr
ID: 16898270
>>It compiles fine for me, except for your redefinition of main().  (The return type should be int, not void).

That's fine with VC++.

>>Check to make sure that you have access to /usr/include/sys/stat.h

Windows compilers for sure haven't access to that file.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 24

Expert Comment

by:fridom
ID: 16899881
Both of you are write. The code is obviously for Unices and there this will work, it will work partly on Windows if you have access to the POSIX layer. However the whole user, grop concept does not hold on Windows.

On Windows you have to use functions like
FileType, ReadFilePermissions, SetSecurity xxxx etc.

It could be however that you can use the given stuff on Windows if you have cygwin installed.

Regards
Friedrich
0
 
LVL 24

Expert Comment

by:fridom
ID: 16900248
Ok, here's a suggestoin which for that stuff which works on Windows
and Linux (you just have to check the proper libapr version)
#include <apr.h>
#include <apr_file_info.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main(void){
      apr_pool_t *mp;
      apr_finfo_t finfo;
      apr_status_t rv;
      char *fn = "apr_stat.c";
      char perms[128];

      apr_initialize();
      apr_pool_create(&mp, NULL);
      rv = apr_stat(&finfo, fn, APR_FINFO_OWNER | APR_FINFO_PROT, mp);

      if (finfo.protection & APR_UREAD){
         strcpy(perms, "user perms: r");
         } else {
            strcpy(perms, "user perms: -");
      }
      if (finfo.protection & APR_UWRITE){
            strcat(perms, "w");
      } else {
            strcat(perms, "-");
      }
      if (finfo.protection & APR_UEXECUTE){
            strcat(perms, "x");
      } else {
            strcat(perms, "-");
      }

      puts(perms);




      apr_terminate2();
      return 0;
}

Regards
Friedrich
0
 
LVL 22

Expert Comment

by:grg99
ID: 16901248
"stat" comes from the Unix file system, and Windows just doesnt have some of the Unix file system status bits.

I'd put in some #ifdef  lines so this program will work on both systems.  Something like:

#ifdef S_WHATEVER
     if( status & S_WHATEVER ) printf ("FILE HAS WHATEVER" );
#endif

0
 

Author Comment

by:scuzz1
ID: 16901854
JKR

I think that is my problem. The files I want to lookup are on a Unix file server. What I don't understand is in the code the include for stat.h is "usr\stat.h". I don't have a \usr directory on my C drive. So, where is it finding stat.h?
0
 
LVL 45

Expert Comment

by:Kent Olsen
ID: 16901945

Hi scuzz1,

Check your C environment's configuration to see where the include files are stored.  I assume that you're using a Microsoft or Borland IDE?

You can make the source more portable and give a very unix-like output by combining a few of the suggests that have been posted.  For each of the share mode flags use something like this:

#ifdef S_ISUSR
  if (buf.st_mode &S_IRUSR)
     printf("r");
  else
     printf("-");
#else
  printf ("_");
#endif

On a unix system, you'll get the expected "drwxrwxrwx" display.  On a Windows system, you'll get "drwx______".

Of course, the underscore can be any character that you choose, but I kind of like it.  :)


Kent

0
 

Author Comment

by:scuzz1
ID: 16903149
Ok.

The environment is my problem. I found the stat header that is being used and there are no defines for
S_IRUSR
S_IRGRP
S_IROTH
etc..

So now (I have never done this before either) how do I get this application to work on a unix box?

It was created as an Win32 console application in VS 6.0.

Do I need to recreate it using some other compiler?
0
 
LVL 45

Expert Comment

by:Kent Olsen
ID: 16903290

Hi scuzz1,

What O/S and version are you using?
0
 

Author Comment

by:scuzz1
ID: 16903466
Solaris 4.0 on the Unix Server

Windows XP on my PC
0
 
LVL 24

Expert Comment

by:fridom
ID: 16903545
Well I guess you got that wrong, the code can be probably compiled on the Sun but you can not compile it on you Window  box and expect that to run on the Unix system.

Of course there do exist cross-platform compilers, but that's a totally different story.

Regards
Friedrich
0
 
LVL 45

Expert Comment

by:Kent Olsen
ID: 16903554

Solaris 4.0?  That predates the dinosaurs.  Like Paul  :)

I believe that the share modes go back at least that far.  I would expect your code to compile on Solaris and fail on Windows.


Kent

0
 

Author Comment

by:scuzz1
ID: 16903933
Sorry,

showrev says kernel version is SunOS 5.6

if that makes a difference.
0
 
LVL 86

Expert Comment

by:jkr
ID: 16904052
Again - you won't be able to query that info using these APIs using code that runs on a Windows machine, simply because there is no representation for that kind of data. You can use Windows' security APIs to get 'translated' values, like '_access()', but e.g. S_WGRP or S_RGRP simply have no meaning on Windows.

/* ACCESS.C: This example uses _access to check the
 * file named "ACCESS.C" to see if it exists and if
 * writing is allowed.
 */

#include  <io.h>
#include  <stdio.h>
#include  <stdlib.h>

void main( void )
{
   /* Check for existence */
   if( (_access( "ACCESS.C", 0 )) != -1 )
   {
      printf( "File ACCESS.C exists\n" );
      /* Check for write permission */
      if( (_access( "ACCESS.C", 2 )) != -1 )
         printf( "File ACCESS.C has write permission\n" );
   }
}
0
 
LVL 45

Expert Comment

by:Kent Olsen
ID: 16904189

I think that the simplest solution might be to just let the unix environment reflect the values that you expect and lump the Windows' values together.

Include these defines after including sys\stat.h:

#ifndef S_IRUSR
#define S_IRUSR S_IREAD
#define S_IRGRP S_IREAD
#define S_IROTH S_IREAD
#endif

#ifndef S_IWUSR
#define S_IWUSR S_IWRITE
#define S_IWGRP S_IWRITE
#define S_IWOTH S_IWRITE
#endif

#ifndef S_IXUSR
#define S_IXUSR S_IEXEC
#define S_IXGRP S_IEXEC
#define S_IXOTH S_IEXEC
#endif

This isn't 100% accurate in that it will improperly show all objects as available to all users on the Windows system, but it will give you a unix-like display that is accurate on the unix system and pseudo-accurate on Windows.


Kent

0
 

Author Comment

by:scuzz1
ID: 16905056
jkr seemed to have it right first.

I am just learning C and everything I have done to date has been Win32 Apps because that is all I know.

I would like to see if I could get this to execute in Unix.

Can I do this with VS 6.0 or do I need something else?

Jim
0
 
LVL 86

Expert Comment

by:jkr
ID: 16908631
VC6 should be fine for that. BTW, to elaborate on the "access rights" issue - Windows defines ACSs and SDs (i.e. Access Control Lists and Security Descriptors) for that purpose. Even though the UNIX access rights will be "mapped" in some way, you can even get to a more accuate level, depending on what your final goal is.
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
The goal of this video is to provide viewers with basic examples to understand how to create, access, and change arrays in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use switch statements in the C programming language.

739 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question