For the beginner C++ programmer

i mean i can read man pages like stat(2) but what does this int flags mean? where is this coming from? Confused.
 
kpa said:
The object st is created by the caller ftw(3) and "passed by reference" by using an explicit pointer (the star in front of it in the argument list) to it.

It could be passed by using C++ references, something like this:

Code:
int action(const char *path, const struct stat &st, int flags)
{
   std::cout << st.st_uid << "  " << st.st_gid << "  " << path << "\n";
   return 0;
}

That would however require a C++ interface to ftw(3) and the stat structure and there's only a C version available.

No the pointers make sense to me, I tracked down the man page for stat. I don't know C but from what I know in C++ a struct and a class are very similar except structs are public by default (where C doesn't have classes and doesn't understand "private")... so their uses in C are obviously for different reasons but still... I know enough where I think I can manipulate it, I'd just like to UNDERSTAND WHY this works, not just borrow and cite your code because it works and write the rest. What good is that to me?
 
return ftw("/etc", action, 1);

is that second parameter calling action() without parantheses. And seriously that 1 is irritating me. Completely no understanding of what it does or why.
 
The second argument of ftw(3) is a pointer to a function that has the following prototype:

Code:
int (*fn)(const char *, const struct stat *, int)

The action() function in the above example matches this prototype. It gets called by ftw(3) for every entry the tree walk encounters. This is a common technique called "call back functions" where the calling code can remain the same but the called functions can be changed by passing pointers to different functions, often to functions that are loaded from plugin DLLs.

Oh and the following are equivalent because a name of a function is equal to taking the address of the function:

Code:
   return ftw("/etc", action, 1);

   return ftw("/etc", &action, 1);
 
I guess I really need to learn more about C if I want to be doing programming for FreeBSD. I thought C++ was the new standard? No schools around here teach C and the C++ classes do everything they can to ignore the C subset.
 
kpa said:
The second argument of ftw(3) is a pointer to a function that has the following prototype:

Code:
int (*fn)(const char *, const struct stat *, int)

The action() function in the above example matches this prototype. It gets called by ftw(3) for every entry the tree walk encounters. This is a common technique called "call back functions" where you can use call different functions based on runtime conditions.

Oh and the following are equivalent because a name of a function is equal to taking the address of the function:

Code:
   return ftw("/etc", action, 1);

   return ftw("/etc", &action, 1);

Thank you that makes sense... That 1 at the end is still perplexing me. This thread is getting rediculous...
 
It's the maxfds parameter for ftw(3).

Code:
The maxfds argument specifies the maximum number of file descriptors to
     keep open while traversing the tree.  It has no effect in this implemen-
     tation
 
reading ftw.h answered my own question. Now I just need to try to figure out how to store these into an array of strings and "grep" them. C seems so much more convoluted than C++.
 
I think maybe I'll study dirent.h... I can't get this to traverse /usr/ports and only show directories. I just don't get it and its frustrating me.
 
I remembered that long time ago I had written a simple class for recursive and reusable path indexing. I modified it slightly to match exactly what you need (to only index directories and not files). Here it is: http://pastebin.com/Mzkiv188

You run it as ./parser /usr/ports gtk it will first index /usr/ports then it will search through the index for directories that contain 'gtk' in their names and print them out. Simple and primitive, but I think thats what you are looking for. It lacks comments so if you have any questions just shoot them at me.
 
ikbendeman said:
I think maybe I'll study dirent.h... I can't get this to traverse /usr/ports and only show directories. I just don't get it and its frustrating me.

Yeah, in general a computer does not what you want it to do, but it does exactly what you ask it to do :p

So, why don't you simply ask it to show only directories by using a simple if() statement:

if (S_ISDIR(st->st_mode))

Code:
// dirtree.cpp

#include <iostream>
#include <ftw.h>
#include <sys/stat.h>

int action(const char *path, const struct stat *st, int flags)
{
   if (S_ISDIR(st->st_mode))
      std::cout << st->st_uid << "  " << st->st_gid << "  " << path << "\n";
   return 0;
}


int main(int argc, const char *argv[])
{
   return ftw("/usr/ports", action, 1);
}
 
rolfheinrich said:
Perhaps using the ftw(3)() interface?

Code:
#include <stdio.h>
#include <ftw.h>
#include <sys/stat.h>


int action(const char *path, const struct stat *st, int flags)
{
   printf("%10d%10d   %s\n", st->st_uid, st->st_gid, path);
   return 0;
}


int main(int argc, const char *argv[])
{
   return ftw("/etc", action, 16);
}

Ok I would like to use ftw but it only seems to work (with this code) for folders under the root directory.

"return ftw("/etc", action, 16);" works;
"return ftw("/usr", action, 16);" works;
"return ftw("/usr/ports", action, 16); does not work.

The man page also seems to have no information on what the 16 is or does either. I can write this using dirent.h and it makes sense to me, however this just frustrates me because it's either not well-documented enough, or I just don't get it....
 
rolfheinrich said:
Yeah, in general a computer does not what you want it to do, but it does exactly what you ask it to do :p

So, why don't you simply ask it to show only directories by using a simple if() statement:

if (S_ISDIR(st->st_mode))

Code:
// dirtree.cpp

#include <iostream>
#include <ftw.h>
#include <sys/stat.h>

int action(const char *path, const struct stat *st, int flags)
{
   if (S_ISDIR(st->st_mode))
      std::cout << st->st_uid << "  " << st->st_gid << "  " << path << "\n";
   return 0;
}


int main(int argc, const char *argv[])
{
   return ftw("/usr/ports", action, 1);
}

There is no output of this code.... seems to me like ftw is not well-enough documented and I'm not the only one who doesn't understand it...
 
Welp... I wrote it to help teach myself more C/C++. dirent.h worked fine... still need help with ftw... seems like I could write a more concise program with it... if it actually worked on anything besides folders in the root directory.
 
ikbendeman said:
seems to me like ftw is not well-enough documented and I'm not the only one who doesn't understand it...

Yep, contrary to what nslay was suggesting, I suggest sticking with this generic portable code for this very reason, it is more common because it is used across multiple operating systems and so you will be able to find more accurate and supported documentation and will make for easier maintainance at a later date.

(You can also get a version of dirent.h for Windows)
 
ikbendeman said:
There is no output of this code.... seems to me like ftw is not well-enough documented and I'm not the only one who doesn't understand it...

The code is OK. Either you named the compiled binary test, or "/usr/ports" does not exist on the machine where you tested the code, or the user executing the binary doesn't have read permission on it.

Check the permissions, then try again:

Code:
# g++ dirtree.cpp -o dirtree && ./dirtree
0  0  /usr/ports
0  0  /usr/ports/.svn
0  0  /usr/ports/.svn/pristine
0  0  /usr/ports/.svn/pristine/1b
...
 
Back
Top