How to write to a file including full directory in C under Unix?

C

CBFalconer

Hongyu said:
CBFalconer said:
Hongyu said:
I am trying to write to a file with full directory name and file
name specified (./outdir/mytestout.txt where . is the current
directory) in C programming language and under Unix, but got
errors of Failed to open file ./outdir/mytestout.txt. Below is
the code:

#include <stdio.h>

int main(void)
{
FILE *fp;
char fname[30];
char pathname[30];

strcpy(fname,"./outdir/mytestout.txt");
fp=fopen(fname, "w");

Look into permissions. On principal, use blanks around '='.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.- Hide quoted text -

- Show quoted text -
------------------ snip from "-- " to here. ---------------
Can you explain a little bit more on this? I am not sure how to use
blanks around "=" for this? Thanks.

Don't quote sigs. You should have stripped the marked portion
after the "-- " marker.

That suggestion was separate. It meant write "fp = fopen(...)" in
place of "fp=fopen(...)". It makes your code more readable, and
avoids many confusing errors in compilation.
 
K

Keith Thompson


In some system-specific manner.

Assuming a Unix-like system, fopen("/foo/bar/newfile.txt", "w") could
implicitly invoke the equivalent of "mkdir -p /foo/bar" before
actually creating the file.

That's just one example. The point is that the C standard doesn't
mention directories at all. There's nothing in the standard that says
an implementation *can't* create a directory as a side effect of
creating a file.

(I'm not aware of any actual implementation that does this.)
 
A

Antoninus Twink

Thanks. I know how to create directory in Unix using mkdir, but what i
don't know is how to make it in the C programming. I will try Brian's
method which mentioned using system method to achieve it. I guess it
will work.

It will "work", but it is a stupid solution. "Brian" is a troll who
wants to disrupt the group with endless topicality and netnanny flame
wars, and in this case he has led you down the wrong path. Running
programs using system() can be a security issue, and you get no way of
discovering errors that may occur.

Instead, use the portable POSIX solution:

#include <sys/stat.h>
#include <sys/types.h>

then do something like

if(mkdir("my_new_directory", S_IRWXU | S_IRWXG | S_IRWXO) == -1) {
/* an error occurred - check errno to find out what */
} else {
/* success - carry on */
}
 
R

Richard Tobin

You need to create the directory before you create the file in it.
On unix, use the mkdir() function - see the manual page for details.
[/QUOTE]
Thanks. I know how to create directory in Unix using mkdir, but what i
don't know is how to make it in the C programming.

I didn't say use the mkdir command, I said use the mkdir() function.

Depending on which version of unix you use, something like "man 2 mkdir"
will show you the manual page.

-- Richard
 
A

Antoninus Twink

On principal, use blanks around '='.

Look, other people have different coding styles and conventions to you.
Many of them post code to Usenet. Just live with it, instead of always
prissily trying to impose "the CBF house style" (with is awful, btw) on
the rest of the world.

And learn how to spell principle. Who's going to take style advice from
an illiterate?
 
W

Walter Roberson

Bill Reid said:
What you're really looking for is something called "POSIX",
which was initially developed based on Unix, but could potentially
apply to any computer system, and as a matter of fact is
included in the "C" compilers for many different types of
systems.

POSIX is included in the C compilers for "many different types of
systems"?? Would I be likely to recognize the names of any of
those systems??

POSIX is the "Portable Operating System Interface". A C compiler
does not implement operating system interfaces: to do so would
take them out of the realm of being *operating system* interfaces
into the realm of being *application* entities.

Sometimes C compilers bundle in, as extensions, header files useful
with POSIX -- but the operating system behaviours are left to
the operating system to implement, not delivered by the C compiler.


Are you aware of the following, Bill?

http://support.microsoft.com/kb/308259

POSIX and OS/2 are not supported in Windows XP or in Windows Server 2003

INTRODUCTION
There is no support for POSIX or OS/2 programs in Microsoft Windows
XP-based or in Microsoft Windows Server 2003-based operating
systems.

http://www.microsoft.com/downloads/...01-325e-487f-a398-efde5758c47f&displaylang=en

Overview
Utilities and SDK for UNIX-Based Applications is an add-on to the
Subsystem for UNIX-Based Applications (referred to as SUA, hence
forth) component that shipped in Microsoft Windows Vista /
Windows Server 2008 RTM. [...]

System Requirements

* Supported Operating Systems: Windows Server 2008; Windows
Vista Enterprise; Windows Vista Enterprise 64-bit edition;
Windows Vista Service Pack 1; Windows Vista Ultimate; Windows
Vista Ultimate 64-bit edition


If it was just a matter of having the right C compiler, then why
the restrictions on the supported editions? Why no support for
Vista Starter, Vista Home, Vista Home Premium, or Vista Business ?
 
N

Nick Keighley

On 11 Aug 2008 at 23:57, Hongyu wrote:

It will "work", but it is a stupid solution.

this is probably so, under Posix. On another OS it may be the only
way.

"Brian" is a troll who
wants to disrupt the group with endless topicality and netnanny flame
wars,

"Twink" is a troll who wants to disrupt the group by massive off-topic
postings.
and in this case he has led you down the wrong path. Running
programs using system() can be a security issue,

I doubt it is a security issue with mkdir. But this is off-topic
on comp.lang.c anyway.

and you get no way of
discovering errors that may occur.

Instead, use the portable POSIX solution:

but not necessarily portable to non-Posix systems.

#include <sys/stat.h>
#include <sys/types.h>

then do something like

if(mkdir("my_new_directory", S_IRWXU | S_IRWXG | S_IRWXO) == -1) {
  /* an error occurred - check errno to find out what */} else {

  /* success - carry on */

<snip>
 
R

Richard Tobin

It will "work", but it is a stupid solution.
[/QUOTE]
this is probably so, under Posix. On another OS it may be the only
way.

Very unlikely - do you know of any operating system where that is
true?. And the system() version is just as unportable as the mkdir()
version, because you have to know what the operating system's command
for creating directories is. If you can find that out, you can find
out what the function is.

-- Richard
 
S

santosh

Richard said:
Very unlikely - do you know of any operating system where that is
true?. And the system() version is just as unportable as the mkdir()
version, because you have to know what the operating system's command
for creating directories is. If you can find that out, you can find
out what the function is.

Well, with interactive programs, one *could* query the user for the
system's directory creation command, while a function is hard-coded...
 
D

Dik T. Winter

> In article <29290ece-45b5-473a-a12e-a64b4494a68d@l64g2000hse.googlegroups.com>, ....
>
> Very unlikely - do you know of any operating system where that is
> true?

Original System V Unix.
> And the system() version is just as unportable as the mkdir()
> version, because you have to know what the operating system's command
> for creating directories is. If you can find that out, you can find
> out what the function is.

But in System V Unix the function to create a directory is not sufficient.
You need also the functions to create links to the parent directory en
to the directory itself. And only "root" is allowed to do that.
 
H

Hongyu

In some system-specific manner.

Assuming a Unix-like system, fopen("/foo/bar/newfile.txt", "w") could
implicitly invoke the equivalent of "mkdir -p /foo/bar" before
actually creating the file.

That's just one example.  The point is that the C standard doesn't
mention directories at all.  There's nothing in the standard that says
an implementation *can't* create a directory as a side effect of
creating a file.

(I'm not aware of any actual implementation that does this.)

--
Keith Thompson (The_Other_Keith) (e-mail address removed)  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"- Hide quoted text -

- Show quoted text -

Thanks everyone's help. The discussion really helps, not only just on
my specific question, but also on the good coding styles etc. I think
what you mentioned here is what I tried in the beginning, but
unfortunately it didn't work, unless i create the directory first. I
am als in a Unix-like system (Linux). I think as people suggested
here, "POSIX" functions are way to go. I will study it more and try
it, and let people know the result after the testing.
 
H

Hongyu

Thanks everyone's help. The discussion really helps, not only just on
my specific question, but also on the good coding styles etc. I think
what you mentioned here is what I tried in the beginning, but
unfortunately it didn't work, unless i create the directory first. I
am als in a Unix-like system (Linux). I think as people suggested
here, "POSIX" functions are way to go. I will study it more and try
it, and let people know the result after the testing.- Hide quoted text -

- Show quoted text -

The discussion is really helpful and interesting. Thanks everyone's
help again. For some unknown reasons, my questioning post was not
appeared in the unix.programmer group discussion board. But from the
suggestions here, I got the code to work. Just to let people with
similar questions know how to solve the problem, here is the code I
used and POISX is the way to go. It should be mentioned that multi-
level subdirectories can only be created in the code recursively or
the parent directory is exist and writtable first (i didn't do
recursive coding in the code here).

#include <stdio.h>
#include <errno.h>
#include <error.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>

int main(void)
{
char fname[40] = "mytestout.txt"; //filename
//char fpath[40] = "./testdir1/testdir2"; // filepath, doesn't work
unless testdir1 is exist and writable
char fpath[40] = "./testdir1"; // filepath, worked!
//char fpath[40] = "."; //filepath. curent directory. worked!
char wholename[100]; //filename with full path
int last;

last = (int)strlen(fpath)-1; // last char of path

//make sure the path is ended with '/'
if ((last >= 0) && (fpath[last] != '/'))
{
last++;
fpath[last] = '/'; // append '\' at the last of path
fpath[last+1] = '\0'; // terminate the path char string
}

strcpy(wholename, fpath);

strcat(wholename, fname);

// create the directory if it is not exist
if(access(fpath, F_OK) != 0) // directory nonexist
{ // actually I don't need to check this
// because the man mkdir says 'create a
directory
// if it is non-exist'. But to make
sure, keep it here

// create the directory with read/write/search permissions for
owner and group,
// and with read/search permissions for others
if(mkdir(fpath,S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)
{
printf("Failed to create directory %s\n", fpath);
return EXIT_FAILURE;
}
}

// write to file whose name is spcified with full path
FILE *fp = fopen(wholename, "w");
if (fp == NULL)
{
error(0, errno, "could not open %s", fname);
exit(EXIT_FAILURE);
}
else
{
fprintf(fp, "This is just a test!");
fclose(fp);
}

return EXIT_SUCCESS;

}
 
H

Hongyu

Thanks everyone's help. The discussion really helps, not only just on
my specific question, but also on the good coding styles etc. I think
what you mentioned here is what I tried in the beginning, but
unfortunately it didn't work, unless i create the directory first. I
am als in a Unix-like system (Linux). I think as people suggested
here, "POSIX" functions are way to go. I will study it more and try
it, and let people know the result after the testing.- Hide quoted text -
- Show quoted text -

The discussion is really helpful and interesting. Thanks everyone's
help again. For some unknown reasons, my questioning post was not
appeared in the unix.programmer group discussion board. But from the
suggestions here, I got the code to work. Just to let people with
similar questions know how to solve the problem, here is the code I
used and POISX is the way to go.  It should be mentioned that multi-
level subdirectories can only be created in the code recursively or
the parent directory is exist and writtable first (i didn't do
recursive coding in the code here).

#include <stdio.h>
#include <errno.h>
#include <error.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>

int main(void)
{
   char fname[40] = "mytestout.txt";  //filename
   //char fpath[40] = "./testdir1/testdir2"; // filepath, doesn't work
unless testdir1 is exist and writable
   char fpath[40] = "./testdir1"; // filepath, worked!
   //char fpath[40] = ".";  //filepath. curent directory. worked!
   char wholename[100]; //filename with full path
   int last;

   last = (int)strlen(fpath)-1; // last char of path

   //make sure the path is ended with '/'
   if ((last >= 0) && (fpath[last] != '/'))
   {
      last++;
      fpath[last] = '/'; // append '\' at the last of path
      fpath[last+1] = '\0'; // terminate the path char string
   }

   strcpy(wholename, fpath);

   strcat(wholename, fname);

   // create the directory if it is not exist
   if(access(fpath, F_OK) != 0) // directory nonexist
   {                            // actually I don't need to check this
                               // because the man mkdir says 'create a
directory
                               // if it is non-exist'. But to make
sure, keep it here

      // create the directory with read/write/search permissions for
owner and group,
      // and with read/search permissions for others
      if(mkdir(fpath,S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)
      {
        printf("Failed to create directory %s\n", fpath);
        return EXIT_FAILURE;
      }
   }

   // write to file whose name is spcified with full path
   FILE *fp = fopen(wholename, "w");
    if (fp == NULL)
   {
      error(0, errno, "could not open %s", fname);
      exit(EXIT_FAILURE);
   }
   else
   {
      fprintf(fp, "This is just a test!");
      fclose(fp);
   }

   return EXIT_SUCCESS;



}- Hide quoted text -

- Show quoted text -- Hide quoted text -

- Show quoted text -

Sorry, the code didn't appear 100% right after the posting since the
comment lines get adjusted. Here is after the re-adjusting to make it
right:

#include <stdio.h>
#include <errno.h>
#include <error.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>


int main(void)
{
char fname[40] = "mytestout.txt"; //filename
//char fpath[40] = "./testdir1/testdir2"; // filepath, doesn't work
unless testdir1 is exist and writable
char fpath[40] = "./testdir1"; // filepath, worked!
//char fpath[40] = "."; //filepath. curent directory. worked!
char wholename[100]; //filename with full path
int last;


last = (int)strlen(fpath)-1; // last char of path


//make sure the path is ended with '/'
if ((last >= 0) && (fpath[last] != '/'))
{
last++;
fpath[last] = '/'; // append '\' at the last of path
fpath[last+1] = '\0'; // terminate the path char string
}


strcpy(wholename, fpath);


strcat(wholename, fname);


// create the directory if it is not exist
if(access(fpath, F_OK) != 0) // directory nonexist
{ // actually I don't need to check
this
// because the man mkdir says 'create a
directory
// if it is non-exist'. But to make
sure, keep it here


// create the directory with read/write/search permissions for
owner and group,
// and with read/search permissions for others
if(mkdir(fpath,S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)
{
printf("Failed to create directory %s\n", fpath);
return EXIT_FAILURE;
}
}


// write to file whose name is spcified with full path
FILE *fp = fopen(wholename, "w");
if (fp == NULL)
{
error(0, errno, "could not open %s", fname);
exit(EXIT_FAILURE);
}
else
{
fprintf(fp, "This is just a test!");
fclose(fp);
}


return EXIT_SUCCESS;

}
 
H

Hongyu

The discussion is really helpful and interesting. Thanks everyone's
help again. For some unknown reasons, my questioning post was not
appeared in the unix.programmer group discussion board. But from the
suggestions here, I got the code to work. Just to let people with
similar questions know how to solve the problem, here is the code I
used and POISX is the way to go.  It should be mentioned that multi-
level subdirectories can only be created in the code recursively or
the parent directory is exist and writtable first (i didn't do
recursive coding in the code here).
#include <stdio.h>
#include <errno.h>
#include <error.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
int main(void)
{
   char fname[40] = "mytestout.txt";  //filename
   //char fpath[40] = "./testdir1/testdir2"; // filepath, doesn't work
unless testdir1 is exist and writable
   char fpath[40] = "./testdir1"; // filepath, worked!
   //char fpath[40] = ".";  //filepath. curent directory. worked!
   char wholename[100]; //filename with full path
   int last;
   last = (int)strlen(fpath)-1; // last char of path
   //make sure the path is ended with '/'
   if ((last >= 0) && (fpath[last] != '/'))
   {
      last++;
      fpath[last] = '/'; // append '\' at the last of path
      fpath[last+1] = '\0'; // terminate the path char string
   }
   strcpy(wholename, fpath);
   strcat(wholename, fname);
   // create the directory if it is not exist
   if(access(fpath, F_OK) != 0) // directory nonexist
   {                            // actually I don't need to check this
                               // because the man mkdir says 'create a
directory
                               // if it is non-exist'. But to make
sure, keep it here
      // create the directory with read/write/search permissions for
owner and group,
      // and with read/search permissions for others
      if(mkdir(fpath,S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)
      {
        printf("Failed to create directory %s\n", fpath);
        return EXIT_FAILURE;
      }
   }
   // write to file whose name is spcified with full path
   FILE *fp = fopen(wholename, "w");
    if (fp == NULL)
   {
      error(0, errno, "could not open %s", fname);
      exit(EXIT_FAILURE);
   }
   else
   {
      fprintf(fp, "This is just a test!");
      fclose(fp);
   }
   return EXIT_SUCCESS;
}- Hide quoted text -
- Show quoted text -- Hide quoted text -
- Show quoted text -

Sorry, the code didn't appear 100% right after the posting since the
comment lines get adjusted. Here is after the re-adjusting to make it
right:

#include <stdio.h>
#include <errno.h>
#include <error.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>

int main(void)
{
   char fname[40] = "mytestout.txt";  //filename
   //char fpath[40] = "./testdir1/testdir2"; // filepath, doesn't work
unless testdir1 is exist and writable
   char fpath[40] = "./testdir1"; // filepath, worked!
   //char fpath[40] = ".";  //filepath. curent directory. worked!
   char wholename[100]; //filename with full path
   int last;

   last = (int)strlen(fpath)-1; // last char of path

   //make sure the path is ended with '/'
   if ((last >= 0) && (fpath[last] != '/'))
   {
      last++;
      fpath[last] = '/'; // append '\' at the last of path
      fpath[last+1] = '\0'; // terminate the path char string
   }

   strcpy(wholename, fpath);

   strcat(wholename, fname);

   // create the directory if it is not exist
   if(access(fpath, F_OK) != 0) // directory nonexist
   {                            // actually I don't need to check
this
                               // because the man mkdir says 'create a
directory
                               // if it is non-exist'. But to make
sure, keep it here

      // create the directory with read/write/search permissions for
owner and group,
      // and with read/search permissions for others
      if(mkdir(fpath,S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)
      {
        printf("Failed to create directory %s\n", fpath);
        return EXIT_FAILURE;
      }
   }

   // write to file whose name is spcified with full path
   FILE *fp = fopen(wholename, "w");
    if (fp == NULL)
   {
      error(0, errno, "could not open %s", fname);
      exit(EXIT_FAILURE);
   }
   else
   {
      fprintf(fp, "This is just a test!");
      fclose(fp);
   }

   return EXIT_SUCCESS;



}- Hide quoted text -

- Show quoted text -- Hide quoted text -

- Show quoted text -

I adjusted above, but after posting, the comment line were not so
correct again. Anyway, the code is working just ignore those comments.
 
C

CBFalconer

Hongyu said:
Thanks everyone's help. The discussion really helps, not only
just on my specific question, but also on the good coding styles
etc. I think what you mentioned here is what I tried in the
beginning, but unfortunately it didn't work, unless i create the
directory first. I am als in a Unix-like system (Linux). I think
as people suggested here, "POSIX" functions are way to go. I will
study it more and try it, and let people know the result after
the testing.

Unless you have specific reasons for needing to use POSIX
functions, you should stick to the standard C functions. Most of
the time the standard functions will be adequate, and in some cases
the results will be more efficient. Using things outside the C
standard always reduces your portability.
 
A

Antoninus Twink

Unless you have specific reasons for needing to use POSIX
functions,

The OP needs to create a directory in a UNIXy operating system. Using
the functions provided by POSIX is the best way to do this by a country
mile.
you should stick to the standard C functions. Most of the time the
standard functions will be adequate, and in some cases the results
will be more efficient.

Which "standard" function is adequate in this case? (hint: none)
Using things outside the C standard always reduces your portability.

You are letting the tail wag the dog. In real life, there's something
you need to get done and you try to do it as portably as possible. Your
attitude is instead that whatever you do must be portable to a 1970s
mainframe or an embedded system controlling a wristwatch, even if that
means you can't actually fulfill your objectives.

But it's hopeless arguing with you - you're a silly old fart who can't
be reasoned with.
 
B

Ben Bacarisse

... For some unknown reasons, my questioning post was not
appeared in the unix.programmer group discussion board.

For your information: one question did appear in comp.unix.programmer
and got three replies and a clarification. You asked a specific
question that got answered. A more open question might have got
better answers.
 
S

s0suk3

... snip ...



Unless you have specific reasons for needing to use POSIX
functions, you should stick to the standard C functions.  Most of
the time the standard functions will be adequate, and in some cases
the results will be more efficient.  Using things outside the C
standard always reduces your portability.

LOL. Portability? What would that portable equivalent be?

Sebastian
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,228
Members
46,818
Latest member
SapanaCarpetStudio

Latest Threads

Top