[comp.unix.questions] mv'ing files from a C program

ggvvgg@mixcom.UUCP (Dave Fenske) (11/15/90)

Is there an easy way to do an 'mv' from a C program?

I just want to be able to move a recently read file into another directory,
and wish to avoid having to write it there.  Using the 'system' call is
not deemed wiable for this application.

DF

cpcahil@virtech.uucp (Conor P. Cahill) (11/15/90)

In article <22@mixcom.UUCP> ggvvgg@mixcom.UUCP (Dave Fenske) writes:
>Is there an easy way to do an 'mv' from a C program?

If you are on a BSD based system you have the rename(2) system call.

For other systems without rename you can emulate a move with the
following sequence (assuming that the directories for both files are
on the same filesystem):

		unlink(newfile)
		link(oldfile,newfile)
		unlink(oldfile)

Of course, you should use the appropriate error detection to ensure
that you don't remove the oldfile if the link was not successfull.

If the files are not on the same filesystem, the only way to do it
is a full copy.  You can do this by hand or by calling the mv command.


>I just want to be able to move a recently read file into another directory,
>and wish to avoid having to write it there.  Using the 'system' call is
>not deemed wiable for this application.

You don't have to use system(3), you can use fork/execl(2) (or one of it's 
family of functions) as follows:

	if( fork() == 0 )
		execl("/bin/mv","mv",oldfile,newfile,(char *)0);
	else
		wait((int *)0);

Again, you will probably want to add better error handling, this is just an 
example of one way to do it.	


-- 
Conor P. Cahill            (703)430-9247        Virtual Technologies, Inc.,
uunet!virtech!cpcahil                           46030 Manekin Plaza, Suite 160
                                                Sterling, VA 22170 

weimer@ssd.kodak.com (Gary Weimer) (11/16/90)

In article <22@mixcom.UUCP> ggvvgg@mixcom.UUCP (Dave Fenske) writes:
>Is there an easy way to do an 'mv' from a C program?
>
>I just want to be able to move a recently read file into another directory,
>and wish to avoid having to write it there.  Using the 'system' call is
>not deemed wiable for this application.
>

You could simulate the mv command using link(2) and unlink(2). First create
a second link in the new directory. If no error, remove first link (unlink).

weimer@ssd.kodak.com (Gary Weimer) (11/16/90)

In article <1990Nov15.132952.11932@virtech.uucp> cpcahil@virtech.UUCP (Conor P. Cahill) writes:
>You don't have to use system(3), you can use fork/execl(2) (or one of it's 
>family of functions) as follows:
>
>	if( fork() == 0 )
>		execl("/bin/mv","mv",oldfile,newfile,(char *)0);
>	else
>		wait((int *)0);

That's just about exactly what system(3) does. (i.e. you gain nothing for
all the added code)

kaleb@thyme.jpl.nasa.gov (Kaleb Keithley ) (11/16/90)

In article <1990Nov15.183359.963@ssd.kodak.com> weimer@ssd.kodak.com (Gary Weimer) writes:
>In article <1990Nov15.132952.11932@virtech.uucp> cpcahil@virtech.UUCP (Conor P. Cahill) writes:
>>You don't have to use system(3), you can use fork/execl(2) (or one of it's 
>>family of functions) as follows:
>>
>>	if( fork() == 0 )
>>		execl("/bin/mv","mv",oldfile,newfile,(char *)0);
>>	else
>>		wait((int *)0);
>
>That's just about exactly what system(3) does. (i.e. you gain nothing for
>all the added code)

Both seem kind of expensive.  What's wrong with rename....  (man 2 rename).
Since I jumped into the middle of this, I presume you're talking about
the same file system, which is a limitation on rename.

-- 
Kaleb Keithley                      Jet Propulsion Labs
kaleb@thyme.jpl.nasa.gov

I don't watch Twin Peaks; I just come to work.

cliffs@gaffa.East.Sun.COM (Clifford C. Skolnick) (11/16/90)

In article <22@mixcom.UUCP> ggvvgg@mixcom.UUCP (Dave Fenske) writes:
>Is there an easy way to do an 'mv' from a C program?
>
>I just want to be able to move a recently read file into another directory,
>and wish to avoid having to write it there.  Using the 'system' call is
>not deemed wiable for this application.
>
>DF

Do it like "mv"

int mv(oldpath, newpath)
char *oldpath, *newpath;
{
	int ret;

	if (ret = link(oldpath, newpath))
		return(ret); /* an error has occured */

	if (ret = unlink(oldpath))
		return(ret); /* gee, another error */

	return(0);
}
--
Cliff Skolnick - Technical Consultant | (716) 385-5049 | cliffs@east.sun.com
           [I only work for Sun, I do not speak for them]

         "The floggings will continue until morale improves"

gwyn@smoke.brl.mil (Doug Gwyn) (11/16/90)

In article <22@mixcom.UUCP> ggvvgg@mixcom.UUCP (Dave Fenske) writes:
>Is there an easy way to do an 'mv' from a C program?

Use the rename() function if you have it, otherwise system("mv...").

wdh@holos0.uucp (Weaver Hickerson) (11/16/90)

main()
{
link("Oldfile","Newfile");  /* link the Newfile with Oldfile */
unlink("Oldfile");          /* unlink the oldfile */

 /* link and unlink are described in your Programmer's ref manual */
}
-- 
-Weaver Hickerson   Voice (404) 496-1358   :  ..!edu!gatech!holos0!wdh

weimer@ssd.kodak.com (Gary Weimer) (11/16/90)

In article <1990Nov15.183359.963@ssd.kodak.com> weimer@ssd.kodak.com (Gary Weimer) writes:
>In article <1990Nov15.132952.11932@virtech.uucp> cpcahil@virtech.UUCP (Conor P. Cahill) writes:
>>You don't have to use system(3), you can use fork/execl(2) (or one of it's 
>>family of functions)...
>
>That's just about exactly what system(3) does. (i.e. you gain nothing for
>all the added code)

As others have pointed out, my above statement about system(3) is wrong.
Sorry for wasting bandwidth.

hunt@dg-rtp.rtp.dg.com (Greg Hunt) (11/17/90)

In article <22@mixcom.UUCP>, ggvvgg@mixcom.UUCP (Dave Fenske) writes:
> Is there an easy way to do an 'mv' from a C program?
> 
> I just want to be able to move a recently read file into another directory,
> and wish to avoid having to write it there.  Using the 'system' call is
> not deemed wiable for this application.
> 

You can use the 'rename' system call to do what you want.  Do something
like the following:

    status = rename ("/udd/olddir/myfile", "/udd/newdir/myfile");

If the new pathname and the old pathname are on the same file systems,
everything will work just fine.  If they are on different file systems,
it may or may not work depending on what your OS permits.  If it's
not allowed, then you'll have to copy the file to the new location
(which is what 'mv' would have to do in that case).  See the man page
for 'rename' for more details.

Enjoy!

--
Greg Hunt                        Internet: hunt@dg-rtp.rtp.dg.com
DG/UX Kernel Development         UUCP:     {world}!mcnc!rti!dg-rtp!hunt
Data General Corporation
Research Triangle Park, NC       These opinions are mine, not DG's.

cpcahil@virtech.uucp (Conor P. Cahill) (11/17/90)

In article <1990Nov15.183359.963@ssd.kodak.com> weimer@ssd.kodak.com (Gary Weimer) writes:
>In article <1990Nov15.132952.11932@virtech.uucp> cpcahil@virtech.UUCP (Conor P. Cahill) writes:
>>You don't have to use system(3), you can use fork/execl(2) (or one of it's 
>>family of functions) as follows:
>>
>>	if( fork() == 0 )
>>		execl("/bin/mv","mv",oldfile,newfile,(char *)0);
>>	else
>>		wait((int *)0);
>
>That's just about exactly what system(3) does. (i.e. you gain nothing for
>all the added code)

No.  System(3) does something like the following: (with error checking removed)

	if( fork() == 0)
		execl("/bin/sh", "-c", argstr, (char*)0);
	else
		wait(...

Note that it execs the shell, which then has to parse the string which
then gets exec'd from the shell.  Quite a bit different.

-- 
Conor P. Cahill            (703)430-9247        Virtual Technologies, Inc.,
uunet!virtech!cpcahil                           46030 Manekin Plaza, Suite 160
                                                Sterling, VA 22170 

jeff@onion.pdx.com (Jeff Beadles) (11/18/90)

wdh@holos0.uucp (Weaver Hickerson) writes:
>main()
>{
>link("Oldfile","Newfile");  /* link the Newfile with Oldfile */
>unlink("Oldfile");          /* unlink the oldfile */
>
> /* link and unlink are described in your Programmer's ref manual */
>}
>-- 
>-Weaver Hickerson   Voice (404) 496-1358   :  ..!edu!gatech!holos0!wdh


Bleep!  Wrong answer Weaver.  What if the files are on two seperate
filesystems?  Guess what?  You just deleted the original without making a
copy!  I think that the users wouldn't appreciate you for this.

In a pseudo-sorta way, here's how a move command should work if you are going
to go thru the hassles of actually writing one. (system("mv ...") is easier,
cleaner, and clearer IMHO)

This is just for a simple mv of two files.  It doesn't take into
consideration things like "mv /etc/passwd /tmp" where the dest is a directory.
Figure that one out by yourself... :-)

[Note: // does not imply C++, it's just easier to type :-]

mv(src,dest)
{
	// Easiest case, where the link works
	if link(src,dest) == success
		unlink(src)
		exit
	// If the error was not that it was across a filesystem, then it's fatal
	if error != EXDEV
		error- can't do it.
		exit with warning

	// At  this point, we know that it's a semi-legal operation,
	// just that it's across a filesystem.
	
	open(src,"r")

	// If file "dest" exists, and can be deleted (ie: not a directory)
	// then unlink the dest file after opening the src file.

	open(dest,"w")

	// read and copy src to dest (Checking for errors and stuff)

	// close src and dest (Checking for errors and stuff)

	// change permissions on dest to match src.

	// if all was ok, unlink src.  (If not, you MIGHT need to unlink dest)

	exit and bug-out.
}


Note, that this is a REAL rough draft of how mv would work if I wrote one from
scratch.  It's NOT complete, nor is it intended to be.

	-Jeff
-- 
Jeff Beadles		jeff@onion.pdx.com

guy@auspex.auspex.com (Guy Harris) (11/18/90)

>Both seem kind of expensive.  What's wrong with rename....  (man 2
>rename).

It's not present in all systems. 

It's present in (4.2andup)BSD-based systems, including System V Release
4.  (1/2 :-) - there are plenty of things from BSD in there....) It's
also specified by POSIX, so any POSIX-compliant system will have it.

It's not in vanilla S5R3 from AT&T (unless it snuck into S5R3.2 - some
vendors S5R3-based systems may have added it, but others may not have),
nor in any earlier AT&T releases.

yakker@ucrmath.ucr.edu (matt robinson) (11/19/90)

In article <22@mixcom.UUCP> ggvvgg@mixcom.UUCP (Dave Fenske) writes:
->Is there an easy way to do an 'mv' from a C program?
->

You might want to try out using rename(1).  Note that I believe this only
works if you are within the same partition, and it may not follow all
symbolic links.  There's a barrage of error returns from a rename(), so
take a look at what is in the manual.  (Sun has a massive list of return
codes from this call.)

Hope this helps.

--Matt

______________________________________________________________________________
Matt D. Robinson                                 "...if I only had a brain..."
Systems Programming Group, UC Riverside     -- The Scarecrow, The Wizard Of Oz
Internet : yakker@ucrmath.ucr.edu       UUCP : ..!ucsd!ucrmath!{yakker,source}

rwelch@diana.cair.du.edu (RANDY S WELCH) (11/21/90)

In article <1990Nov16.231909.20173@virtech.uucp> cpcahil@virtech.uucp (Conor P. Cahill) writes:

   Path: mercury.cair.du.edu!pikes!boulder!ncar!zaphod.mps.ohio-state.edu!usc!jarthur!uunet!virtech!cpcahil
   From: cpcahil@virtech.uucp (Conor P. Cahill)
   Newsgroups: comp.unix.questions
   Date: 16 Nov 90 23:19:09 GMT
   References: <22@mixcom.UUCP> <1990Nov15.132952.11932@virtech.uucp> <1990Nov15.183359.963@ssd.kodak.com>
   Reply-To: cpcahil@virtech.UUCP (Conor P. Cahill)
   Distribution: na
   Organization: Virtual Technologies Inc., Sterling VA
   Lines: 27

   In article <1990Nov15.183359.963@ssd.kodak.com> weimer@ssd.kodak.com (Gary Weimer) writes:
   >In article <1990Nov15.132952.11932@virtech.uucp> cpcahil@virtech.UUCP (Conor P. Cahill) writes:
   >>You don't have to use system(3), you can use fork/execl(2) (or one of it's 
   >>family of functions) as follows:
   >>
   >>	if( fork() == 0 )
   >>		execl("/bin/mv","mv",oldfile,newfile,(char *)0);
   >>	else
   >>		wait((int *)0);
   >
   >That's just about exactly what system(3) does. (i.e. you gain nothing for
   >all the added code)

Isn't invoking a shell a bit much to mv a file when you can
link(2)/unlink(2)?  

-randy

-- 
Randy Welch   Mail to :  ...!ncar!scicom!bldr!randy or rwelch@du.edu
Boulder, CO   VOICE   :  303-442-6717
"Unfortunately, life contains an unavoidable element of unpredictability"
-David Lynch "The Angriest Dog in the World"

cpcahil@virtech.uucp (Conor P. Cahill) (11/24/90)

In article <1990Nov21.061700.20005@mercury.cair.du.edu> rwelch@diana.cair.du.edu (RANDY S WELCH) writes:
>Isn't invoking a shell a bit much to mv a file when you can
>link(2)/unlink(2)?  

Yes it is.  However, if the files are not on the same file system you 
cannot do a link/unlink.  The fork/exec of mv was the last of three 
examples of how you could do the move without having to have your program
explicitly copy the file (requirement of original poster).

-- 
Conor P. Cahill            (703)430-9247        Virtual Technologies, Inc.,
uunet!virtech!cpcahil                           46030 Manekin Plaza, Suite 160
                                                Sterling, VA 22170 

guy@auspex.auspex.com (Guy Harris) (11/26/90)

>Isn't invoking a shell a bit much to mv a file when you can
>link(2)/unlink(2)?  

In this particular case, it probably is.  The original poster seemed to
be indicating that they wanted to move a file (i.e., not a directory),
and may have wanted to move it to another directory on the same file
system.

If they'd wanted to move a directory, then unless their system had
"rename(2)" (in which case, using "link(2)" and "unlink(2)" is a bit
much) or their program was running as super-user, they'd almost
certainly have to run "mv", as most UNIX systems disallow anybody but
the super-user from linking to or unlinking from a directory.  (And even
if it *is* running as super-user, I'd still be tempted to run "mv"
anyway, as there's more than just a simple "link()/"unlink()" pair
involved in moving a directory.)

Also, if they wanted to move it to another file system, running "mv" may
be more convenient than duplicating "mv"s "try to move it with
'remove()' or 'link()/unlink()' and, if you get EXDEV, copy it" action.