1

I'm trying to create a TAR archive from my program and then opening the archive for further processing. I have a 2 second delay between calling system() and open(). So far, it works fine, but I'm not sure why the 2 second delay is necessary or if it's the correct solution.

Without the delay, I get error code 2 (ENOENT "No such file or directory") from the open() call. My first thought was the filesystem wasn't updating itself fast enough and open() couldn't find the file. But what if the system is really busy? Do I need a longer delay? Should I loop until open() succeeds instead of the delay? Is the problem something completely different?

UPDATE
The root filesystem is EXT2. /tmp is mounted in RAM using TMPFS. I'm using tar to create an archive, not extract contents of one. Essentially, my program is supposed to create an archive of some log files and send them over the network (that's why I open the archive after creating it).

int return_value = system("/bin/tar -czf /tmp/logs.tar.gz /var/log/mylogs.log* &> /dev/null");
// error checks on return_value as described here: http://linux.die.net/man/2/wait
if(return_value != 0) {
  return return_value;
}
//usleep(2000000);
return_value = open("/tmp/logs.tar.gz", O_RDONLY | O_LARGEFILE, 0);
// success or failure depending on whether there's a delay or not
Ioan
  • 2,382
  • 18
  • 32
  • 2
    What happens if you use `popen`? – Richard J. Ross III Dec 19 '11 at 19:28
  • 1
    Exactly, this is a job for `popen()`. Tutorials teaching `system()` should be given the axe. – fge Dec 19 '11 at 19:31
  • `popen()` has the same end result as `system()`. I.E. the `open()` call fails in the same way without a delay. – Ioan Dec 19 '11 at 20:32
  • 1
    What filesystem are we talking about here, anyway? Is network transport involved? Are you perhaps the victim of a crappy consumer NAS device? (Been there, seen that... for example, a NAS dev exportings its files using CIFS - and never storing filestamps, which means rsync could not do its job properly.) – jørgensen Dec 19 '11 at 21:27
  • Perhaps the problem is elsewhere. You should show actual code to get real help. – Basile Starynkevitch Dec 20 '11 at 08:40
  • @fge Does `popen()` have the same warning about suid and sgid programs as `system()`? Or is the best solution `fork()/exec()`? – Ioan Dec 20 '11 at 13:12

3 Answers3

2

You could even avoid running an external tar command by using libtar directly in your program.


ADDED

And you should show us your program. I'm pretty sure that if the call to system just extracted some file thru tar, it is available just after a successful system call, e.g. something like:

 int err = system("/bin/tar xf /tmp/foo.tar bar");
 int fd = -1;
 if (err == 0)
      fd = open("bar", O_RDONLY);
 // fd is available

there is no reason to wait a few seconds in this code. You are probably doing more complex things, or you forgot to test the result of system

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
1

Here's what I would try:

  1. fork/exec tar yourself, and have your parent collect the tar-child. If system is introducing a race condition with the file system, taking control of the child process creating/reaping may help.

  2. touch an empty file (fopen for writing and close) and then tar into into the new file.

  3. Give tar the --verify option; the file has to exist in order to be verified :)

Christopher Neylan
  • 8,018
  • 3
  • 38
  • 51
  • yes, but if we're operating under the assumption that there is a bug somewhere, this will rule out the possibility that it's a code/library issue, letting us focus on other things. – Christopher Neylan Dec 20 '11 at 16:43
1

You think you are redirecting tar's output with "&>", but actually you are running it in the background, because system() happens to invoke a shell that doesn't support &> and so interprets it as "&" followed by ">". The delay causes your program to wait long enough that tar completes.

The fix is to modify your command to use syntax that your shell supports. Throwing the error output from tar is probably a mistake in any case.