|
 |
|
 |
 |
10-02-2006, 01:57 PM
|
#1 (permalink)
|
|
C++ Beginner
Join Date: Jul 2005
Location: Ottawa
Posts: 73
|
DU command adapted in C
Hey guys, i've been working on this program for about a week or two (this is a linux application programming class), it's supposed to pretty much perform what the du command does, but make it a little nicer, specifically show in a tree format. usage is as follows:
./du3 -[asLhi:t] [directory-name(s)]
where
a = output line for each file and directory in current directorie(s)
s = summary - only total of for each specified name arguments to be given
h = help...provide usage
L = follow symbolic links
t = tree format (default indent of 3 for files within directory)
in= where n is the indentation if you want it different from default of 3.
if a and s are both specified, call help, if no directory, default to current directory...i think that's it for requirements....now to the questions:
I'm to make use of a makefile to link everything together, using these compile options at minimum: -ansi -pedantic -Wall -Wextra -02
It's near completion, i just need some clarification on a few things: they are as follows:
if I do a du -ac . I get a listing similar to what my program would show, -c shows the total blocksize for the directory. When I run my program with the -ai5 let's say, i get a near identical display but all the blocksizes are doubled! (there's question # 1), i don't know why I receive this result...i've tried it on several systems (fedora, ubuntu).
Question 2: Inside my optS function, where I am only displaying the total for each one, I can't seem to figure out how to display a total for each specified argument....i just get the first...and then nothing else...I can't seem to follow my error on this one.
Makefile
Code:
CFLAGS=-ansi -pedantic -Wall -Wextra -g
du3: main.o optA.o optS.o
gcc ${CFLAGS} -o du3 main.o optA.o optS.o
main.o: main.c du3.h
gcc ${CFLAGS} -c main.c
optA.o: optA.c du3.h
gcc ${CFLAGS} -c optA.c
optS.o: optS.c du3.h
gcc ${CFLAGS} -c optS.c
clean:
rm -f core *.o
header file du3.h:
Code:
#ifndef __includes_
#define __includes_
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <getopt.h>
#include <string.h>
#endif
main function:
Code:
int main( int argc, char *argv[] )
{
int c,type=0,indent=0;
while( (c = getopt(argc, argv, "ai:hLst")) != -1 )
{
switch( c )
{
case 'a':
type = 1;
break;
case 'h':
printf( "option h\n" );
return 0;
case 'i':
indent = atoi( optarg );
break;
case 'L':
printf( "option L\n" );
break;
case 's':
type = 2;
break;
case 't':
indent = 3;
break;
case '?':
printf( "Unknown option!\n" );
return 0;
default:
printf( "default is to print usage\n" );
break;
}
}
if (type == 1)
{
while( optind < argc )
optA( argv[optind++], type, indent );
}
if (type == 2)
{
while (optind < argc)
optS(argv[optind++],1,indent);
}
return 0;
}
Function optA:
Code:
#include "du3.h"
int optA( char *dpath, int type, int indent )
{
DIR *pDir;
struct dirent *dInfo;
struct stat fInfo;
char tempName[1000];
if( (pDir = opendir(dpath)) == NULL)
{
printf( "Unable to open path: %s\n", dpath );
return 1;
}
while( (dInfo=readdir(pDir)) != NULL )
{
if( strcmp(dInfo->d_name, ".") != 0 && strcmp(dInfo->d_name, "..") != 0 )
{
strcpy( tempName, dpath );
strcat( tempName, "/" );
strcat( tempName, dInfo->d_name );
if( (stat(tempName, &fInfo)) == -1 )
printf( "Unable to stat: %s", dInfo->d_name);
else if( (type == 0) && S_ISDIR(fInfo.st_mode) )
printf( "%-*d%-20s\n", indent, (int)fInfo.st_blocks, dInfo->d_name );
else if( (type == 1) && S_ISDIR(fInfo.st_mode) )
{
printf( "%-*d%-20s\n", indent, (int)fInfo.st_blocks, dInfo->d_name );
optA( tempName, type, indent+3 );
}
else if( type == 1 )
printf( "%-*d%-20s\n", indent, (int)fInfo.st_blocks, dInfo->d_name );
}
}
closedir( pDir );
return 0;
}
function optS
Code:
#include "du3.h"
/* Function to display total at the end */
void DisplayTotal(char *temppath,int indent,int total)
{
printf("%-*d%-20s\n",indent,total,temppath);
}
int optS( char *dpath, int type, int indent )
{
DIR *pDir;
struct dirent *dInfo;
struct stat fInfo;
char tempName[1000];
int blocksize;
blocksize = 0;
if( (pDir = opendir(dpath)) == NULL)
{
printf( "Unable to open path: %s\n", dpath );
return 1;
}
while( (dInfo=readdir(pDir)) != NULL )
{
if( strcmp(dInfo->d_name, ".") != 0 && strcmp(dInfo->d_name, "..") != 0 )
{
strcpy( tempName, dpath );
strcat( tempName, "/" );
strcat( tempName, dInfo->d_name );
if( (stat(tempName, &fInfo)) == -1 )
printf( "Unable to stat: %s", dInfo->d_name);
else if( (type == 0) && S_ISDIR(fInfo.st_mode) ){}
/* printf( "%-*d%-20s\n", indent, (int)fInfo.st_blocks, dInfo->d_name );*/
else if( (type == 1) && S_ISDIR(fInfo.st_mode) )
{
/* printf( "%-*d%-20s\n", indent, (int)fInfo.st_blocks, dInfo->d_name ); */
optS( tempName, type, indent+3 );
}
else if( type == 1 )
{
/* printf( "%-*d%-20s\n", indent, (int)fInfo.st_blocks, dInfo->d_name ); */
blocksize += fInfo.st_blocks;
}
}
}
/* printf("Total: %d\n",blocksize); */
closedir( pDir );
DisplayTotal(dpath,indent,blocksize);
return 0;
}
I apologize for the amount of code 
running make should provide no errors on the files specified so i have a logic problem at hand....play around if anyone has time...my -a is working fine i believe except for displaying double the blocksize, I can't seem to figure it out since i'm just retrieving it's blocksize from dirent struct with a stat...
my option s seems to work when I specify only one directory (that is it gives me exactly double the total if i do a du - s [directory])...and only works with the first given argument...any help would be appreciated...
other thing i've noticed: if i do a ./du3 -si5 ..
i get the total of .. to be smaller than that of . which in my case was 136 blocks...i got .. as a blocksize of 112 !? Well i'm rambling....maybe i'll shed my own light in the meantime
__________________
|
|
|
10-03-2006, 01:21 PM
|
#2 (permalink)
|
|
C++ Beginner
Join Date: Jul 2005
Location: Ottawa
Posts: 73
|
Almost got it finished, there's just a few bugs, I'll post my solution within a few days
__________________
|
|
|
10-05-2006, 05:49 AM
|
#3 (permalink)
|
|
C++ Beginner
Join Date: Jul 2005
Location: Ottawa
Posts: 73
|
Here's my final solution to this problem. I'm pretty sure I have it all working out, if anyone wants to try and crack it and see if I've overlooked anything feel free. I think the only new thing which I may not have mentioned in my original post is that all options must precede directories...
Any suggestions are welcome
-------------------------------
Makefile
Code:
CFLAGS=-ansi -pedantic -Wall -Wextra -g
du3: optA.o optS.o noOpt.o help.o main.o
gcc ${CFLAGS} -o du3 optA.o optS.o noOpt.o help.o main.o
optA.o: optA.c du3.h
gcc ${CFLAGS} -c optA.c
optS.o: optS.c du3.h
gcc ${CFLAGS} -c optS.c
noOpt.o: noOpt.c du3.h
gcc ${CFLAGS} -c noOpt.c
help.o: help.c du3.h
gcc ${CFLAGS} -c help.c
main.o: main.c du3.h
gcc ${CFLAGS} -c main.c
clean:
rm -f core *.o
du3 header file:
Code:
#ifndef __includes_
#define __includes_
#define _GNU_SOURCE
#define NONE 0
#define ALL 1
#define SUM 2
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <getopt.h>
#include <string.h>
#endif
Function main:
Code:
#include "du3.h"
int optA( char*, int, int, int );
int optS( char*, int );
int noOpt( char*, int, int, int );
void help();
int main( int argc, char *argv[] )
{
int c,type=NONE,indent=0,lvl=0;
int followlinks=0,blocksize=0;
while( (c = getopt(argc, argv, "+ai:hLst")) != -1 )
{
switch( c )
{
case 'a':
if( type == NONE )
type = ALL;
else {
printf( "You cannot specify options 'a' and 's' together\n" );
return EXIT_FAILURE;
}
break;
case 'h':
help();
return EXIT_SUCCESS;
case 'i':
if( atoi(optarg) >= 2 && atoi(optarg) <= 8 )
indent = atoi( optarg );
else
{
printf( "You must specify an indent between 2 and 8!\n" );
return EXIT_FAILURE;
}
break;
case 'L':
followlinks = 1;
break;
case 's':
if( type == NONE )
type = SUM;
else {
printf( "You cannot specify options 'a' and 's' together\n" );
return EXIT_FAILURE;
}
break;
case 't':
indent = 3;
break;
case '?':
help();
return EXIT_FAILURE;
default:
help();
return EXIT_FAILURE;
}
}
switch( type )
{
case ALL:
while( optind < argc && argv[optind][0] != '-' )
optA( argv[optind++], indent, lvl, followlinks );
break;
case SUM:
while( optind < argc ) {
if( (blocksize=optS(argv[optind],followlinks)) != -1 )
printf( "%d%*s%s\n", blocksize, indent, " ", argv[optind++] );
}
break;
case NONE:
while( optind < argc )
noOpt( argv[optind++], indent, lvl, followlinks );
break;
}
return EXIT_SUCCESS;
}
function optA.c
Code:
#include "du3.h"
int optS( char*, int );
int optA( char *dpath, int indent, int lvl, int followlinks )
{
DIR *pDir;
struct dirent *dInfo;
struct stat fInfo;
char tempName[1000];
int total_size = 0;
if( (pDir = opendir(dpath)) == NULL)
{
printf( "Unable to open path: %s\n", dpath );
return 1;
}
while( (dInfo=readdir(pDir)) != NULL )
{
if( strcmp(dInfo->d_name, ".") != 0 && strcmp(dInfo->d_name, "..") != 0 )
{
strcpy( tempName, dpath );
strcat( tempName, "/" );
strcat( tempName, dInfo->d_name );
if( followlinks )
{
if( ( stat(tempName, &fInfo)) == -1 )
printf( "Unable to stat: %s",tempName );
else if( S_ISDIR(fInfo.st_mode) )
{
printf( "%d%*s%s\n", optS(tempName,followlinks) , (indent*lvl)+1, " ", dInfo->d_name );
optA( tempName, indent, lvl+1, followlinks );
}
else
{
printf( "%d%*s%s\n", (int)fInfo.st_blocks, (indent*lvl)+1, " ", dInfo->d_name );
total_size += (int)fInfo.st_blocks;
}
}
else
{
if( ( lstat(tempName, &fInfo)) == -1 )
printf( "Unable to stat: %s",tempName );
else if( S_ISDIR(fInfo.st_mode) )
{
printf( "%d%*s%s\n", optS(tempName,followlinks), (indent*lvl)+1, " ", dInfo->d_name );
optA( tempName, indent, lvl+1, followlinks );
}
else
{
printf( "%d%*s%s\n", (int)fInfo.st_blocks, (indent*lvl)+1, " ", dInfo->d_name );
total_size += (int)fInfo.st_blocks;
}
}
}
}
closedir( pDir );
return 0;
}
function optS.c
Code:
#include "du3.h"
/************************************************
Function optS
*************************************************/
int optS( char *dpath, int followlinks )
{
DIR *pDir;
struct dirent *dInfo;
struct stat fInfo;
char tempName[1000];
int blocksize = 0;
if( (pDir = opendir(dpath)) == NULL) {
printf( "Unable to open path: %s\n", dpath );
return -1;
}
while( (dInfo=readdir(pDir)) != NULL ) {
if( strcmp(dInfo->d_name, ".") != 0 && strcmp(dInfo->d_name, "..") != 0 ) {
strcpy( tempName, dpath );
strcat( tempName, "/" );
strcat( tempName, dInfo->d_name );
if (followlinks) {
if( (stat(tempName, &fInfo)) == -1 )
printf( "Unable to stat: %s", dInfo->d_name);
else if( S_ISDIR(fInfo.st_mode) ) {
blocksize += optS( tempName, followlinks );
}
else {
blocksize = blocksize + fInfo.st_blocks;
}
}
else {
if ((lstat(tempName,&fInfo)) == -1)
printf( "Unable to lstat: %s\n", dInfo->d_name);
else if( S_ISDIR(fInfo.st_mode) )
blocksize += optS (tempName, followlinks);
else
blocksize += fInfo.st_blocks;
}
}
}
closedir( pDir );
return blocksize;
}
Function noOpt.c
Code:
#include "du3.h"
int noOpt( char *dpath, int indent, int lvl, int followlinks )
{
DIR *pDir;
struct dirent *dInfo;
struct stat fInfo;
char tempName[1000];
if( (pDir = opendir(dpath)) == NULL )
{
printf( "Unable to open path: %s\n", dpath );
return 1;
}
while( (dInfo=readdir(pDir)) != NULL )
{
if( strcmp(dInfo->d_name, ".") != 0 && strcmp(dInfo->d_name, "..") != 0 )
{
strcpy( tempName, dpath );
strcat( tempName, "/" );
strcat( tempName, dInfo->d_name );
if( followlinks )
{
if( stat(tempName, &fInfo) == -1 )
printf( "Unable to stat: %s", tempName );
else if( S_ISDIR(fInfo.st_mode) )
{
/* summerize(); */
printf( "%d%*s%s\n", (int)fInfo.st_blocks, (indent*lvl)+1, " ", dInfo->d_name );
noOpt( tempName, indent, lvl+1, followlinks );
}
}
else
{
if( lstat(tempName, &fInfo) == -1 )
printf( "Unable to stat: %s", tempName );
else if( S_ISDIR(fInfo.st_mode) )
{
/* summerize(); */
printf( "%d%*s%s\n", (int)fInfo.st_blocks, (indent*lvl)+1, " ", dInfo->d_name );
noOpt( tempName, indent, lvl+1, followlinks );
}
}
}
}
return 0;
}
function help.h
Code:
#include "du3.h"
void help()
{
printf( "NAME\n\tdu3 - estimate block usage in tree format\n\n" );
printf( "SYNOPSIS\n\tdu [OPTION]... [FILE]...\n\n" );
printf( "DESCRIPTION\n\tDisplay block count of each FILE, recursively for directories.\n\n" );
printf( "\t-a\n\t\twrite block count for all files, not just directories\n\n" );
printf( "\t-s\n\t\twrite total block count\n\n" );
printf( "\t-t\n\t\tuse an indent of 3 to display tree\n\n" );
printf( "\t-i[n]\n\t\tuse an indent of 'n' to display tree\n\n" );
printf( "\t-L\n\t\tfollow symbolic links\n\n" );
printf( "\t-h\n\t\tdisplay thios help and exit\n\n" );
}
__________________
|
|
|
12-03-2006, 08:56 PM
|
#4 (permalink)
|
|
Recruit
Join Date: Nov 2006
Posts: 9
|
nice programs there, however it differs from what real du command outputs, i made a modification which matches what du command output, however, it only includes one -k option. now it takes a file or a directory. also, it can take no argument which by default it will be current directory, and it takes -k option which only display half size. lastly, i includes a small feature which when the sub directories go beyond 4 it will stop and print message, because we don't want to print a very unacceptable long path directory info.
Code:
#define NONE 0
#define ALL 1
#define SUM 2
#define F 3
#define G 4
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <getopt.h>
#include <string.h>
#include <errno.h>
int optS( char* );
int noOpt( char*, int,char* );
int optK(char* , int,char*);
int fopt( char* );
int main( int argc, char *argv[] )
{
int c,type=NONE,lvl=0,blocksize=0;
char ck[1000];
struct stat info;
if (argc ==1) /* no argument */
{type = ALL;}
if (argc ==2)
{
strcpy(ck, argv[1]);
if(lstat(ck, &info) < 0)
{printf( "Unable to stat: %s \n", ck);
exit(1);}
if(S_ISDIR(info.st_mode) == 0) /* it's a file */
{
type = F;
}
}
while( (c = getopt(argc, argv, "+k")) != -1 ) /*take option */
{
switch( c )
{
case 'k': /* option k */
strcpy(ck, argv[2]);
if(lstat(ck, &info) < 0)
{printf( "Unable to stat: %s \n", ck);
exit(1);}
if(S_ISDIR(info.st_mode) == 0) /* if it's a file */
{type = G;}
else if( type == NONE )
type = SUM;
else {
return EXIT_FAILURE;
}
break;
default:
return EXIT_FAILURE;
}
}
switch( type )
{
case ALL:
noOpt(".", lvl,NULL); /*no argument, so current dir is default setting*/
break;
case SUM:
while( optind < argc ) /*directory is taking option -k */
optK( argv[optind++], lvl, NULL );
break;
case NONE:
while( optind < argc ) /* normal one argument, directory*/
noOpt( argv[optind++], lvl,NULL );
break;
case F:
while( optind < argc ) /*argument is a file*/
{
if( (blocksize=fopt(argv[optind])) != -1 )
printf( "%d%s%s\n", blocksize, "\t ", argv[optind++] );
}
break;
case G:
while( optind < argc ) /*argument is a file and take -k option*/
{
if( (blocksize=fopt(argv[optind])) != -1 )
printf( "%d%s%s\n", blocksize/2, "\t ", argv[optind++] );
}
break;
}
return EXIT_SUCCESS;
}
/************************************************
Function optS
calculate total blocksize and return value
*************************************************/
int optS( char *dpath )
{
DIR *pDir;
struct dirent *dInfo;
struct stat fInfo;
char tempName[1000];
int blocksize = 0;
if( (pDir = opendir(dpath)) == NULL) /*see if can stat or not*/
{
perror("cannot open");
return 0;
}
while( (dInfo=readdir(pDir)) != NULL )
{
if( strcmp(dInfo->d_name, ".") != 0 && strcmp(dInfo->d_name, "..") != 0 ) /*ignore .. and . */
{
strcpy( tempName, dpath );
strcat( tempName, "/" );
strcat( tempName, dInfo->d_name );
if ((lstat(tempName,&fInfo)) == -1)
printf( "Unable to lstat: %s\n", dInfo->d_name);
else if( S_ISDIR(fInfo.st_mode) ) /*accumulate size and add directory size*/
{blocksize += fInfo.st_blocks;
blocksize += optS (tempName);}
else
blocksize += fInfo.st_blocks; /*accumulate blocksize*/
}
}
closedir( pDir );
return blocksize;
}
/************************************************
function noOpt
normal directory argument
************************************************/
int noOpt( char *dpath, int lvl,char *temp )
{
DIR *pDir;
struct dirent *dInfo;
struct stat fInfo;
char tempName[1000],tempchar[1000];
if( (pDir = opendir(dpath)) == NULL )
{
perror("cannot open");
return 1;
}
while( (dInfo=readdir(pDir)) != NULL )
{
if( strcmp(dInfo->d_name, ".") != 0 && strcmp(dInfo->d_name, "..") != 0 )
{
strcpy( tempName, dpath );
strcat( tempName, "/" );
strcat( tempName, dInfo->d_name );
if( lstat(tempName, &fInfo) == -1 )
printf( "Unable to stat: %s \n", tempName );
else if( S_ISDIR(fInfo.st_mode) ) /*if it's a nested directory loop through*/
{
strcpy(tempchar, dInfo->d_name);
if ( lvl > 2) /*set up a counter to monitor how many directory go through*/
{printf("encounter a deep path unable to print : %s.\n",temp);/*print message*/
return 0;
}
noOpt( tempName, lvl+1,tempchar );
}
}
}
printf("%d%s%s\n", 2+optS(dpath), "\t", dpath); /* print final outcome for every loop*/
return 0;
}
/**************************************************
function optK
take directory as argument and take -k option
**************************************************/
int optK(char *dpath, int lvl,char *temp )
{
DIR *pDir;
struct dirent *dInfo;
struct stat fInfo;
char tempName[1000], tempchar[1000];
if( (pDir = opendir(dpath)) == NULL )
{
perror("cannot open");
return 1;
}
while( (dInfo=readdir(pDir)) != NULL )
{
if( strcmp(dInfo->d_name, ".") != 0 && strcmp(dInfo->d_name, "..") != 0 )
{
strcpy( tempName, dpath );
strcat( tempName, "/" );
strcat( tempName, dInfo->d_name );
if( lstat(tempName, &fInfo) == -1 )
printf( "Unable to stat: %s \n", tempName );
else if( S_ISDIR(fInfo.st_mode) )
{
strcpy(tempchar, dInfo->d_name);
if ( lvl > 2) /*set up a counter to monitor how many directory go through*/
{printf("encounter a deep path unable to print : %s.\n",temp);/*print message*/
return 0;
}
/*loop through all directory inside */
optK( tempName, lvl+1,tempchar);
}
}
}
lvl = 0; /* clear it after loop*/
printf("%d%s%s\n", (2+optS(dpath))/2, "\t", dpath); /*the size is half of regular*/
return 0;
}
/************************************************
function fopt
take argument as file
*************************************************/
int fopt(char *dpath)
{
char tempName[1000];
int blocksize = 0;
struct stat fInfo;
strcpy( tempName, dpath );
if ((lstat(tempName,&fInfo)) == -1)
printf( "Unable to lstat: %s\n", tempName);
else
blocksize = fInfo.st_blocks;
return blocksize;
}
__________________
|
|
|
| Thread Tools |
|
|
| Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -8. The time now is 06:05 PM.
|
Copyright © 2000-2006, Milano Interactive
Web Hosting provided by Portal 360 Web Hosting
Open Circle
|
 |
|