Solved

Problems with STAT

Posted on 2006-06-13
18
1,091 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
  • 5
  • 5
  • 4
  • +2
18 Comments
 
LVL 86

Accepted Solution

by:
jkr earned 500 total points
Comment Utility
>>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:Kdo
Comment Utility
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
Comment Utility
>>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
 
LVL 24

Expert Comment

by:fridom
Comment Utility
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
Comment Utility
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
Comment Utility
"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
Comment Utility
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:Kdo
Comment Utility

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
Comment Utility
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
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
LVL 45

Expert Comment

by:Kdo
Comment Utility

Hi scuzz1,

What O/S and version are you using?
0
 

Author Comment

by:scuzz1
Comment Utility
Solaris 4.0 on the Unix Server

Windows XP on my PC
0
 
LVL 24

Expert Comment

by:fridom
Comment Utility
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:Kdo
Comment Utility

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
Comment Utility
Sorry,

showrev says kernel version is SunOS 5.6

if that makes a difference.
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
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:Kdo
Comment Utility

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
Comment Utility
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
Comment Utility
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

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
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…
The goal of this video is to provide viewers with basic examples to understand and use structures in the C programming language.
The goal of this video is to provide viewers with basic examples to understand recursion in the C programming language.

772 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

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now