OVH Cloud OVH Cloud

Déplacer un fichier d'une partition à l'autre

22 réponses
Avatar
Robert CHERAMY
Bonjour,

je cherche (dans un programme C++) à déplacer un fichier d'une partition
à l'autre, ce qui n'est pas possible avec la fonction rename(), qui
renvoit dans ce cas l'erreur "Invalid cross-device link".

J'ai cherché dans google, regardé dans la glib, dans les sources du
programme mv:
* google: recherches infructueuses, je dois être trop bête pour trouver
la requête qui va bien.
* glib: la commande g_rename ne fait rien de plus qu'appeler rename, ce
qui ne m'avance pas :-)
* mv: c'est un peu trop complexe pour un "déplacement de rien du tout" ;-)

Avez-vous des idées ?

Merci!

tibob

10 réponses

1 2 3
Avatar
Jean-Louis Liagre
Robert CHERAMY wrote:
Bonjour,

je cherche (dans un programme C++) à déplacer un fichier d'une partition
à l'autre, ce qui n'est pas possible avec la fonction rename(), qui
renvoit dans ce cas l'erreur "Invalid cross-device link".


Correct, déplacer un fichier d'un système de fichier à un autre ne
peut pas être effectué par un simple renommage, c'est à dire sans
déplacement des données.

J'ai cherché dans google, regardé dans la glib, dans les sources du
programme mv:
* google: recherches infructueuses, je dois être trop bête pour trouver
la requête qui va bien.
* glib: la commande g_rename ne fait rien de plus qu'appeler rename, ce
qui ne m'avance pas :-)
* mv: c'est un peu trop complexe pour un "déplacement de rien du tout" ;-)


C'est pourtant ce qu'il faut faire: une recopie du fichier suivie
de l'effacement du fichier source.

Avatar
Robert CHERAMY
Jean-Louis Liagre wrote:
C'est pourtant ce qu'il faut faire: une recopie du fichier suivie
de l'effacement du fichier source.
Snif... moi qui pensait m'en sortir plus facilement...


Pour info, il semble que QT4 fait le travail pour vous avec la fonction
QFile::rename(). Mais tout le monde ne peut utiliser C++ et QT4 (surtout
quand on ne fait que corriger un bug...)

Merci Jean-Louis et A+,

tibob

Avatar
Fred
Jean-Louis Liagre wrote:

C'est pourtant ce qu'il faut faire: une recopie du fichier suivie
de l'effacement du fichier source.


Snif... moi qui pensait m'en sortir plus facilement...

Pour info, il semble que QT4 fait le travail pour vous avec la fonction
QFile::rename(). Mais tout le monde ne peut utiliser C++ et QT4 (surtout
quand on ne fait que corriger un bug...)

Merci Jean-Louis et A+,

tibob


Pas besoin de chercher midi à quatorze heures :

sprintf(ch, "mv %s %s", sourcePath, destPath);
system(ch);

La commande mv fait un cp et un rm lorsque les partitions de départ et
d'arrivée sont différentes.

A+


Avatar
Nicolas George
Fred wrote in message
<dr25qm$brc$:
Pas besoin de chercher midi à quatorze heures :

sprintf(ch, "mv %s %s", sourcePath, destPath);
system(ch);


Bravo la sécurité !

Avatar
Fred
Fred wrote in message
<dr25qm$brc$:

Pas besoin de chercher midi à quatorze heures :

sprintf(ch, "mv %s %s", sourcePath, destPath);
system(ch);



Bravo la sécurité !



Il n'était pas question de sécurité dans le cahier des charges ;)
A+
Fred


Avatar
Antoine Leca
In news:dr0jdj$6b4$, Robert CHERAMY va escriure:
Jean-Louis Liagre wrote:
C'est pourtant ce qu'il faut faire: une recopie du fichier suivie
de l'effacement du fichier source.
Snif... moi qui pensait m'en sortir plus facilement...



Bah non, pas possible.
Deux systèmes de fichiers sont physiquement distincts. Donc il faut
physiquement écrire le contenu du fichier dans le système de destination
(opération de copie de fichier), et [ensuite] physiquement libérer l'espace
sur le système source (opération d'effacement).

Si vous avez une autre solution, vous allez droit au Nobel.


Antoine


Avatar
Nicolas George
Fred wrote in message
<dr2oa7$js3$:
Il n'était pas question de sécurité dans le cahier des charges ;)


Il est _toujours_ question de sécurité quand on programme.

Accessoirement, ta solution se vautre sur les fichiers dont le nom comporte
un espace.

Avatar
lhabert
Fred :

sprintf(ch, "mv %s %s", sourcePath, destPath);
system(ch);



Bravo la sécurité !



Il n'était pas question de sécurité dans le cahier des charges ;)


Un trou de sécurité sans attaquant, ça reste un bug. Il y en a certes où il
faut le faire exprès pour tomber dedans, mais celui-là, non, il est vraiment
béhant.



Avatar
Harpo
Fred wrote:

Fred wrote in message
<dr25qm$brc$:

Pas besoin de chercher midi à quatorze heures :

sprintf(ch, "mv %s %s", sourcePath, destPath);
system(ch);


Bravo la sécurité !



Il n'était pas question de sécurité dans le cahier des charges ;)


Tu mènes quand même une vie dangereuse...

1 - system( ) n'est pas très sûr, surtout si on est suid / sgid. on ne
peut guère l'employer que lorsqu'on est sûr que le programme ne sera
pas utilisé dans ces conditions, c'est à dire pas très souvent.
Utiliser plutôt fork( ), execv( )/execve( ), waitpid( ).
2 - sprintf( ) mérite un peu d'attention dans son emploi. Ici, c'est un
des cas où il peut être utilisé car la taille de la chaîne résultante
est prévisible.

Si tu tiens à utiliser system( ), ce qui peut peut-être (?) se concevoir
dans ce cas, il faut prendre un minimum de précautions.
Voilà un petit programme qui appelle mv et s'utilise comme mv :

-----------------------------
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define FORMAT "/bin/mv %s %s"
#define FORMAT_SIZE ( sizeof( FORMAT ) - 5 )

int main( int argc, char ** argv ){
char * cmd = NULL;
char * from;
char * to;
size_t len;
int rc;

if ( argc < 3 ) {
fprintf( stderr, "Not enough arguments.n" );
fprintf( stderr, "usage : mymove from-file to-filen" );
return( EXIT_FAILURE );
}
from = *(argv + 1);
to = *(argv + 2);
len = FORMAT_SIZE + strlen( from ) + strlen( to );
cmd = malloc( len + 1 );
if ( cmd == NULL ) {
fprintf( stderr, "Cannot allocate memory for mv commandn" );
return( EXIT_FAILURE ) ;
}
rc = sprintf( cmd, FORMAT, from, to );
if ( rc != (int) len ) {
fprintf( stderr, "sprintf failed rc=%dn", rc );
return( EXIT_FAILURE ) ;
}
rc = system( cmd );
if ( rc ) {
fprintf( stderr, "Cannot execute command below rc=%d :n'%s'n",
WEXITSTATUS( rc ), cmd );
if ( WIFSIGNALED( rc ) ) {
fprintf( stderr, "Killed by signal %d.n", WTERMSIG( rc ) );
}
return( EXIT_FAILURE ) ;
}
return( EXIT_SUCCESS ) ;
}
-----------------------------



Avatar
Loïc Restoux
Le 28 jan, à 10:36, Harpo papotait :
Tu mènes quand même une vie dangereuse...


Hmmmm... voyons...
(Attention, je vais etre HS).

2 - sprintf( ) mérite un peu d'attention dans son emploi. Ici, c'est un
des cas où il peut être utilisé car la taille de la chaîne résultante
est prévisible.


[SNIP]

-----------------------------
#define FORMAT "/bin/mv %s %s"
#define FORMAT_SIZE ( sizeof( FORMAT ) - 5 )
^^^^^

Aie :
- La constante FORMAT_SIZE ne contient donc *pas* la taille de la
constante FORMAT. Mauvais nommage.
- On a le nombre 5 en dur, si quelqu'un modifie la chaine de format sans
chercher à comprendre, ça ne marchera plus.
- Dans les calculs qui suivent, on perd l'espace séparateur entre les
deux arguments...

int main( int argc, char ** argv ){
char * cmd = NULL;
char * from;
char * to;
size_t len;
int rc;

if ( argc < 3 ) {
fprintf( stderr, "Not enough arguments.n" );
fprintf( stderr, "usage : mymove from-file to-filen" );
return( EXIT_FAILURE );
}
from = *(argv + 1);
to = *(argv + 2);
len = FORMAT_SIZE + strlen( from ) + strlen( to );


Ici, len ne tient pas compte du fameux espace séparateur des deux
arguments. Par contre, on y trouve le caractère terminal de la chaine de
format.

cmd = malloc( len + 1 );


Pour quoi +1, puisque l'on a compté le caractère terminal de la chaine
de format ? Coup de bol, ça rattrape le fameux espace que l'on avait
perdu en cours de route.

if ( cmd == NULL ) {
fprintf( stderr, "Cannot allocate memory for mv commandn" );
return( EXIT_FAILURE ) ;
}
rc = sprintf( cmd, FORMAT, from, to );
if ( rc != (int) len ) {
fprintf( stderr, "sprintf failed rc=%dn", rc );
return( EXIT_FAILURE ) ;
}


Ca rentre pile poil. On a eu chaud.

Ou alors, c'était fait exprès dès le départ, mais dans ce cas là, je
plains franchement le mainteneur du bout de code, il va avoir du mal à
retrouver ces petits.

Et puis, ça manque de commentaires. :)

--
No fortunes found

1 2 3