This is an example of a application level file copy using the ConnectSMB Libraries
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
#include <unistd.h>
#include <ofc/config.h>
#include "smbinit.h"
#define BUFFER_SIZE OFC_MAX_IO
#define NUM_FILE_BUFFERS 10
typedef enum {
BUFFER_STATE_IDLE,
BUFFER_STATE_READ,
BUFFER_STATE_WRITE
} BUFFER_STATE;
typedef struct {
BUFFER_STATE state;
} OFC_FILE_BUFFER;
typedef enum {
ASYNC_RESULT_DONE,
ASYNC_RESULT_ERROR,
ASYNC_RESULT_EOF,
ASYNC_RESULT_PENDING
} ASYNC_RESULT;
struct copy_state {
};
static ASYNC_RESULT AsyncRead(
OFC_HANDLE wait_set,
OFC_FILE_BUFFER *buffer,
{
ASYNC_RESULT result;
buffer->state = BUFFER_STATE_READ;
{
result = ASYNC_RESULT_DONE;
}
else
{
{
buffer->readOverlapped);
result = ASYNC_RESULT_PENDING;
}
else
{
{
result = ASYNC_RESULT_EOF;
}
else
{
result = ASYNC_RESULT_ERROR;
}
buffer->state = BUFFER_STATE_IDLE;
}
}
return (result);
}
static ASYNC_RESULT AsyncReadResult(
OFC_HANDLE wait_set,
OFC_FILE_BUFFER *buffer,
{
ASYNC_RESULT result;
{
if (*dwLen == 0)
{
result = ASYNC_RESULT_EOF;
}
else
{
result = ASYNC_RESULT_DONE;
}
}
else
{
result = ASYNC_RESULT_PENDING;
else
{
{
result = ASYNC_RESULT_ERROR;
}
else
result = ASYNC_RESULT_EOF;
}
}
if (result != ASYNC_RESULT_PENDING)
{
buffer->state = BUFFER_STATE_IDLE;
}
return (result);
}
{
ASYNC_RESULT result;
buffer->offset);
buffer->state = BUFFER_STATE_WRITE;
buffer->writeOverlapped);
result = ASYNC_RESULT_DONE;
{
{
result = ASYNC_RESULT_PENDING;
}
else
{
result = ASYNC_RESULT_ERROR;
buffer->state = BUFFER_STATE_IDLE;
}
}
return (result);
}
static ASYNC_RESULT AsyncWriteResult(
OFC_HANDLE wait_set,
OFC_FILE_BUFFER *buffer,
{
ASYNC_RESULT result;
result = ASYNC_RESULT_DONE;
else
{
result = ASYNC_RESULT_PENDING;
else
{
result = ASYNC_RESULT_ERROR;
}
}
if (result != ASYNC_RESULT_PENDING)
{
buffer->state = BUFFER_STATE_IDLE;
}
return (result);
}
static OFC_VOID destroy_buffer(
struct copy_state *copy_state,
OFC_FILE_BUFFER *buffer)
{
{
}
{
}
{
free(buffer->data);
}
free(buffer);
}
static OFC_VOID destroy_buffer_list (
struct copy_state *copy_state,
{
OFC_FILE_BUFFER *buffer;
{
destroy_buffer(copy_state, buffer);
}
}
static OFC_HANDLE alloc_buffer_list(
struct copy_state *copy_state,
{
OFC_FILE_BUFFER *buffer;
for (int i = 0; i < NUM_FILE_BUFFERS && status; i++)
{
buffer = malloc(sizeof(OFC_FILE_BUFFER));
{
}
else
{
buffer->data = malloc(BUFFER_SIZE);
{
}
else
{
{
}
}
{
}
else
{
destroy_buffer(copy_state, buffer);
}
}
}
{
destroy_buffer_list(copy_state, buffer_list);
}
return (buffer_list);
}
static OFC_DWORD prime_buffers (
struct copy_state *copy_state)
{
OFC_FILE_BUFFER *buffer;
ASYNC_RESULT result;
{
dwLen = BUFFER_SIZE;
copy_state->pending++;
buffer->offset = copy_state->offset;
result = AsyncRead(copy_state->wait_set, copy_state->read_file,
buffer, dwLen, &dwLastError);
if (result != ASYNC_RESULT_PENDING)
{
copy_state->pending--;
}
copy_state->offset += BUFFER_SIZE;
}
return (dwLastError);
}
static OFC_VOID destroy_copy_state(
struct copy_state *copy_state)
{
{
destroy_buffer_list (copy_state, copy_state->buffer_list);
}
{
}
{
}
{
}
free(copy_state);
}
static struct copy_state *init_copy_state(
OFC_CTCHAR *rfilename,
{
struct copy_state *copy_state;
copy_state = malloc(sizeof(struct copy_state));
else
{
copy_state->offset = 0;
copy_state->pending = 0;
{
}
else
{
0,
{
}
}
{
{
}
}
{
copy_state->buffer_list = alloc_buffer_list(copy_state,
copy_state->read_file,
copy_state->write_file);
}
{
destroy_copy_state (copy_state);
}
}
return (copy_state);
}
static OFC_DWORD feed_buffers(
struct copy_state *copy_state)
{
OFC_FILE_BUFFER *buffer;
ASYNC_RESULT result;
while (copy_state->pending > 0)
{
{
if (buffer->state == BUFFER_STATE_READ)
{
result = AsyncReadResult(copy_state->wait_set,
copy_state->read_file,
buffer, &dwLen,
&dwLastError);
if (result == ASYNC_RESULT_ERROR)
dwFirstError = dwLastError;
else if (result == ASYNC_RESULT_DONE)
{
result = AsyncWrite(copy_state->wait_set,
copy_state->write_file,
buffer, dwLen,
&dwLastError);
if (result == ASYNC_RESULT_ERROR)
dwFirstError = dwLastError;
}
if (result == ASYNC_RESULT_ERROR ||
result == ASYNC_RESULT_EOF ||
(result == ASYNC_RESULT_DONE &&
{
copy_state->pending--;
}
}
else
{
result = AsyncWriteResult(copy_state->wait_set,
copy_state->write_file,
buffer, &dwLen,
&dwLastError);
if (result == ASYNC_RESULT_ERROR)
dwFirstError = dwLastError;
else if (result == ASYNC_RESULT_DONE)
{
buffer->offset = copy_state->offset;
copy_state->offset += BUFFER_SIZE;
result = AsyncRead(copy_state->wait_set,
copy_state->read_file,
buffer, BUFFER_SIZE,
&dwLastError);
if (result == ASYNC_RESULT_ERROR)
dwFirstError = dwLastError;
}
if (result != ASYNC_RESULT_PENDING)
{
copy_state->pending--;
}
}
}
}
return (dwFirstError);
}
{
struct copy_state *copy_state;
copy_state = init_copy_state(rfilename, wfilename, &dwLastError);
{
dwLastError = prime_buffers(copy_state);
{
dwLastError = feed_buffers(copy_state);
}
destroy_copy_state(copy_state);
}
return (dwLastError);
}
{
struct copy_state *copy_state;
{
}
else
{
0,
{
}
else
{
while ((ret =
OfcReadFile(read_file, buffer, BUFFER_SIZE,
{
}
{
}
}
}
return (dwLastError);
}
int main (int argc, char **argp)
{
size_t len;
mbstate_t ps;
const char *cursor;
int async = 0;
int argidx;
smbcp_init();
if (argc < 3)
{
printf ("Usage: smbcp [-a | -dc <bootstrap-dc>] <source> <destination>\n");
exit (1);
}
argidx = 1;
while (1)
{
if (strcmp(argp[argidx], "-a") == 0)
{
async = 1;
argidx++;
}
else if (strcmp(argp[argidx], "-dc") == 0)
{
argidx++;
memset(&ps, 0, sizeof(ps));
len = strlen(argp[argidx]) + 1;
argidx++;
}
else
break;
}
memset(&ps, 0, sizeof(ps));
len = strlen(argp[argidx]) + 1;
rfilename = malloc(sizeof(wchar_t) * len);
cursor = argp[argidx];
mbsrtowcs(rfilename, &cursor, len, &ps);
memset(&ps, 0, sizeof(ps));
len = strlen(argp[argidx+1]) + 1;
wfilename = malloc(sizeof(wchar_t) * len);
cursor = argp[argidx+1];
mbsrtowcs(wfilename, &cursor, len, &ps);
printf("Copying %s to %s: ", argp[argidx], argp[argidx+1]);
fflush(stdout);
if (async)
ret = copy_async(rfilename, wfilename);
else
ret = copy_sync(rfilename, wfilename);
free(rfilename);
free(wfilename);
int status;
{
printf("[ok]\n");
status = 0;
}
else
{
printf("[failed]\n");
status = 1;
}
printf("Deactivating Stack\n");
smbcp_deactivate();
exit(status);
}
@ OFC_ERROR_SUCCESS
Definition: file.h:1508
@ OFC_ERROR_HANDLE_EOF
Definition: file.h:1534
@ OFC_ERROR_NOT_ENOUGH_MEMORY
Definition: file.h:1515
@ OFC_ERROR_IO_PENDING
Definition: file.h:1591
OFC_CORE_LIB OFC_BOOL OfcCloseHandle(OFC_HANDLE hObject)
OFC_CORE_LIB const OFC_CHAR * ofc_get_error_string(OFC_DWORD dwerr)
OFC_CORE_LIB OFC_DWORD OfcGetLastError(OFC_VOID)
@ OFC_FILE_SHARE_READ
Definition: file.h:240
OFC_CORE_LIB OFC_BOOL OfcGetOverlappedResult(OFC_HANDLE hFile, OFC_HANDLE hOverlapped, OFC_LPDWORD lpNumberOfBytesTransferred, OFC_BOOL bWait)
OFC_CORE_LIB OFC_VOID OfcDestroyOverlapped(OFC_HANDLE hFile, OFC_HANDLE hOverlapped)
OFC_CORE_LIB OFC_BOOL OfcReadFile(OFC_HANDLE hFile, OFC_LPVOID lpBuffer, OFC_DWORD nNumberOfBytesToRead, OFC_LPDWORD lpNumberOfBytesRead, OFC_HANDLE hOverlapped)
#define OfcCreateFile
Definition: file.h:2623
OFC_CORE_LIB OFC_BOOL OfcWriteFile(OFC_HANDLE hFile, OFC_LPCVOID lpBuffer, OFC_DWORD nNumberOfBytesToWrite, OFC_LPDWORD lpNumberOfBytesWritten, OFC_HANDLE hOverlapped)
@ OFC_OPEN_EXISTING
Definition: file.h:258
@ OFC_CREATE_ALWAYS
Definition: file.h:254
OFC_CORE_LIB OFC_VOID OfcSetOverlappedOffset(OFC_HANDLE hFile, OFC_HANDLE hOverlapped, OFC_OFFT offset)
@ OFC_FILE_ATTRIBUTE_NORMAL
Definition: file.h:298
@ OFC_FILE_FLAG_OVERLAPPED
Definition: file.h:380
OFC_CORE_LIB OFC_HANDLE OfcCreateOverlapped(OFC_HANDLE hFile)
@ OFC_GENERIC_WRITE
Definition: file.h:211
@ OFC_GENERIC_READ
Definition: file.h:204
#define OFC_HANDLE_NULL
Definition: handle.h:64
OFC_CORE_LIB OFC_HANDLE ofc_handle_get_app(OFC_HANDLE hHandle)
OFC_DWORD_PTR OFC_HANDLE
Definition: handle.h:43
#define OFC_INVALID_HANDLE_VALUE
Definition: handle.h:52
OF_SMB_LIB OFC_VOID of_smb_set_bootstrap_dcs(OFC_UINT count, OFC_CHAR **dc)
OFC_CORE_LIB OFC_HANDLE ofc_queue_create(OFC_VOID)
OFC_CORE_LIB OFC_VOID ofc_enqueue(OFC_HANDLE qHead, OFC_VOID *qElement)
OFC_CORE_LIB OFC_VOID * ofc_queue_next(OFC_HANDLE qHead, OFC_VOID *qElement)
OFC_CORE_LIB OFC_VOID * ofc_dequeue(OFC_HANDLE qHead)
OFC_CORE_LIB OFC_VOID * ofc_queue_first(OFC_HANDLE qHead)
@ OFC_FALSE
Definition: types.h:632
@ OFC_TRUE
Definition: types.h:636
void OFC_VOID
Definition: types.h:159
OFC_LARGE_INTEGER OFC_OFFT
Definition: types.h:360
OFC_UINT8 OFC_BOOL
Definition: types.h:624
OFC_UINT32 OFC_DWORD
Definition: types.h:430
OFC_WCHAR OFC_TCHAR
Definition: types.h:463
#define OFC_NULL
Definition: types.h:656
char OFC_CHAR
Definition: types.h:143
const OFC_WCHAR OFC_CTCHAR
Definition: types.h:467
int OFC_INT
Definition: types.h:119
OFC_CORE_LIB OFC_VOID ofc_waitset_remove(OFC_HANDLE hSet, OFC_HANDLE hEvent)
OFC_CORE_LIB OFC_HANDLE ofc_waitset_create(OFC_VOID)
OFC_CORE_LIB OFC_VOID ofc_waitset_add(OFC_HANDLE hSet, OFC_HANDLE hApp, OFC_HANDLE hEvent)
OFC_CORE_LIB OFC_VOID ofc_waitset_destroy(OFC_HANDLE handle)
OFC_CORE_LIB OFC_HANDLE ofc_waitset_wait(OFC_HANDLE handle)