2013-05-21 2 views
1

J'essaie d'utiliser BSD copyfile (...) pour copier un fichier sur un partage AFP monté (/ Volumes/exchange) avec un code Obj-C++ comme ceci:Mac OS 10.7.5 BSD copyfile() EINVAL lors de la copie de fichiers avec des guillemets dans le nom

exemple minimal:

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

#import <Cocoa/Cocoa.h> 

int copyfile_callback(int what, int stage, copyfile_state_t state, const char * src, const char * dst, void * ctx); 
void copy_file(const std::string& src, const std::string& dst); 
NSString* StringToNSString (const std::string& Str); 

int main() 
{ 
    [NSAutoreleasePool new]; 
    [NSApplication sharedApplication]; 
    [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; 
    id menubar = [[NSMenu new] autorelease]; 
    id appMenuItem = [[NSMenuItem new] autorelease]; 
    [menubar addItem:appMenuItem]; 
    [NSApp setMainMenu:menubar]; 
    id appMenu = [[NSMenu new] autorelease]; 
    id appName = [[NSProcessInfo processInfo] processName]; 
    id quitTitle = [@"Quit " stringByAppendingString:appName]; 
    id quitMenuItem = [[[NSMenuItem alloc] initWithTitle:quitTitle 
     action:@selector(terminate:) keyEquivalent:@"q"] autorelease]; 
    [appMenu addItem:quitMenuItem]; 
    [appMenuItem setSubmenu:appMenu]; 
    id window = [[[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 200, 200) 
     styleMask:NSTitledWindowMask backing:NSBackingStoreBuffered defer:NO] 
      autorelease]; 
    [window cascadeTopLeftFromPoint:NSMakePoint(20,20)]; 
    [window setTitle:appName]; 
    [window makeKeyAndOrderFront:nil]; 

    copy_file(
     "copyfile.mm", 
     "/Volumes/exchange/filename(\"[[email protected]#$%^&*,.']\").MP4" 
    ); 

    [NSApp activateIgnoringOtherApps:YES]; 
    [NSApp run]; 
    return 0; 
} 

void copy_file(const std::string& fromPath, const std::string& toPath) 
{ 
    NSLog(@"copyfile: %s -> %s", fromPath.c_str(), toPath.c_str()); 
    copyfile_state_t s = copyfile_state_alloc(); 
    copyfile_state_set(s, COPYFILE_STATE_STATUS_CB, (void*)&copyfile_callback); 
    int returnCode = copyfile(fromPath.c_str(), toPath.c_str(), s, COPYFILE_ALL); 
    if(returnCode) { 
     NSLog(@"copyfile error code: %d, errno=%d", returnCode, errno); 
    } 
    copyfile_state_free(s); 
} 

int copyfile_callback(int what, int stage, copyfile_state_t state, const char * src, const char * dst, void * ctx) 
{ 
    bool bContinue = true; 
    switch(what) { 
     case COPYFILE_COPY_DATA: 
      if(stage == COPYFILE_PROGRESS) { 
       int src_fd; 
       off_t bytes_completed = 0L, total_bytes = 0L; 
       copyfile_state_get(state, COPYFILE_STATE_COPIED, (void*)&bytes_completed); 
       copyfile_state_get(state, COPYFILE_STATE_SRC_FD, (void*)&src_fd); 
       struct stat fstat_info; 
       if(src_fd > 0 && 0 == fstat(src_fd, &fstat_info)) { 
        total_bytes = fstat_info.st_size; 
       } 
       NSLog(@"copyfile_callback: Copied %lld/%lld bytes so far.", bytes_completed, total_bytes); 

      } else if(stage == COPYFILE_ERR) { 
       NSLog(@"copyfile: COPYFILE_COPY_DATA COPYFILE_ERR"); 
       bContinue = false; 
      } 
      break; 
     case COPYFILE_ERR: 
      bContinue = false; 
      break; 
    } 
    return bContinue ? COPYFILE_CONTINUE : COPYFILE_QUIT; 
} 

NSString* StringToNSString (const std::string& Str) 
{ 
    NSString *pString = [NSString stringWithCString:Str.c_str() 
              encoding:[NSString defaultCStringEncoding] 
         ]; 
    return pString; 
} 

Enregistrer cet exemple copyfile.mm et compiler avec:

g++ -framework Cocoa -x objective-c++ copyfile.mm -o copyfile 

Il fonctionne très bien à moins que mon nom de fichier de destination (toPath) contient un symbole de double-citation Puis je reçois

returnCode == -1; 
errno == 22; // EINVAL 

Il fonctionne également avec C++ normal, mais échoue avec Obj-C++. Avec Obj-C++ - Je vois aussi le message suivant dans le system.log:

5/21/13 11:47:51.314 PM myAppName: open on /Volumes/exchange/filename("[[email protected]#$%^&*,.']").MP4: Invalid argument 

Mac OS 10.7.5 et gcc 4.2.1:

$ g++ -v 
Using built-in specs. 
Target: i686-apple-darwin11 
Configured with: /private/var/tmp/llvmgcc42/llvmgcc42-2336.11~148/src/configure --disable-checking --enable-werror --prefix=/Applications/Xcode.app/Contents/Developer/usr/llvm-gcc-4.2 --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-prefix=llvm- --program-transform-name=/^[cg][^.-]*$/s/$/-4.2/ --with-slibdir=/usr/lib --build=i686-apple-darwin11 --enable-llvm=/private/var/tmp/llvmgcc42/llvmgcc42-2336.11~148/dst-llvmCore/Developer/usr/local --program-prefix=i686-apple-darwin11- --host=x86_64-apple-darwin11 --target=i686-apple-darwin11 --with-gxx-include-dir=/usr/include/c++/4.2.1 
Thread model: posix 
gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00) 
+0

Il fonctionne lorsque je tente avec 'copyfile ("xc", "nom de fichier (\"[~! @ # $%^& * ,. '] \ ") .MP4", s, COPYFILE_ALL) 'sur un volume AFP. Vous devriez montrer un [exemple compilable autonome] (http://sscce.org). –

+0

@EricPostpischil, j'ai essayé avec le fichier SSCCE C++ compilé avec g ++ et ça marche aussi pour moi. Le problème se pose lorsque j'appelle cela depuis Obj-C++. Je ne suis pas très bon avec 'xcodebuild', donc ça va prendre du temps pour fournir SSCCE ... – 2can

+0

@EricPostpischil J'ai ajouté un exemple minimal, veuillez vérifier – 2can

Répondre

0

Comme souligné par Eric Postpischil (merci !) - c'était un problème avec le partage réseau. Après la mise à niveau vers la dernière version de netatalk et la définition du paramètre correct pour netatalk config, mon code fonctionne sans aucun changement.

(désolé pour la réponse tardive, les gars :)

Questions connexes