Jeff Laing avatar Jeff Laing committed 94cb69b

Put source and target into notifications
Add method for recursive copying of directories

Comments (0)

Files changed (2)

MobileDeviceAccess.h

 - (BOOL)rename:(NSString*)oldpath to:(NSString*)newpath;
 
 /**
+ * Create a hard link on the device.
+ * @param linkname Full pathname of link to create
+ * @param target Target of link
+ */
+- (BOOL)link:(NSString*)linkname to:(NSString*)target;
+
+/**
+ * Create a symbolic link on the device.
+ * @param linkname Full pathname of symbolic link to create
+ * @param target Target of symbolic link
+ */
+- (BOOL)symlink:(NSString*)linkname to:(NSString*)target;
+
+/**
+ * Copy the contents of a local file or directory (on the Mac) to
+ * a directory on the device.  The copy is recursive (for directories)
+ * and will copy symbolic links as links.
+ * @param frompath Full pathname of the local file/directory
+ * @param topath Full pathname of the device directory to copy into
+ */
+- (BOOL)copyLocalFile:(NSString*)frompath toRemoteDir:(NSString*)topath;
+
+/**
  * Copy the contents of a local file (on the Mac) to the device.
  * @param frompath Full pathname of the local file
  * @param topath Full pathname of the device file to copy into

MobileDeviceAccess.m

 afc_error_t AFCDirectoryCreate(afc_connection conn,const char *dirname);
 afc_error_t AFCRemovePath(afc_connection conn,const char *dirname);
 afc_error_t AFCRenamePath(afc_connection conn,const char *from,const char *to);
-//afc_error_t AFCLinkPath(afc_connection conn,const char *from,const char *to);
-//	NSLog(@"linkpath returned %#lx",AFCLinkPath(_afc,"/tmp/aaa","/tmp/bbb"));
+afc_error_t AFCLinkPath(afc_connection conn,uint64_t mode, const char *target,const char *link);
+//	NSLog(@"linkpath returned %#lx",AFCLinkPath(_afc,(1=hard,2=sym)"/tmp/aaa","/tmp/bbb"));
 
 // file i/o functions
 afc_error_t AFCFileRefOpen(afc_connection conn, const char *path, uint64_t mode,afc_file_ref *ref);
 	return [self checkStatus:AFCRenamePath(_afc, [path1 UTF8String], [path2 UTF8String]) from:"AFCRenamePath"];
 }
 
+- (BOOL)link:(NSString*)path to:(NSString*)target
+{
+	if (!path) {
+		[self setLastError:@"Path is nil"];
+		return NO;
+	}
+	if (!target) {
+		[self setLastError:@"Target is nil"];
+		return NO;
+	}
+	if (![self ensureConnectionIsOpen]) return NO;
+	return [self checkStatus:AFCLinkPath(_afc, 1, [target UTF8String], [path UTF8String]) from:"AFCLinkPath"];
+}
+
+
+- (BOOL)symlink:(NSString*)path to:(NSString*)target
+{
+	if (!path) {
+		[self setLastError:@"Path is nil"];
+		return NO;
+	}
+	if (!target) {
+		[self setLastError:@"Target is nil"];
+		return NO;
+	}
+	if (![self ensureConnectionIsOpen]) return NO;
+	return [self checkStatus:AFCLinkPath(_afc, 2, [target UTF8String], [path UTF8String]) from:"AFCLinkPath"];
+}
+
 - (AFCFileReference*)openForRead:(NSString*)path
 {
 	if (![self ensureConnectionIsOpen]) return nil;
 				NSMutableDictionary *info = [[NSMutableDictionary new] autorelease];
 				struct stat s;
 				stat([path1 fileSystemRepresentation],&s);
+				[info setObject:path1 forKey:@"Source"];
+				[info setObject:path2 forKey:@"Target"];
 				[info setObject:[NSNumber numberWithInt:s.st_size] forKey:@"Size"];
 				[nc postNotificationName:@"AFCFileCopyBegin" object:self userInfo:info];
 				// open remote file for write
 	return result;
 }
 
+- (BOOL)copyLocalFile:(NSString*)path1 toRemoteDir:(NSString*)path2
+{
+	NSFileManager *fm = [NSFileManager defaultManager];
+	NSString *fname;
+	BOOL isdir;
+	isdir = NO;
+	if ([fm fileExistsAtPath:path1 isDirectory:&isdir]) {
+		if (isdir) {
+			// create the target directory
+			NSString *basename = [path2 stringByAppendingPathComponent:[path1 lastPathComponent]];
+			if (![self mkdir:basename]) return NO;
+			for (fname in [fm contentsOfDirectoryAtPath:path1 error:nil]) {
+				BOOL worked;
+				worked = [self copyLocalFile:[path1 stringByAppendingPathComponent:fname]
+						toRemoteDir:basename];
+				if (!worked) {
+					NSLog(@"failed on %@/%@: %@",path1,fname,self.lasterror);
+					return NO;
+				}
+			}
+			return YES;
+		} else {
+			fname = [path1 lastPathComponent];
+			NSString *dest = [path2 stringByAppendingPathComponent:fname];
+			char buff[PATH_MAX+1];
+			ssize_t buflen = readlink([path1 UTF8String], buff, sizeof(buff));
+			if (buflen>0) {
+				buff[buflen] = 0;
+				return [self symlink:dest to:[NSString stringWithUTF8String:buff]];
+			} else {
+				return [self copyLocalFile:path1 toRemoteFile:dest];
+			}
+		}
+	}
+
+	return NO;
+}
+
 - (BOOL)copyRemoteFile:(NSString*)path1 toLocalFile:(NSString*)path2
 {
 	BOOL result = NO;
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.