[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 551
  • Last Modified:

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);
  }


}
0
Artimage
Asked:
Artimage
  • 3
1 Solution
 
jkrCommented:
The problem is that 'path' is an unitialied pointer, not a valid arry, thus the 'sprintf()' leads to unpredictable results. Use

  GtkCTree * ctree;
  char  path[ 1024];
  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");
  }

instead...
0
 
jkrCommented:
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);

/* ... */

0
 
jkrCommented:
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>)
0
 
ArtimageAuthor Commented:
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.
0

Featured Post

Easily manage email signatures in Office 365

Managing email signatures in Office 365 can be a challenging task if you don't have the right tool. CodeTwo Email Signatures for Office 365 will help you implement a unified email signature look, no matter what email client is used by users. Test it for free!

  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now