int rapi_copy(char *source, char *dest) { int result = 1; HRESULT hr; time_t start; time_t duration; size_t bytes_copied = 0; hr = CeRapiInit(); if (RAPI_FAILED(hr)) { fprintf(stderr, "Unable to initialize RAPI: %s\n", synce_strerror(hr)); goto exit; } if (!dest) { char* p; if (is_remote_file(source)) { for (p = source + strlen(source); p != source; p--) { if (*p == '/' || *p == '\\') { dest = (char *) strdup(p+1); break; } } if (!dest || '\0' == dest[0]) { fprintf(stderr, "Unable to extract destination filename from source path '%s'\n", source); goto exit; } } else { WCHAR mydocuments[MAX_PATH]; char* mydocuments_ascii = NULL; p = strrchr(source, '/'); if (p) p++; else p = source; if ('\0' == *p) { fprintf(stderr, "Unable to extract destination filename from source path '%s'\n", source); goto exit; } if (!CeGetSpecialFolderPath(CSIDL_PERSONAL, sizeof(mydocuments), mydocuments)) { fprintf(stderr, "Unable to get the \"My Documents\" path.\n"); goto exit; } dest = (char *) calloc(1, 1 + wstr_strlen(mydocuments) + 1 + strlen(p) + 1); mydocuments_ascii = wstr_to_ascii(mydocuments); strcat(dest, ":"); strcat(dest, mydocuments_ascii); strcat(dest, "\\"); strcat(dest, p); wstr_free_string(mydocuments_ascii); } } if (0 == strcmp(source, dest)) { fprintf(stderr, "You don't want to copy a file to itself.\n"); goto exit; } if (is_remote_file(source) && is_remote_file(dest)) { /* * * Both are remote; use CeCopyFile() * */ if (!remote_copy(source, dest)) goto exit; } else { start = time(NULL); /* * * At least one is local, Use the AnyFile functions * */ if (!anyfile_copy(source, dest, &bytes_copied)) goto exit; } result = 0; exit: CeRapiUninit(); return result; }
CEOID _CeWriteRecordProps( RapiContext *context, HANDLE hDbase, CEOID oidRecord, WORD cPropID, CEPROPVAL* rgPropVal)/*{{{*/ { CEOID return_value = 0; unsigned data_offset = 0; void * send_buf = NULL; void * send_buf_pos = NULL; unsigned local_array_size = 0; unsigned local_total_size = 0; unsigned send_array_size = 0; unsigned send_total_size = 0; unsigned data_size = 0; unsigned i; /* * Format of the CeWriteRecordProps packet - primitives are encoded in the CEPROPVAL structures, lpwstr and blob properties are * attached to the end of the buffer and referenced by offset pointers * * long hDBase | long oidRecord | long cPropID | long datalen (of following data) | n * CEPROPVAL | char[] data * */ rapi_database_trace("begin"); rapi_context_begin_command(context, 0x11); rapi_buffer_write_uint32(context->send_buffer, hDbase); rapi_buffer_write_uint32(context->send_buffer, oidRecord); rapi_buffer_write_uint16(context->send_buffer, cPropID); /* * we have to go through the rgPropVals array two times: * 1. to determine the size of the whole buffer, including data * 2. to write out the CEPROPVAL array followed by the data segment */ /* * 1. calculate the length of the whole buffer, including the data segment at the end */ for ( i = 0; i < cPropID; i++ ) { switch ( ( rgPropVal[i].propid ) & 0xFFFF ) { case CEVT_BLOB: data_size += rgPropVal[i].val.blob.dwCount; break; case CEVT_LPWSTR: data_size += sizeof(WCHAR) * ( wstr_strlen( rgPropVal[i].val.lpwstr ) + 1 ); break; default: break; } ALIGN(data_size); } local_total_size = local_array_size = cPropID * sizeof(CEPROPVAL); /* length of all cepropvals */ send_total_size = send_array_size = cPropID * 16; local_total_size += data_size; send_total_size += data_size; rapi_database_trace("Array size = %i", local_array_size); rapi_database_trace("Total size = %i", local_total_size); rapi_database_trace("Send array size = %i", send_array_size); rapi_database_trace("Send total size = %i", send_total_size); rapi_buffer_write_uint32(context->send_buffer, send_total_size); /* * 2. write out the CEPROPVAL array * * make a copy of the buffer, converting endianness, converting pointers to 32 bit offsets, and * appending extra data to the array data */ send_buf = calloc(1, send_total_size); for (i = 0, data_offset = send_array_size, send_buf_pos = send_buf; i < cPropID; i++) { if (!PreparePropValForWriting(&data_offset, send_buf, &send_buf_pos, rgPropVal[i])) { rapi_database_error("PreparePropValForWriting failed"); goto exit; } ALIGN(data_offset); } if (data_offset != send_total_size) { rapi_database_error("Data offset is %08x but should be %08x", data_offset, send_total_size); goto exit; } if (!rapi_buffer_write_data(context->send_buffer, send_buf, send_total_size)) { rapi_database_error("rapi_buffer_write_data failed"); goto exit; } if ( !rapi_context_call(context) ) { rapi_database_error("rapi_context_call failed"); goto exit; } if ( !rapi_buffer_read_uint32(context->recv_buffer, &context->last_error) ) goto exit; rapi_database_trace("context->last_error=0x%08x", context->last_error); if ( !rapi_buffer_read_uint32(context->recv_buffer, &return_value) ) { rapi_database_trace("failed to read return value"); return_value = 0; goto exit; } rapi_database_trace("return_value=0x%08x", return_value); exit: free(send_buf); send_buf = NULL; return return_value; }/*}}}*/
int main(int argc, char** argv) { int result = 1; RapiConnection* connection = NULL; char* source = NULL; char* dest = NULL; HRESULT hr; time_t start; time_t duration; size_t bytes_copied = 0; if (!handle_parameters(argc, argv, &source, &dest)) goto exit; if ((connection = rapi_connection_from_path(devpath)) == NULL) { fprintf(stderr, "%s: Could not find configuration at path '%s'\n", argv[0], devpath?devpath:"(Default)"); goto exit; } rapi_connection_select(connection); hr = CeRapiInit(); if (FAILED(hr)) { fprintf(stderr, "%s: Unable to initialize RAPI: %s\n", argv[0], synce_strerror(hr)); goto exit; } if (!dest) { char* p; if (is_remote_file(source)) { for (p = source + strlen(source); p != source; p--) { if (*p == '/' || *p == '\\') { dest = strdup(p+1); break; } } if (!dest || '\0' == dest[0]) { fprintf(stderr, "%s: Unable to extract destination filename from source path '%s'\n", argv[0], source); goto exit; } } else { WCHAR mydocuments[MAX_PATH]; char* mydocuments_ascii = NULL; p = strrchr(source, '/'); if (p) p++; else p = source; if ('\0' == *p) { fprintf(stderr, "%s: Unable to extract destination filename from source path '%s'\n", argv[0], source); goto exit; } if (!CeGetSpecialFolderPath(CSIDL_PERSONAL, sizeof(mydocuments), mydocuments)) { fprintf(stderr, "%s: Unable to get the \"My Documents\" path.\n", argv[0]); goto exit; } dest = calloc(1, 1 + wstr_strlen(mydocuments) + 1 + strlen(p) + 1); mydocuments_ascii = wstr_to_current(mydocuments); strcat(dest, ":"); strcat(dest, mydocuments_ascii); strcat(dest, "\\"); strcat(dest, p); wstr_free_string(mydocuments_ascii); } } if (0 == strcmp(source, dest)) { fprintf(stderr, "You don't want to copy a file to itself.\n"); goto exit; } if (is_remote_file(source) && is_remote_file(dest)) { /* * Both are remote; use CeCopyFile() */ if (!remote_copy(source, dest)) goto exit; } else { start = time(NULL); /* * At least one is local, Use the AnyFile functions */ if (!anyfile_copy(source, dest, argv[0], &bytes_copied)) goto exit; duration = time(NULL) - start; if (0 == duration) printf("File copy took less than one second!\n"); else printf("File copy of %i bytes took %li minutes and %li seconds, that's %li bytes/s.\n", bytes_copied, duration / 60, duration % 60, bytes_copied / duration); } result = 0; exit: if (source) free(source); if (dest) free(dest); CeRapiUninit(); return result; }
static bool PreparePropValForWriting(unsigned* data_offset, void *send_buf, void **send_buf_pos, CEPROPVAL propval)/*{{{*/ { bool success = true; rapi_database_trace("Preparing value of type %i", propval.propid & 0xffff); *((CEPROPID*)*send_buf_pos) = htole32(propval.propid); *send_buf_pos += 4; *((WORD*)*send_buf_pos) = htole16(propval.wLenData); *send_buf_pos += 2; *((WORD*)*send_buf_pos) = htole16(propval.wFlags); *send_buf_pos += 2; switch (propval.propid & 0xffff) { case CEVT_BLOB: *((DWORD*)*send_buf_pos) = htole32(propval.val.blob.dwCount); *send_buf_pos += 4; /* don't use LPBYTE for propval->val.blob.lpb because it's a 32 bit offset */ *((DWORD*)*send_buf_pos) = (DWORD)htole32(*data_offset); *send_buf_pos += 4; memcpy((LPBYTE)(send_buf + *data_offset), propval.val.blob.lpb, propval.val.blob.dwCount); *data_offset += propval.val.blob.dwCount; break; case CEVT_BOOL: *((uint32_t*)*send_buf_pos) = htole32(propval.val.boolVal); *send_buf_pos += 8; break; case CEVT_FILETIME: *((uint32_t*)*send_buf_pos) = htole32(propval.val.filetime.dwLowDateTime); *send_buf_pos += 4; *((uint32_t*)*send_buf_pos) = htole32(propval.val.filetime.dwHighDateTime); *send_buf_pos += 4; break; case CEVT_I2: *((int16_t*)*send_buf_pos) = htole16(propval.val.iVal); *send_buf_pos += 8; break; case CEVT_I4: *((int32_t*)*send_buf_pos) = htole32(propval.val.lVal); *send_buf_pos += 8; break; case CEVT_LPWSTR: if (propval.val.lpwstr) { size_t size = sizeof(WCHAR) * (wstr_strlen(propval.val.lpwstr) + 1); rapi_database_trace_wstr(propval.val.lpwstr); *((DWORD*)*send_buf_pos) = (DWORD)htole32(*data_offset); rapi_database_trace("String offset: %u", *((DWORD*)*send_buf_pos)); memcpy((LPBYTE)send_buf + *data_offset, propval.val.lpwstr, size); *data_offset += size; *send_buf_pos += 8; } else { rapi_database_error("String property value is NULL"); success = false; } break; case CEVT_UI2: *((uint16_t*)*send_buf_pos) = htole16(propval.val.uiVal); *send_buf_pos += 8; break; case CEVT_UI4: *((uint32_t*)*send_buf_pos) = htole32(propval.val.ulVal); *send_buf_pos += 8; break; case CEVT_R8: /* TODO: convert endianness for this, need to set up 64 swap in synce.h */ memcpy(*send_buf_pos, &(propval.val), 8); *send_buf_pos += 8; break; default: rapi_database_error("Don't know how to prepare value type 0x%04x", propval.propid & 0xffff); success = false; break; } return success; }/*}}}*/