• C

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


}
ArtimageAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C

From novice to tech pro — start learning today.