Link to home
Start Free TrialLog in
Avatar of Artimage
Artimage

asked on

fopen in unix.

I have a subroutine that opens a file, then calls another routine to do some work on the file, and finally closes the file. The first time I call this routine it works fine, but subsequent calls fail with errno saying "Not a directory".
It is trying to open the same file, and it should truncate if it exists.

So why does the second fopen fail, and how can I get it to work. I don't want to leave the file open between subsequent calls. TIA

The code snippet is here.

void
on_Save_clicked                        (GtkButton       *button,
                                     gpointer         mainWindow)
{
  GtkCTree * ctree;
  char * path;
  FILE * fp;

  /* Get HOME from environment. */
  path = getenv("HOME");

  sprintf(path, "%s/.todorc", path);

  /* Open the rc file */
  if ( (fp = fopen(path,"w")) == NULL) {
    perror("Failed to open .todorc for save");
  }
  else {

    ctree = GTK_CTREE (lookup_widget (mainWindow, "Ctree"));  
   
    /* Walk the tree in prefix order. Apply the function to each node, starting
       at the root.
       BUGBUG change stderr to the file we want to save to.
    */
    gtk_ctree_pre_recursive (ctree, NULL, Save_Node, (gpointer) fp);

    fclose(fp);
  }


}
ASKER CERTIFIED SOLUTION
Avatar of jkr
jkr
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
BTW: Replace '1024' above with an appropriate value, this is just an example (in which I found an error). The 'cleanest' solution would be:

  GtkCTree * ctree;
  char* home;
  char * path;
  FILE * fp;

  /* Get HOME from environment. */
  home = getenv("HOME");

  path = malloc ( (strlen ( home) + strlen ("/.todorc") * sizeof ( char));

  sprintf(path, "%s/.todorc", home);

  /* Open the rc file */
  if ( (fp = fopen(path,"w")) == NULL) {
    perror("Failed to open .todorc for save");
  }

/* ... */

free (path);

/* ... */

Hate to correct myself again ;-)

>> 'path' is an unitialied pointer

The memory 'path' points to in your code is 'owned' by the runtime library, so you mustn't write to it.

Another thing

 path = malloc ( (strlen ( home) + strlen ("/.todorc") * sizeof ( char));

should read

 path = malloc ( (strlen ( home) + strlen ("/.todorc") + 1) * sizeof ( char));

(missing bracket and space for the trailing zero <blushing>)
Avatar of Artimage
Artimage

ASKER

Just so if anyone else looks this up:

Actually, path points to memory that is "owned" by my environment. But you are correct that I shouldn't be writing to it. The failure comes becuase the subsequent call to getenv was getting the value stored by the last sprintf. Thanks for the help.