system("mv") vs: open()...

system("mv") vs: open()...

Post by Chris Sonna » Fri, 22 Mar 1996 04:00:00



Any thoughts on which is best if I want to rename AND move a file when
I know I'll be renaming cross-device?

EASY WAY OUT:
-------------
        sprintf (buff, "mv %s %s", oldname, newname);
        system (buff);

LESS EASY (BETTER?):
--------------------
        int  ofd = open (oldname, O_RDONLY);
        int  nfd = open (newname, O_WRONLY|O_CREAT, 0777);

    /** read() & write() loop using a LARGE buffer **/

    close (nfd), close (ofd);

??????,
--

Engineering Information Services/Information Technology/3M, St.Paul, Minn
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TODAY'S RULE: No Smoffing or Fnargling!

Opinions expressed herein are my own and may not represent those of 3M.

 
 
 

system("mv") vs: open()...

Post by Ruurd Beerst » Sat, 23 Mar 1996 04:00:00


: Any thoughts on which is best if I want to rename AND move a file when
: I know I'll be renaming cross-device?

: EASY WAY OUT:
: -------------
:       sprintf (buff, "mv %s %s", oldname, newname);
:       system (buff);

: LESS EASY (BETTER?):
: --------------------
:       int  ofd = open (oldname, O_RDONLY);
:       int  nfd = open (newname, O_WRONLY|O_CREAT, 0777);

:     /** read() & write() loop using a LARGE buffer **/

:     close (nfd), close (ofd);

: ??????,
: --

: Engineering Information Services/Information Technology/3M, St.Paul, Minn
: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
: TODAY'S RULE: No Smoffing or Fnargling!

: Opinions expressed herein are my own and may not represent those of 3M.
--
========================================================================
Ruurd Beerstra, CMG-IT, Netherlands. | #include <stddisclaimer.h>



 
 
 

system("mv") vs: open()...

Post by Kevin Cli » Sat, 23 Mar 1996 04:00:00


 >Any thoughts on which is best if I want to rename AND move a file when
 >I know I'll be renaming cross-device?
 >
 >EASY WAY OUT:
 >-------------
 >   sprintf (buff, "mv %s %s", oldname, newname);
 >   system (buff);
 >
 >LESS EASY (BETTER?):
 >--------------------
 >   int  ofd = open (oldname, O_RDONLY);
 >   int  nfd = open (newname, O_WRONLY|O_CREAT, 0777);
 >
 >    /** read() & write() loop using a LARGE buffer **/
 >
 >    close (nfd), close (ofd);
 >
 >??????,

If you aren't concerned with speed, then by all means use option 1.
It will be slower than option 2 due to the cost of forking and exec'ing
first the shell and then mv.

You left out a third possibility, intermediate in speed:
fork and exec mv yourself.

        char* argv[3];
        argv[0] = "mv";
        argv[1] = oldname;
        argv[2] = newname;
        pid_t pid;
        if (pid = fork()) {
                int status;
                while (waitpid(pid, &status, 0) < 0 && errno == EINTR);
        }
        else {
                execv("/bin/mv", argv);
        }

Well, that is even more complicated than copying the files yourself.
Just use option 1; then if the files ever are on the same file system
you won't pay the cost of the copy.
--
Kevin Cline

 
 
 

system("mv") vs: open()...

Post by Matt DiM » Sat, 23 Mar 1996 04:00:00



>Any thoughts on which is best if I want to rename AND move a file when
>I know I'll be renaming cross-device?

I'd use mv, rather than copying it myself.  mv normally mmap's the input
file, which is faster than read().  You could, of course, do that yourself,
but all it saves is a fork()/exec(), which will be small compared to the
move.

Use fork()/exec() rather than system, though (just religion).

 
 
 

system("mv") vs: open()...

Post by David Hallin » Mon, 25 Mar 1996 04:00:00





>>Any thoughts on which is best if I want to rename AND move a file when
>>I know I'll be renaming cross-device?

>I'd use mv, rather than copying it myself.  mv normally mmap's the input
>file, which is faster than read().  You could, of course, do that yourself,
>but all it saves is a fork()/exec(), which will be small compared to the
>move.

If speed is so critical that you want to use an mmap() solution, here
is a possible code outline.  I wrote this program as an excuse to
learn mmap() so let me know if there's something wrong with it.


/*** begin prog ***/
#include <stdio.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>  /* for fstat() */
#include <sys/mman.h>  /* for mmap()  */
#include <fcntl.h>     /* for open()  */
#include <unistd.h>    /* for write() */

/*
 *  Move a file via mmap().   (Usefull for moving a file across
 *  filesystems.)  Abort() is currently called if any error occurs.
 */
void move(const char *oldName, const char *newName)
{
  int oFd, nFd;
  int ret;
  int mask;
  struct stat st;
  caddr_t nAddr, oAddr;

  /*
   *  Open and map the old file name
   */
  oFd = open(oldName, O_RDONLY);
  assert( oFd > 0 );

  /* get the size and protections for the old name */
  ret = fstat(oFd, &st);
  assert( ret == 0 );

  /* map old.  MAP_SHARED would behave the same as MAP_PRIVATE here */
  oAddr = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, oFd, 0);
  assert( oAddr != (caddr_t)-1 );

  /* we don't need the descriptor once the file is mapped */
  ret = close( oFd );
  assert( ret == 0 );

  /*
   *  Open and map the new file name.  Keep old protections.  According to
   *  the manpage we should be able to open this file with O_WRONLY as
   *  long as it's mapped with PROT_WRITE, but mmap() fails unless the
   *  file is opened with both read and write privs here.  Explanations??
   */
  mask = umask(0);
  nFd = open(newName, O_CREAT | O_TRUNC | O_RDWR, st.st_mode);
  assert( nFd > 0 );
  umask(mask);

  /* extend  the new file name as mmap() won't do it for us */
  ret = lseek(nFd, st.st_size - 1, SEEK_SET);
  assert( ret != -1 );
  ret = write(nFd, "", 1);
  assert( ret == 1 );

  /* map the new file */
  nAddr = mmap(0, st.st_size, PROT_WRITE, MAP_SHARED, nFd, 0);
  assert( nAddr != (caddr_t)-1 );

  /* close descriptor */
  ret = close( nFd );
  assert( ret == 0 );

  /* Copy the data over */
  memcpy(nAddr, oAddr, st.st_size);

  /* unmap both files */
  ret = munmap(oAddr, st.st_size);
  assert( ret == 0 );
  ret = munmap(nAddr, st.st_size);
  assert( ret == 0 );

  /* unlink the old file name */
  ret = remove( oldName );
  assert( ret == 0 );

Quote:}

/*
 *  Usage:  a.out <old path> <new path>
 */
int main(int argc, char *argv[])
{
  assert( argc == 3 );
  move(argv[1], argv[2]);
  return 0;

Quote:}

/*** end prog ***/
 
 
 

system("mv") vs: open()...

Post by Guy Harr » Tue, 26 Mar 1996 04:00:00



>  oAddr = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, oFd, 0);

This may fail if the file is *really* large.  Note that SunOS 4.x's "cp"
command does "mmap()"-based copying a megabyte at a time.
 
 
 

system("mv") vs: open()...

Post by Michael Maxi » Tue, 26 Mar 1996 04:00:00



   (Matt DiMeo) writes:

  <SNIP>

Matt> Use fork()/exec() rather than system, though (just religion).

More than religion.  If running setuid root, system is a security
risk.


Regards,
--


                        Under Construction -->       http://www.crl.com/~maxie

 
 
 

system("mv") vs: open()...

Post by Chris Sonna » Tue, 26 Mar 1996 04:00:00



> You left out a third possibility, intermediate in speed:
> fork and exec mv yourself.

>    char* argv[3];
>    argv[0] = "mv";
>    argv[1] = oldname;
>    argv[2] = newname;
>    pid_t pid;
>    if (pid = fork()) {
>            int status;
>            while (waitpid(pid, &status, 0) < 0 && errno == EINTR);
>    }
>    else {
>            execv("/bin/mv", argv);
>    }

Certainly a very viable idea. How does it compare to:

    sprintf (tmp, "exec /bin/mv %s %s", oldname, newname);
    system (tmp);

(Someone emailed me the idea of using exec in the system() call. That
also saves a fork().)

--

Engineering Information Services/Information Technology/3M, St.Paul, Minn
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A Waste is a terrible thing to Mind.

Opinions expressed herein are my own and may not represent those of 3M.

 
 
 

system("mv") vs: open()...

Post by Scott Narves » Thu, 28 Mar 1996 04:00:00




>> You left out a third possibility, intermediate in speed:
>> fork and exec mv yourself.

>>        char* argv[3];
>>        argv[0] = "mv";
>>        argv[1] = oldname;
>>        argv[2] = newname;
>>        pid_t pid;
>>        if (pid = fork()) {
>>                int status;
>>                while (waitpid(pid, &status, 0) < 0 && errno == EINTR);
>>        }
>>        else {
>>                execv("/bin/mv", argv);
>>        }
>Certainly a very viable idea. How does it compare to:
>    sprintf (tmp, "exec /bin/mv %s %s", oldname, newname);
>    system (tmp);
>(Someone emailed me the idea of using exec in the system() call. That
>also saves a fork().)

Rolling your own fork/exec saves an exec over the system-based solution
above (sytem(3) forks, child execs /bin/sh, then sh execs mv).  Also, in
the roll-your-own, I'd do the following, to make sure mv thinks it's given
two arguments:

        char* argv[4];
        argv[0] = "mv";
        argv[1] = oldname;
        argv[2] = newname;
        argv[3] = 0;            /* or NULL, depending on your religion */

...and be sure to check the status from the wait.

Regarding the original question: for a simple utility, I'd probably invoke
mv one way or t'other, mostly because "fork/exec + mv" is likely to be
cheaper than the "efficiencies" of hand-done reads and writes (ie, things
in /bin usually do their task about as well as can reasonably be done;
lacking source, I wouldn't waste time trying to better them).

On the other hand, if you need very close control over error-handling in
your code, you may wish to avoid invoking subprograms.  Something like mv
will just scribble messages on its stderr and exit with non-zero status if
something goes awry.  If, say, you're implementing a library, you may not
want your code to volunteer output in that fashion, and avoiding that
behavior adds to more work (now we're talking pipe/dup sorts of things).

>--

>Engineering Information Services/Information Technology/3M, St.Paul, Minn
>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>A Waste is a terrible thing to Mind.

--


               \ Cray Research, Inc.  \ 655F Lone Oak Drive \ Eagan, MN 55121

 
 
 

system("mv") vs: open()...

Post by Stephen Bayn » Fri, 29 Mar 1996 04:00:00


: Any thoughts on which is best if I want to rename AND move a file when
: I know I'll be renaming cross-device?

Assuming you have an ANSI C compiler

        man rename

As far as I know it should work across devices, but it may depend on your
implementation.

--

Philips Semiconductors Ltd
Southampton                                 My views are my own.
United Kingdom

 
 
 

system("mv") vs: open()...

Post by Chris Sonna » Fri, 29 Mar 1996 04:00:00



> Regarding the original question: for a simple utility, I'd probably invoke
> mv one way or t'other, mostly because "fork/exec + mv" is likely to be
> cheaper than the "efficiencies" of hand-done reads and writes (ie, things
> in /bin usually do their task about as well as can reasonably be done;
> lacking source, I wouldn't waste time trying to better them).

Nor would I. I was wondering about the overhead of the sub-process(es).
I know the cost of spawning new processes is much, much less than in some
OSes (e.g. VMX -- very high new process overhead), but was wondering if
it might be high enough to justify rolling my own.

Quote:> On the other hand, if you need very close control over error-handling in
> your code, you may wish to avoid invoking subprograms.  Something like mv
> will just scribble messages on its stderr and exit with non-zero status if
> something goes awry.  If, say, you're implementing a library, you may not
> want your code to volunteer output in that fashion, and avoiding that
> behavior adds to more work (now we're talking pipe/dup sorts of things).

You know, I hadn't considered that aspect. This IS a library I'm building!

thanks!!,
--

Engineering Information Services/Information Technology/3M, St.Paul, Minn
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"If two million people do a foolish thing, it's still a foolish thing."

Opinions expressed herein are my own and may not represent those of 3M.

 
 
 

1. Type "(", ")" and "{", "}" in X...

Hi,

When i start a shell under X, i can type all characters on my keyboard,
the same when i start the simple editor, but when i start Forte (Java
IDE) written in Java i cant use the "(", ")", "{", "}" and allmost none
of the characters that are located on the same key as a number...

Does anybody have an idea what i can do about that... could it be
something with programs written in Java..?

Mvg,
Erwin

Sent via Deja.com http://www.deja.com/
Before you buy.

2. FreeBSD as a firewall for IP packed changes

3. "umsdos" vs "vfat" vs "looped ext2"

4. 5.0.0 release supplement

5. "Standard Journaled File System" vs "Large File Enabled Journaled File System"

6. My PPP over serial line to slow!

7. "Open" vs. "Closed" (was Re: Netscape: FREE!)

8. Backup of SP

9. GETSERVBYNAME()????????????????????"""""""""""""

10. AIX, C Language, Multi-process : fopen(..."a+") and mv

11. """"""""My SoundBlast 16 pnp isn't up yet""""""""""""

12. SSA/Veritas: use "vxassist move" or "vxsd mv"

13. Bizzare "cp" and "mv" commands