2013-05-21 7 views
1

BSD copyfile (...)을 사용하여 파일을 마운트 된 AFP 공유 (/ Volumes/exchange)에 복사하려고합니다.)이 같은의 Obj-C++ 코드 :Mac OS 10.7.5 BSD copyfile() 이름에 큰 따옴표가있는 파일을 복사 할 때 EINVAL

최소 예 :

#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; 
} 

저장이 copyfile.mm 예를하고 컴파일 :

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

그것은 내 대상 파일 이름하지 않는 한 (toPath 잘 작동) 포함하다 큰 따옴표. 그럼 내가 얻을

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

또한 정상적인 C++에서 작동하지만 Obj-C++에서는 실패합니다.

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

맥 OS 10.7.5 및 GCC 4.2.1 : - ++의 Obj-C와 나는 또한 다음 SYSTEM.LOG에 메시지가 표시

$ 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

내가 "(\ 파일 이름"CopyFile 수'로 ("XC"를, 그것을 시도 할 때 작동 [~! @ # $으로의 %^& * ,. '] \ ") .MP4", s, COPYFILE_ALL)을 AFP 볼륨에 저장하십시오. [자체 포함 가능한 컴파일 가능한 예] (http://sscce.org)를 보여 주어야합니다. –

+0

@EricPostpischil, 나는 g ++로 컴파일 된 SSCCE C++ 파일을 사용해 보았지만 나에게도 효과적이다. 문제는 Obj-C++에서 호출 할 때 발생합니다. 나는 'xcodebuild'와 잘 맞지 않으므로 적절한 SSCCE를 제공하는 데 약간의 시간이 걸릴 것입니다 ... – 2can

+0

@EricPostpischil 최소 예제를 추가했습니다. – 2can

답변

0

으로 에릭 Postpischil에 의해 지적되었다 (감사 !) - 네트워크 공유에 문제가있었습니다. 최신 netatalk 버전으로 업그레이드하고 올바른 설정을 netatalk config로 설정하면 내 코드가 변경되지 않고 작동합니다.

(죄송합니다 늦게 답장을 보내 주셔서, 여러분 :)