#include "stdafx.h"
#include "beCompat.h"
#include "betalk.h"
#include "authentication.h"
#include "readerWriter.h"
#include "printing.h"
#include "ubi_SplayTree.h"
#include "winsvc.h"
#include "NTServApp.h"
#include "myservice.h"
#define BT_MAX_THREADS 100
#define BT_MAX_RETRIES 3
#define BT_MAX_FILE_SHARES 128
#define BT_MAX_PRINTER_SHARES 16
#define BT_THREAD_NAME "BeServed Handler"
#define BT_HOST_THREAD_NAME "BeServed Host Publisher"
#define PATH_ROOT "/boot"
#define PATH_DELIMITER '/'
#ifndef iswhite
#define iswhite(c) ((c == ' ' || c == '\t'))
#endif
typedef struct
{
unsigned int type;
unsigned int length;
char *data;
} bt_arg_t;
typedef struct btblock
{
vnode_id vnid;
beos_off_t pos;
int32 len;
int32 count;
char *buffer;
struct btblock *next;
struct btblock *prev;
} bt_block;
typedef struct session
{
int socket;
unsigned int client_s_addr;
HANDLE handlerID;
bool killed;
char user[MAX_NAME_LENGTH + 1];
int share;
int rights;
time_t logon;
bt_block *rootBlock;
sem_id blockSem;
char ioBuffer[BT_MAX_IO_BUFFER + 1];
char attrBuffer[BT_MAX_ATTR_BUFFER + 1];
char pathBuffer[B_PATH_NAME_LENGTH];
struct session *next;
} bt_session_t;
typedef void (*bt_net_func)(bt_session_t *, unsigned int, int, bt_arg_t *);
typedef struct dirCommand
{
unsigned char command;
bt_net_func handler;
bool supported;
uint8 args;
uint32 argTypes[MAX_COMMAND_ARGS];
} bt_command_t;
typedef struct
{
vnode_id vnid;
int shareId;
char unused[20];
} bt_fdesc;
typedef struct btnode
{
ubi_trNode node;
vnode_id vnid;
char *name;
bool invalid;
struct btnode *parent;
} bt_node;
typedef struct fileShare
{
char path[B_PATH_NAME_LENGTH];
char name[B_FILE_NAME_LENGTH];
bool used;
bool readOnly;
bt_user_rights *rights;
int security;
struct fileShare *next;
} bt_fileShare_t;
typedef struct mime_mapping
{
char extension[7];
char *mimeType;
struct mime_mapping *next;
} bt_mime_mapping;
void BeServedStartup(CMyService *service);
bool dateCheck();
DWORD WINAPI btSendHost(LPVOID data);
void getHostInfo(bt_hostinfo *info);
int getSharedResources(char *buffer, int bufSize, bool shares, bool printers);
int getHostUsers(char *buffer);
void startService();
void endService(int sig);
void initMimeMap();
void closeMimeMap();
void closePrinters();
void freeFileShares();
void waitForThread(HANDLE threadId);
void initShares();
void initPrinters();
void loadShares();
void getFileShare(const char *buffer);
void loadFolder(const char *path);
void getShareProperty(const char *buffer);
void getAuthenticate(const char *buffer);
bool getAuthServerAddress(const char *name);
void addUserRights(char *share, char *user, int rights, bool isGroup);
void getGrant(const char *buffer);
void getPrinter(const char *buffer);
int getToken();
int receiveRequest(bt_session_t *session);
void handleRequest(bt_session_t *session, unsigned int xid, unsigned char command, int argc, bt_arg_t argv[]);
void launchThread(int client, struct sockaddr_in *addr);
int tooManyConnections(unsigned int _s_addr);
void sendErrorToClient(int client, unsigned int xid, int error);
void getArguments(bt_session_t *session, bt_inPacket *packet, unsigned char command);
DWORD WINAPI requestThread(LPVOID data);
DWORD WINAPI printerThread(LPVOID data);
void KillNode(ubi_trNodePtr node);
int CompareVnidNodes(ubi_trItemPtr item, ubi_trNodePtr node);
int CompareNameNodes(ubi_trItemPtr item, ubi_trNodePtr node);
bt_node *btGetNodeFromVnid(vnode_id vnid);
void btAddHandle(vnode_id dir_vnid, vnode_id file_vnid, char *name);
void btRemoveHandle(vnode_id vnid);
void btPurgeNodes(vnode_id vnid);
bool btIsAncestorNode(vnode_id vnid, bt_node *node);
char *btGetLocalFileName(char *path, vnode_id vnid);
void btMakeHandleFromNode(bt_node *node, vnode_id vnid);
bt_node *btFindNode(bt_node *parent, char *fileName);
char *btGetSharePath(char *shareName);
int btGetShareId(char *shareName);
int btGetShareIdByPath(char *path);
bt_printer *btFindPrinter(char *printerName);
uint32 btGetWinInode(const char *path);
int btGetBeosStat(char *fileName, beos_stat *st);
void btMakePath(char *path, char *dir, char *file);
int btPreMount(bt_session_t *session, char *shareName);
int btMount(bt_session_t *session, char *shareName, char *user, char *password, vnode_id *vnid);
int btGetFSInfo(fs_info *fsInfo, char *path);
int btLookup(char *pathBuf, vnode_id dir_vnid, char *fileName, vnode_id *file_vnid);
int btStat(char *pathBuf, vnode_id vnid, beos_stat *st);
int btReadDir(char *pathBuf, vnode_id dir_vnid, long **dir, vnode_id *file_vnid, char *filename, beos_stat *st);
int32 btRead(char *pathBuf, vnode_id vnid, beos_off_t pos, int32 len, char *buffer);
int32 btWrite(bt_session_t *session, vnode_id vnid, beos_off_t pos, int32 len, int32 totalLen, char *buffer);
int btCreate(char *pathBuf, vnode_id dir_vnid, char *name, int omode, int perms, vnode_id *file_vnid);
int btTruncate(char *pathBuf, vnode_id vnid, int64 len);
int btCreateDir(char *pathBuf, vnode_id dir_vnid, char *name, int perms, vnode_id *file_vnid, beos_stat *st);
int btDeleteDir(char *pathBuf, vnode_id dir_vnid, char *name);
int btRename(char *pathBuf, vnode_id old_vnid, char *oldName, vnode_id new_vnid, char *newName);
int btUnlink(char *pathBuf, vnode_id vnid, char *name);
int btReadLink(char *pathBuf, vnode_id vnid, char *buffer, int length);
int btSymLink(char *pathBuf, vnode_id vnid, char *name, char *dest);
int btWStat(char *pathBuf, vnode_id vnid, long mask, int32 mode, int32 uid, int32 gid, int64 size, int32 atime, int32 mtime);
int btCommit(bt_session_t *session, vnode_id vnid);
int btReadAttrib(char *pathBuf, vnode_id vnid, char *name, char *buffer);
int btAuthenticate(char *resource, char *user, char *password);
bt_block *btGetWriteBlock(bt_session_t *session, vnode_id vnid);
void btInsertWriteBlock(bt_session_t *session, bt_block *block);
void btRemoveWriteBlock(bt_session_t *session, bt_block *block);
void netbtPreMount(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtMount(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtFSInfo(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtLookup(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtStat(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtReadDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtRead(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtWrite(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtCreate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtTruncate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtCreateDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtDeleteDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtRename(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtUnlink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtReadLink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtSymLink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtWStat(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtReadAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtWriteAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtReadAttribDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtRemoveAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtStatAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtReadIndexDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtCreateIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtRemoveIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtStatIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtReadQuery(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtCommit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtPrintJobNew(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtPrintJobData(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtPrintJobCommit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtAuthenticate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
void netbtQuit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]);
CMyService *winService;
bt_node *rootNode = NULL;
ubi_btRoot vnidTree;
ubi_btRoot nameTree;
bt_mime_mapping *mimeMap = NULL;
bt_session_t *rootSession = NULL;
bt_fileShare_t fileShares[BT_MAX_FILE_SHARES];
bt_printer sharedPrinters[BT_MAX_PRINTER_SHARES];
char tokBuffer[MAX_NAME_LENGTH + 1], *tokPtr;
bool running = true;
bool preload = false;
int server;
char authServerName[B_FILE_NAME_LENGTH];
unsigned int authServerIP;
bt_managed_data handleData;
bt_managed_data sessionData;
HANDLE hostThread;
char *keywords[] =
{
"share",
"as",
"set",
"read",
"write",
"read-write",
"promiscuous",
"on",
"to",
"authenticate",
"with",
"group",
"printer",
"print",
"is",
"spooled",
"device",
"type",
"preload",
NULL
};
bt_command_t dirCommands[] =
{
{ BT_CMD_PREMOUNT, netbtPreMount, true, 1, { B_STRING_TYPE } },
{ BT_CMD_MOUNT, netbtMount, true, 3, { B_STRING_TYPE, B_STRING_TYPE, B_STRING_TYPE } },
{ BT_CMD_FSINFO, netbtFSInfo, true, 1, { B_INT64_TYPE } },
{ BT_CMD_LOOKUP, netbtLookup, true, 2, { B_INT64_TYPE, B_STRING_TYPE } },
{ BT_CMD_STAT, netbtStat, true, 1, { B_INT64_TYPE } },
{ BT_CMD_READDIR, netbtReadDir, true, 2, { B_INT64_TYPE, B_STRING_TYPE } },
{ BT_CMD_READ, netbtRead, true, 3, { B_INT64_TYPE, B_INT32_TYPE, B_INT32_TYPE } },
{ BT_CMD_WRITE, netbtWrite, true, 5, { B_INT64_TYPE, B_INT64_TYPE, B_INT32_TYPE, B_INT32_TYPE, B_STRING_TYPE } },
{ BT_CMD_CREATE, netbtCreate, true, 4, { B_INT64_TYPE, B_STRING_TYPE, B_INT32_TYPE, B_INT32_TYPE } },
{ BT_CMD_TRUNCATE, netbtTruncate, true, 2, { B_INT64_TYPE, B_INT64_TYPE } },
{ BT_CMD_MKDIR, netbtCreateDir, true, 3, { B_INT64_TYPE, B_STRING_TYPE, B_INT32_TYPE } },
{ BT_CMD_RMDIR, netbtDeleteDir, true, 2, { B_INT64_TYPE, B_STRING_TYPE } },
{ BT_CMD_RENAME, netbtRename, true, 4, { B_INT64_TYPE, B_STRING_TYPE, B_INT64_TYPE, B_STRING_TYPE } },
{ BT_CMD_UNLINK, netbtUnlink, true, 2, { B_INT64_TYPE, B_STRING_TYPE } },
{ BT_CMD_READLINK, netbtReadLink, false, 1, { B_INT64_TYPE } },
{ BT_CMD_SYMLINK, netbtSymLink, false, 3, { B_INT64_TYPE, B_STRING_TYPE, B_STRING_TYPE } },
{ BT_CMD_WSTAT, netbtWStat, true, 8, { B_INT64_TYPE, B_INT32_TYPE, B_INT32_TYPE, B_INT32_TYPE, B_INT32_TYPE, B_INT32_TYPE, B_INT32_TYPE, B_INT32_TYPE } },
{ BT_CMD_READATTRIB, netbtReadAttrib, true, 5, { B_STRING_TYPE, B_STRING_TYPE, B_INT32_TYPE, B_INT32_TYPE, B_INT32_TYPE } },
{ BT_CMD_WRITEATTRIB, netbtWriteAttrib, false, 6, { B_STRING_TYPE, B_STRING_TYPE, B_INT32_TYPE, B_STRING_TYPE, B_INT32_TYPE, B_INT32_TYPE } },
{ BT_CMD_READATTRIBDIR, netbtReadAttribDir, false, 2, { B_STRING_TYPE, B_STRING_TYPE } },
{ BT_CMD_REMOVEATTRIB, netbtRemoveAttrib, false, 2, { B_STRING_TYPE, B_STRING_TYPE } },
{ BT_CMD_STATATTRIB, netbtStatAttrib, true, 2, { B_STRING_TYPE, B_STRING_TYPE } },
{ BT_CMD_READINDEXDIR, netbtReadIndexDir, false, 1, { B_STRING_TYPE } },
{ BT_CMD_CREATEINDEX, netbtCreateIndex, false, 3, { B_STRING_TYPE, B_INT32_TYPE, B_INT32_TYPE } },
{ BT_CMD_REMOVEINDEX, netbtRemoveIndex, false, 1, { B_STRING_TYPE } },
{ BT_CMD_STATINDEX, netbtStatIndex, false, 1, { B_STRING_TYPE } },
{ BT_CMD_READQUERY, netbtReadQuery, false, 2, { B_STRING_TYPE, B_STRING_TYPE } },
{ BT_CMD_COMMIT, netbtCommit, true, 1, { B_INT64_TYPE } },
{ BT_CMD_PRINTJOB_NEW, netbtPrintJobNew, true, 4, { B_STRING_TYPE, B_STRING_TYPE, B_STRING_TYPE, B_STRING_TYPE } },
{ BT_CMD_PRINTJOB_DATA, netbtPrintJobData, true, 4, { B_STRING_TYPE, B_STRING_TYPE, B_STRING_TYPE, B_INT32_TYPE } },
{ BT_CMD_PRINTJOB_COMMIT, netbtPrintJobCommit, true, 2, { B_STRING_TYPE, B_STRING_TYPE } },
{ BT_CMD_AUTHENTICATE, netbtAuthenticate, true, 3, { B_STRING_TYPE, B_STRING_TYPE, B_STRING_TYPE } },
{ BT_CMD_QUIT, netbtQuit, true, 0, { 0 } },
{ 0, NULL, false, 0, { 0 } }
};
void BeServedStartup(CMyService *service)
{
WSADATA wsaData;
DWORD threadId;
ASSERT(service);
winService = service;
initPrinters();
initMimeMap();
initShares();
signal(SIGINT, endService);
signal(SIGTERM, endService);
ubi_trInitTree(&vnidTree, CompareVnidNodes, 0);
ubi_trInitTree(&nameTree, CompareNameNodes, 0);
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
return;
if (initManagedData(&handleData))
if (initManagedData(&sessionData))
hostThread = CreateThread(NULL, 0, btSendHost, NULL, 0, &threadId);
}
bool dateCheck()
{
struct _stat st;
time_t curTime;
time(&curTime);
if (curTime > 1012537700)
return false;
if (_stat("/boot/home/config/servers/beserved_server", &st) == 0)
if (curTime < st.st_ctime || curTime > st.st_ctime + 7776000)
return false;
return true;
}
void restartService()
{
bt_fileShare_t *oldShares;
int i;
initPrinters();
beginWriting(&handleData);
beginWriting(&sessionData);
oldShares = (bt_fileShare_t *) malloc(sizeof(bt_fileShare_t) * BT_MAX_FILE_SHARES);
if (oldShares)
{
for (i = 0; i < BT_MAX_FILE_SHARES; i++)
memcpy(&oldShares[i], &fileShares[i], sizeof(bt_fileShare_t));
initShares();
for (i = 0; i < BT_MAX_FILE_SHARES; i++)
if (oldShares[i].used)
{
bt_session_t *s;
int share = btGetShareIdByPath(oldShares[i].path);
if (share == -1)
{
for (s = rootSession; s; s = s->next)
if (s->share == i)
s->killed = true;
}
else if (share != i)
{
for (s = rootSession; s; s = s->next)
if (s->share == i)
s->share = share;
}
}
free(oldShares);
}
endWriting(&sessionData);
endWriting(&handleData);
}
DWORD WINAPI btSendHost(LPVOID data)
{
bt_request request;
bt_hostinfo info;
struct sockaddr_in serverAddr, clientAddr;
char buffer[4096];
int server, addrLen, bufLen, replyLen;
buffer[0] = 0;
bufLen = sizeof(buffer);
server = socket(AF_INET, SOCK_DGRAM, 0);
if (server == INVALID_SOCKET)
return 0;
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(BT_QUERYHOST_PORT);
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(server, (struct sockaddr *) &serverAddr, sizeof(serverAddr)))
return 0;
while (running)
{
addrLen = sizeof(struct sockaddr_in);
replyLen = 0;
if (recvfrom(server, (char *) &request, sizeof(request), 0, (struct sockaddr *) &clientAddr, &addrLen) <= 0)
continue;
switch (request.command)
{
case BT_REQ_HOST_PROBE:
gethostname(buffer, bufLen);
break;
case BT_REQ_SHARE_PROBE:
replyLen = getSharedResources(buffer, sizeof(buffer), true, true);
break;
case BT_REQ_PRINTER_PROBE:
replyLen = getSharedResources(buffer, sizeof(buffer), false, true);
break;
case BT_REQ_HOST_INFO:
getHostInfo(&info);
memcpy(buffer, &info, sizeof(bt_hostinfo));
replyLen = sizeof(bt_hostinfo);
break;
case BT_REQ_HOST_USERS:
replyLen = getHostUsers(buffer);
break;
}
if (replyLen == 0)
replyLen = strlen(buffer);
sendto(server, buffer, replyLen, 0, (struct sockaddr *) &clientAddr, addrLen);
}
shutdown(server, 2);
closesocket(server);
return 0;
}
int getSharedResources(char *buffer, int bufSize, bool shares, bool printers)
{
bt_resource resource;
int i, bufPos = 0;
if (bufSize < 2 * sizeof(bt_resource))
return 0;
if (shares)
for (i = 0; i < BT_MAX_FILE_SHARES; i++)
if (fileShares[i].used)
{
if (bufPos + sizeof(bt_resource) >= bufSize)
break;
resource.type = BT_SHARED_FOLDER;
resource.subType = 0;
strcpy(resource.name, fileShares[i].name);
memcpy(buffer + bufPos, &resource, sizeof(bt_resource));
bufPos += sizeof(bt_resource);
}
if (printers)
for (i = 0; i < BT_MAX_PRINTER_SHARES; i++)
if (sharedPrinters[i].used)
{
if (bufPos + sizeof(bt_resource) >= bufSize)
break;
resource.type = BT_SHARED_PRINTER;
resource.subType = BT_PRINTER_PCL3;
strcpy(resource.name, sharedPrinters[i].printerName);
memcpy(buffer + bufPos, &resource, sizeof(bt_resource));
bufPos += sizeof(bt_resource);
}
resource.type = BT_SHARED_NULL;
resource.subType = 0;
resource.name[0] = 0;
memcpy(buffer + bufPos, &resource, sizeof(bt_resource));
bufPos += sizeof(bt_resource);
return bufPos;
}
void getHostInfo(bt_hostinfo *info)
{
SYSTEM_INFO systemInfo;
OSVERSIONINFOEX osInfo;
bt_session_t *s;
osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if (!GetVersionEx((OSVERSIONINFO *) &osInfo))
{
osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx((OSVERSIONINFO *) &osInfo);
}
GetSystemInfo(&systemInfo);
switch (osInfo.dwPlatformId)
{
case VER_PLATFORM_WIN32_WINDOWS:
if (osInfo.dwMinorVersion == 0)
{
strcpy(info->system, "Windows 95");
if (osInfo.szCSDVersion[1] == 'C' || osInfo.szCSDVersion[1] == 'B')
strcat(info->system, " OSR2");
}
else if (osInfo.dwMinorVersion == 10)
{
strcpy(info->system, "Windows 98");
if (osInfo.szCSDVersion[1] == 'A')
strcat(info->system, " SE");
}
else if (osInfo.dwMinorVersion == 90)
strcpy(info->system, "Windows Me");
break;
case VER_PLATFORM_WIN32_NT:
if (osInfo.dwMajorVersion <= 4)
sprintf(info->system, "Windows NT %d.%d %s (Build %d)",
osInfo.dwMajorVersion, osInfo.dwMinorVersion, osInfo.szCSDVersion,
osInfo.dwBuildNumber);
else if (osInfo.dwMajorVersion == 5)
if (osInfo.dwMinorVersion == 0)
sprintf(info->system, "Windows 2000 %s (Build %d)",
osInfo.szCSDVersion, osInfo.dwBuildNumber & 0xffff);
else
sprintf(info->system, "Windows XP %s (Build %d)",
osInfo.szCSDVersion, osInfo.dwBuildNumber & 0xffff);
break;
}
strcpy(info->beServed, "BeServed 1.2.6");
info->cpus = systemInfo.dwNumberOfProcessors;
info->maxConnections = BT_MAX_THREADS;
switch (systemInfo.wProcessorArchitecture)
{
case PROCESSOR_ARCHITECTURE_MIPS:
strcpy(info->platform, "MIPS");
break;
case PROCESSOR_ARCHITECTURE_ALPHA:
strcpy(info->platform, "DEC Alpha");
break;
case PROCESSOR_ARCHITECTURE_PPC:
strcpy(info->platform, "PowerPC");
break;
case PROCESSOR_ARCHITECTURE_INTEL:
strcpy(info->platform, "Intel x86");
break;
default:
strcpy(info->platform, "Unknown");
}
beginReading(&sessionData);
info->connections = 0;
for (s = rootSession; s; s = s->next)
if (s->socket != INVALID_SOCKET)
info->connections++;
info->connections = B_HOST_TO_LENDIAN_INT32(info->connections);
endReading(&sessionData);
}
int getHostUsers(char *buffer)
{
bt_session_t *s;
char addr[20];
int len, bufSize;
buffer[0] = 0;
bufSize = 0;
beginReading(&sessionData);
for (s = rootSession; s; s = s->next)
if (s->socket != INVALID_SOCKET)
{
uint8 *client_s_addr = (uint8 *) s->client_s_addr;
sprintf(addr, "%d.%d.%d.%d", client_s_addr[0], client_s_addr[1], client_s_addr[2], client_s_addr[3]);
len = strlen(buffer);
strcpy(&buffer[len > 0 ? len + 1 : 0], addr);
bufSize += len + 1;
}
endReading(&sessionData);
buffer[bufSize++] = 0;
return bufSize;
}
void initMimeMap()
{
FILE *fp;
bt_mime_mapping *map;
char mimeLine[256];
int i, mimeLen;
fp = fopen("BeServed-MimeMap", "r");
if (fp)
{
while (fgets(mimeLine, sizeof(mimeLine) - 1, fp))
{
mimeLine[strlen(mimeLine) - 1] = 0;
map = (bt_mime_mapping *) malloc(sizeof(bt_mime_mapping));
if (!map)
continue;
map->next = mimeMap;
mimeMap = map;
for (i = 0; mimeLine[i] != ' '; i++)
map->extension[i] = mimeLine[i];
map->extension[i] = 0;
while (mimeLine[i] == ' ')
i++;
mimeLen = strlen(&mimeLine[i]);
map->mimeType = (char *) malloc(mimeLen + 1);
if (map->mimeType)
strncpy(map->mimeType, &mimeLine[i], mimeLen + 1);
}
fclose(fp);
}
}
void closeMimeMap()
{
bt_mime_mapping *map = mimeMap;
while (map)
{
map = mimeMap->next;
free(mimeMap->mimeType);
free(mimeMap);
mimeMap = map;
}
}
void initShares()
{
FILE *fp;
char buffer[512];
int i, length;
for (i = 0; i < BT_MAX_FILE_SHARES; i++)
{
fileShares[i].name[0] = 0;
fileShares[i].path[0] = 0;
fileShares[i].used = false;
fileShares[i].readOnly = true;
fileShares[i].security = BT_AUTH_NONE;
fileShares[i].rights = NULL;
fileShares[i].next = NULL;
}
fp = fopen("BeServed-Settings", "r");
if (fp)
{
while (fgets(buffer, sizeof(buffer) - 1, fp))
{
length = strlen(buffer);
if (length <= 1 || buffer[0] == '#')
continue;
if (buffer[length - 1] == '\n')
buffer[--length] = 0;
if (strncmp(buffer, "share ", 6) == 0)
getFileShare(buffer);
else if (strncmp(buffer, "set ", 4) == 0)
getShareProperty(buffer);
else if (strncmp(buffer, "grant ", 6) == 0)
getGrant(buffer);
else if (strncmp(buffer, "authenticate ", 13) == 0)
getAuthenticate(buffer);
else if (strncmp(buffer, "printer ", 8) == 0)
getPrinter(buffer);
else if (strcmp(buffer, "preload") == 0)
preload = true;
}
fclose(fp);
}
}
void initPrinters()
{
int i;
for (i = 0; i < BT_MAX_PRINTER_SHARES; i++)
{
sharedPrinters[i].printerName[0] = 0;
sharedPrinters[i].deviceName[0] = 0;
sharedPrinters[i].spoolDir[0] = 0;
sharedPrinters[i].rights = NULL;
sharedPrinters[i].security = BT_AUTH_NONE;
sharedPrinters[i].used = false;
sharedPrinters[i].killed = false;
}
}
void loadShares()
{
int i;
if (preload)
for (i = 0; i < BT_MAX_FILE_SHARES; i++)
if (fileShares[i].used)
loadFolder(fileShares[i].path);
}
void getFileShare(const char *buffer)
{
struct _stat st;
char path[B_PATH_NAME_LENGTH], share[MAX_NAME_LENGTH + 1], *folder;
int i, tok;
tokPtr = (char *) buffer + (6 * sizeof(char));
tok = getToken();
if (tok != BT_TOKEN_STRING)
return;
strcpy(path, tokBuffer);
tok = getToken();
if (tok != BT_TOKEN_AS)
return;
tok = getToken();
if (tok != BT_TOKEN_STRING)
return;
strcpy(share, tokBuffer);
folder = btGetSharePath(share);
if (folder)
{
winService->LogEvent(EVENTLOG_WARNING_TYPE, EVMSG_DUPLICATE_SHARE, share);
return;
}
if (_stat(path, &st) != 0)
{
winService->LogEvent(EVENTLOG_WARNING_TYPE, EVMSG_INVALID_SHARE_PATH, path);
return;
}
for (i = 0; i < BT_MAX_FILE_SHARES; i++)
if (!fileShares[i].used)
{
strcpy(fileShares[i].name, share);
strcpy(fileShares[i].path, path);
fileShares[i].used = true;
return;
}
winService->LogEvent(EVENTLOG_WARNING_TYPE, EVMSG_TOO_MANY_SHARES, share);
}
void getShareProperty(const char *buffer)
{
char share[B_FILE_NAME_LENGTH + 1];
int tok, shareId;
tokPtr = (char *) buffer + (4 * sizeof(char));
tok = getToken();
if (tok != BT_TOKEN_STRING)
return;
strcpy(share, tokBuffer);
shareId = btGetShareId(share);
if (shareId < 0)
return;
tok = getToken();
if (tok == BT_TOKEN_READWRITE)
fileShares[shareId].readOnly = false;
}
void getGrant(const char *buffer)
{
char share[MAX_NAME_LENGTH + 1];
int tok, rights;
bool isGroup = false;
tokPtr = (char *) buffer + (6 * sizeof(char));
rights = 0;
do
{
tok = getToken();
if (tok == BT_TOKEN_READ)
{
rights |= BT_RIGHTS_READ;
tok = getToken();
}
else if (tok == BT_TOKEN_WRITE)
{
rights |= BT_RIGHTS_WRITE;
tok = getToken();
}
else if (tok == BT_TOKEN_PRINT)
{
rights |= BT_RIGHTS_PRINT;
tok = getToken();
}
} while (tok == BT_TOKEN_COMMA);
if (tok != BT_TOKEN_ON)
return;
tok = getToken();
if (tok != BT_TOKEN_STRING)
return;
strcpy(share, tokBuffer);
tok = getToken();
if (tok != BT_TOKEN_TO)
return;
tok = getToken();
if (tok == BT_TOKEN_GROUP)
{
isGroup = true;
tok = getToken();
}
if (tok != BT_TOKEN_STRING)
return;
addUserRights(share, tokBuffer, rights, isGroup);
}
void getAuthenticate(const char *buffer)
{
int i, tok;
tokPtr = (char *) buffer + (13 * sizeof(char));
tok = getToken();
if (tok != BT_TOKEN_WITH)
return;
tok = getToken();
if (tok != BT_TOKEN_STRING)
return;
getAuthServerAddress(tokBuffer);
for (i = 0; i < BT_MAX_FILE_SHARES; i++)
fileShares[i].security = BT_AUTH_BESURE;
for (i = 0; i < BT_MAX_PRINTER_SHARES; i++)
sharedPrinters[i].security = BT_AUTH_BESURE;
}
bool getAuthServerAddress(const char *name)
{
struct hostent *ent = gethostbyname(name);
if (ent == NULL)
{
unsigned long addr = inet_addr(tokBuffer);
authServerIP = ntohl(addr);
}
else
authServerIP = ntohl(*((unsigned int *) ent->h_addr));
strcpy(authServerName, name);
return true;
}
void addUserRights(char *share, char *user, int rights, bool isGroup)
{
bt_printer *printer;
bt_user_rights *ur;
bool isPrinter = false;
int shareId;
if (rights & BT_RIGHTS_PRINT)
{
if (rights & BT_RIGHTS_READ || rights & BT_RIGHTS_WRITE)
return;
printer = btFindPrinter(share);
if (!printer)
return;
isPrinter = true;
}
else
{
shareId = btGetShareId(share);
if (shareId < 0)
return;
}
ur = (bt_user_rights *) malloc(sizeof(bt_user_rights));
if (ur)
{
ur->user = (char *) malloc(strlen(user) + 1);
if (ur->user)
{
strcpy(ur->user, user);
ur->rights = rights;
ur->isGroup = isGroup;
if (isPrinter)
{
ur->next = printer->rights;
printer->rights = ur;
}
else
{
ur->next = fileShares[shareId].rights;
fileShares[shareId].rights = ur;
}
}
else
free(ur);
}
}
void getPrinter(const char *buffer)
{
bt_printer printer;
DWORD threadId;
int i, tok;
tokPtr = (char *) buffer + (8 * sizeof(char));
tok = getToken();
if (tok != BT_TOKEN_STRING)
return;
strcpy(printer.printerName, tokBuffer);
tok = getToken();
if (tok != BT_TOKEN_IS)
return;
tok = getToken();
if (tok != BT_TOKEN_TYPE)
return;
tok = getToken();
if (tok != BT_TOKEN_STRING)
return;
strcpy(printer.deviceType, tokBuffer);
tok = getToken();
if (tok != BT_TOKEN_DEVICE)
return;
tok = getToken();
if (tok != BT_TOKEN_STRING)
return;
strcpy(printer.deviceName, tokBuffer);
tok = getToken();
if (tok != BT_TOKEN_SPOOLED)
return;
tok = getToken();
if (tok != BT_TOKEN_TO)
return;
tok = getToken();
if (tok != BT_TOKEN_STRING)
return;
strcpy(printer.spoolDir, tokBuffer);
for (i = 0; i < BT_MAX_PRINTER_SHARES; i++)
if (!sharedPrinters[i].used)
{
sharedPrinters[i].used = true;
strcpy(sharedPrinters[i].printerName, printer.printerName);
strcpy(sharedPrinters[i].deviceType, printer.deviceType);
strcpy(sharedPrinters[i].deviceName, printer.deviceName);
strcpy(sharedPrinters[i].spoolDir, printer.spoolDir);
sharedPrinters[i].handlerID = CreateThread(NULL, 0, printerThread, (void *) &sharedPrinters[i], 0, &threadId);
break;
}
}
int getToken()
{
bool quoted = false;
tokBuffer[0] = 0;
while (*tokPtr && iswhite(*tokPtr))
tokPtr++;
if (*tokPtr == ',')
{
*tokPtr++;
return BT_TOKEN_COMMA;
}
else if (*tokPtr == '\"')
{
quoted = true;
tokPtr++;
}
if (isalnum(*tokPtr) || *tokPtr == '\\')
{
int i = 0;
while (isalnum(*tokPtr) || isValid(*tokPtr) || (quoted && *tokPtr == ' '))
if (i < MAX_NAME_LENGTH)
tokBuffer[i++] = *tokPtr++;
else
tokPtr++;
tokBuffer[i] = 0;
if (!quoted)
for (i = 0; keywords[i]; i++)
if (stricmp(tokBuffer, keywords[i]) == 0)
return ++i;
if (quoted)
if (*tokPtr != '\"')
return BT_TOKEN_ERROR;
else
tokPtr++;
return BT_TOKEN_STRING;
}
return BT_TOKEN_ERROR;
}
void startService()
{
struct sockaddr_in serverAddr, clientAddr;
int client, addrLen;
char flags;
addrLen = sizeof(struct sockaddr_in);
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_port = htons(BT_TCPIP_PORT);
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server == INVALID_SOCKET)
return;
flags = 1;
setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags));
if (bind(server, (struct sockaddr *) &serverAddr, sizeof(serverAddr)))
return;
if (listen(server, 5))
return;
while (running)
{
client = accept(server, (struct sockaddr *) &clientAddr, &addrLen);
if (client != INVALID_SOCKET)
launchThread(client, &clientAddr);
}
shutdown(server, 2);
closesocket(server);
server = INVALID_SOCKET;
}
void endService(int sig)
{
WSACleanup();
TerminateThread(hostThread, 0);
closeManagedData(&sessionData);
closeManagedData(&handleData);
closePrinters();
closeMimeMap();
freeFileShares();
ubi_trKillTree(&vnidTree, KillNode);
ubi_trKillTree(&nameTree, KillNode);
signal(SIGINT, SIG_DFL);
signal(SIGTERM, SIG_DFL);
}
void closePrinters()
{
int i;
for (i = 0; i < BT_MAX_PRINTER_SHARES; i++)
if (sharedPrinters[i].used)
{
sharedPrinters[i].killed = true;
waitForThread(sharedPrinters[i].handlerID);
}
}
void waitForThread(HANDLE threadId)
{
DWORD exitCode;
while (true)
{
if (!GetExitCodeThread(threadId, &exitCode))
break;
if (exitCode != STILL_ACTIVE)
break;
Sleep(100);
}
}
void freeFileShares()
{
bt_user_rights *ur, *nextUr;
int i;
for (i = 0; i < BT_MAX_FILE_SHARES; i++)
for (ur = fileShares[i].rights; ur; )
{
nextUr = ur->next;
if (ur->user)
free(ur->user);
free(ur);
ur = nextUr;
}
}
void launchThread(int client, struct sockaddr_in *addr)
{
bt_session_t *s, *cur, *last = NULL;
DWORD threadId;
int count = 0;
beginWriting(&sessionData);
s = rootSession;
while (s)
{
if (s->socket == INVALID_SOCKET)
{
if (last)
last->next = s->next;
else
rootSession = s->next;
cur = s->next;
free(s);
s = cur;
continue;
}
last = s;
s = s->next;
count++;
}
if (count < BT_MAX_THREADS)
{
bt_session_t *session = (bt_session_t *) malloc(sizeof(bt_session_t));
if (session)
{
session->socket = client;
session->client_s_addr = addr->sin_addr.s_addr;
session->rootBlock = NULL;
session->killed = false;
session->rights = 0;
session->handlerID = CreateThread(NULL, 0, requestThread, (void *) session, 0, &threadId);
session->next = rootSession;
rootSession = session;
endWriting(&sessionData);
return;
}
}
endWriting(&sessionData);
sendErrorToClient(client, 0, EBUSY);
shutdown(client, 2);
closesocket(client);
}
DWORD WINAPI requestThread(LPVOID data)
{
bt_session_t *session = (bt_session_t *) data;
if (!session)
return 0;
session->blockSem = CreateSemaphore(NULL, 1, 1, NULL);
if (session->blockSem)
{
session->rootBlock = NULL;
while (!session->killed && receiveRequest(session));
CloseHandle(session->blockSem);
}
shutdown(session->socket, 2);
closesocket(session->socket);
session->socket = INVALID_SOCKET;
return 0;
}
int receiveRequest(bt_session_t *session)
{
bt_inPacket packet;
char signature[20], *buffer;
unsigned char command;
int client, sigLen;
int32 length;
client = session->socket;
sigLen = strlen(BT_RPC_SIGNATURE);
if (btRecvMsg(client, signature, sigLen, 0) == -1)
return 0;
signature[sigLen] = 0;
if (strcmp(signature, BT_RPC_SIGNATURE))
return 0;
if (btRecvMsg(client, (char *) &length, sizeof(int32), 0) == -1)
return 0;
length = B_LENDIAN_TO_HOST_INT32(length);
if (length == 0 || length > BT_RPC_MAX_PACKET_SIZE)
return 0;
buffer = (char *) malloc(length + 1);
if (!buffer)
return 0;
if (btRecvMsg(client, buffer, length, 0) == -1)
{
free(buffer);
return 0;
}
buffer[length] = 0;
packet.buffer = buffer;
packet.length = length;
packet.offset = 0;
command = btRPCGetChar(&packet);
getArguments(session, &packet, command);
free(buffer);
return (command != BT_CMD_QUIT && command != BT_CMD_PREMOUNT);
}
void getArguments(bt_session_t *session, bt_inPacket *packet, unsigned char command)
{
bt_arg_t args[MAX_COMMAND_ARGS];
int i, client;
bool error;
unsigned char argc, terminator;
int32 xid;
error = false;
client = session->socket;
argc = btRPCGetChar(packet);
if (argc > MAX_COMMAND_ARGS)
return;
for (i = 0; i < argc && !error; i++)
{
args[i].type = btRPCGetInt32(packet);
args[i].data = btRPCGetNewString(packet);
if (args[i].data == NULL)
error = true;
}
if (!error)
{
xid = btRPCGetInt32(packet);
terminator = btRPCGetChar(packet);
if (terminator == BT_CMD_TERMINATOR)
handleRequest(session, xid, command, argc, args);
}
while (--i >= 0)
free(args[i].data);
}
void handleRequest(bt_session_t *session, unsigned int xid, unsigned char command, int argc, bt_arg_t argv[])
{
bool validated = true;
int i, j;
for (i = 0; dirCommands[i].handler; i++)
if (command == dirCommands[i].command)
{
if (!dirCommands[i].supported)
{
sendErrorToClient(session->socket, xid, ENOTSUP);
return;
}
if (argc == dirCommands[i].args)
{
for (j = 0; j < argc; j++)
if (dirCommands[i].argTypes[j] != argv[j].type)
{
validated = false;
break;
}
if (validated)
{
(*dirCommands[i].handler)(session, xid, argc, argv);
return;
}
}
}
sendErrorToClient(session->socket, xid, EINVAL);
}
void sendErrorToClient(int client, unsigned int xid, int error)
{
bt_outPacket packet;
btRPCCreateAck(&packet, xid, error);
btRPCSendAck(client, &packet);
}
int btRecvMsg(int sock, void *data, int dataLen, int flags)
{
int bytesRead = 0;
do
{
int bytes = btRecv(sock, (char *) data + bytesRead, dataLen - bytesRead, flags);
if (bytes == -1)
return -1;
bytesRead += bytes;
} while (bytesRead < dataLen);
return bytesRead;
}
int btRecv(int sock, void *data, int dataLen, int flags)
{
int bytes;
for (;;)
{
bytes = recv(sock, (char *) data, dataLen, flags);
if (bytes == 0)
return -1;
else if (bytes == -1)
if (errno == EINTR)
continue;
else
return -1;
else
break;
}
return bytes;
}
int btSendMsg(int sock, void *data, int dataLen, int flags)
{
int bytesSent = 0;
do
{
int bytes = btSend(sock, (char *) data + bytesSent, dataLen - bytesSent, flags);
if (bytes == -1)
return -1;
bytesSent += bytes;
} while (bytesSent < dataLen);
return bytesSent;
}
int btSend(int sock, void *data, int dataLen, int flags)
{
int bytes;
for (;;)
{
bytes = send(sock, (char *) data, dataLen, flags);
if (bytes == -1)
if (errno == EINTR)
continue;
else
return -1;
else
break;
}
return bytes;
}
uint32 btSwapInt32(uint32 num)
{
uint8 byte;
union
{
uint32 value;
uint8 bytes[4];
} convert;
convert.value = num;
byte = convert.bytes[0];
convert.bytes[0] = convert.bytes[3];
convert.bytes[3] = byte;
byte = convert.bytes[1];
convert.bytes[1] = convert.bytes[2];
convert.bytes[2] = byte;
return convert.value;
}
uint64 btSwapInt64(uint64 num)
{
uint8 byte;
union
{
uint64 value;
uint8 bytes[8];
} convert;
convert.value = num;
byte = convert.bytes[0];
convert.bytes[0] = convert.bytes[7];
convert.bytes[7] = byte;
byte = convert.bytes[1];
convert.bytes[1] = convert.bytes[6];
convert.bytes[6] = byte;
byte = convert.bytes[2];
convert.bytes[2] = convert.bytes[5];
convert.bytes[5] = byte;
byte = convert.bytes[3];
convert.bytes[3] = convert.bytes[4];
convert.bytes[4] = byte;
return convert.value;
}
void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error)
{
packet->size = BT_RPC_MIN_PACKET_SIZE;
packet->buffer = (char *) malloc(packet->size);
packet->length = 0;
if (!packet->buffer)
return;
strcpy(packet->buffer, BT_RPC_SIGNATURE);
packet->length += strlen(BT_RPC_SIGNATURE);
btRPCPutInt32(packet, xid);
btRPCPutInt32(packet, 0);
btRPCPutInt32(packet, error);
}
void btRPCSendAck(int client, bt_outPacket *packet)
{
if (packet)
if (packet->buffer)
{
*(int32 *)(&packet->buffer[9]) = B_HOST_TO_LENDIAN_INT32(packet->length - 13);
btSendMsg(client, packet->buffer, packet->length, 0);
free(packet->buffer);
}
}
unsigned char btRPCGetChar(bt_inPacket *packet)
{
unsigned char value;
if (packet->offset < packet->length)
value = (unsigned char) packet->buffer[packet->offset];
else
value = 0;
packet->offset += sizeof(value);
return value;
}
unsigned int btRPCGetInt32(bt_inPacket *packet)
{
int32 value;
if (packet->offset < packet->length)
value = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset]));
else
value = 0;
packet->offset += sizeof(value);
return value;
}
int64 btRPCGetInt64(bt_inPacket *packet)
{
int64 value;
if (packet->offset < packet->length)
value = B_LENDIAN_TO_HOST_INT64(*((int64 *) &packet->buffer[packet->offset]));
else
value = 0;
packet->offset += sizeof(value);
return value;
}
char *btRPCGetNewString(bt_inPacket *packet)
{
char *str;
unsigned int bytes;
if (packet->offset >= packet->length)
return NULL;
bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset]));
packet->offset += sizeof(bytes);
if (bytes < 0 || bytes > BT_MAX_IO_BUFFER)
return NULL;
str = (char *) malloc(bytes + 1);
if (!str)
return NULL;
if (bytes > 0)
memcpy(str, &packet->buffer[packet->offset], bytes);
str[bytes] = 0;
packet->offset += bytes;
return str;
}
int btRPCGetString(bt_inPacket *packet, char *buffer, int length)
{
unsigned int bytes;
if (packet->offset >= packet->length)
return ERANGE;
bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset]));
packet->offset += sizeof(bytes);
if (bytes < 0 || bytes > BT_MAX_IO_BUFFER)
return ERANGE;
if (length < bytes)
return ERANGE;
if (bytes > 0)
memcpy(buffer, &packet->buffer[packet->offset], bytes);
packet->offset += bytes;
return bytes;
}
void btRPCGrowPacket(bt_outPacket *packet, int bytes)
{
if (packet->length + bytes > packet->size)
{
int growth = ((bytes / BT_RPC_MIN_PACKET_SIZE) + 1) * BT_RPC_MIN_PACKET_SIZE;
packet->buffer = (char *) realloc(packet->buffer, packet->size + growth);
packet->size += growth;
}
}
void btRPCPutChar(bt_outPacket *packet, char value)
{
btRPCGrowPacket(packet, sizeof(value));
packet->buffer[packet->length] = value;
packet->length += sizeof(value);
}
void btRPCPutInt32(bt_outPacket *packet, int32 value)
{
btRPCGrowPacket(packet, sizeof(value));
*(int32 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT32(value);
packet->length += sizeof(value);
}
void btRPCPutInt64(bt_outPacket *packet, int64 value)
{
btRPCGrowPacket(packet, sizeof(value));
*(int64 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT64(value);
packet->length += sizeof(value);
}
void btRPCPutString(bt_outPacket *packet, char *buffer, int length)
{
if (packet && buffer)
{
btRPCGrowPacket(packet, sizeof(length) + length);
btRPCPutInt32(packet, length);
memcpy(&packet->buffer[packet->length], buffer, length);
packet->length += length;
}
}
void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length)
{
if (packet && buffer)
{
btRPCGrowPacket(packet, length);
memcpy(&packet->buffer[packet->length], buffer, length);
packet->length += length;
}
}
void btRPCGetStat(bt_inPacket *packet, beos_stat *st)
{
st->st_dev = 0;
st->st_nlink = btRPCGetInt32(packet);
st->st_uid = btRPCGetInt32(packet);
st->st_gid = btRPCGetInt32(packet);
st->st_size = (int32) btRPCGetInt64(packet);
st->st_blksize = btRPCGetInt32(packet);
st->st_rdev = btRPCGetInt32(packet);
st->st_ino = (int32) btRPCGetInt64(packet);
st->st_mode = btRPCGetInt32(packet);
st->st_atime = btRPCGetInt32(packet);
st->st_mtime = btRPCGetInt32(packet);
st->st_ctime = btRPCGetInt32(packet);
}
void btRPCPutStat(bt_outPacket *packet, beos_stat *st)
{
if (packet && st)
{
int64 size = (int64) st->st_size;
int64 inode = (int64) st->st_ino;
btRPCPutInt32(packet, (int) st->st_nlink);
btRPCPutInt32(packet, (int) st->st_uid);
btRPCPutInt32(packet, (int) st->st_gid);
btRPCPutInt64(packet, size);
btRPCPutInt32(packet, (int) 1024);
btRPCPutInt32(packet, (int) st->st_rdev);
btRPCPutInt64(packet, inode);
btRPCPutInt32(packet, (int) st->st_mode);
btRPCPutInt32(packet, (int) st->st_atime);
btRPCPutInt32(packet, (int) st->st_mtime);
btRPCPutInt32(packet, (int) st->st_ctime);
}
}
bt_node *btGetNodeFromVnid(vnode_id vnid)
{
return (bt_node *) ubi_trFind(&vnidTree, &vnid);
}
void btAddHandle(vnode_id dir_vnid, vnode_id file_vnid, char *name)
{
bt_node *vnidNode, *nameNode, *dirNode;
if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
return;
beginWriting(&handleData);
if (dir_vnid)
dirNode = btGetNodeFromVnid(dir_vnid);
else
dirNode = NULL;
if (btGetNodeFromVnid(file_vnid))
{
endWriting(&handleData);
return;
}
vnidNode = (bt_node *) malloc(sizeof(bt_node));
if (vnidNode == NULL)
{
endWriting(&handleData);
return;
}
nameNode = (bt_node *) malloc(sizeof(bt_node));
if (nameNode == NULL)
{
free(vnidNode);
endWriting(&handleData);
return;
}
vnidNode->name = (char *) malloc(strlen(name) + 1);
if (vnidNode->name == NULL)
{
free(nameNode);
free(vnidNode);
endWriting(&handleData);
return;
}
strcpy(vnidNode->name, name);
nameNode->name = strdup(vnidNode->name);
if (nameNode->name == NULL)
{
free(vnidNode->name);
free(nameNode);
free(vnidNode);
endWriting(&handleData);
return;
}
vnidNode->invalid = nameNode->invalid = false;
vnidNode->vnid = nameNode->vnid = file_vnid;
vnidNode->parent = nameNode->parent = dirNode;
ubi_trInsert(&vnidTree, vnidNode, &vnidNode->vnid, NULL);
ubi_trInsert(&nameTree, nameNode, nameNode, NULL);
endWriting(&handleData);
}
void btRemoveHandle(vnode_id vnid)
{
bt_node *deadVnidNode, *deadNameNode;
beginWriting(&handleData);
deadVnidNode = (bt_node *) ubi_trFind(&vnidTree, &vnid);
if (deadVnidNode)
{
ubi_trRemove(&vnidTree, deadVnidNode);
deadNameNode = (bt_node *) ubi_trFind(&nameTree, deadVnidNode);
if (deadNameNode)
ubi_trRemove(&nameTree, deadNameNode);
}
endWriting(&handleData);
}
void btPurgeNodes(vnode_id vnid)
{
bt_node *curNode;
ubi_trNodePtr cur, next;
ubi_trRootPtr tree;
ubi_trRootPtr trees[] = { &vnidTree, &nameTree, NULL };
int i;
beginWriting(&handleData);
for (i = 0, tree = trees[i]; trees[i]; i++)
{
cur = ubi_trFirst(tree->root);
while (cur)
{
next = ubi_trNext(cur);
curNode = (bt_node *) cur;
if (curNode->vnid == vnid || btIsAncestorNode(vnid, curNode))
curNode->invalid = true;
cur = next;
}
cur = ubi_trFirst(tree->root);
while (cur)
{
next = ubi_trNext(cur);
curNode = (bt_node *) cur;
if (curNode->invalid)
{
ubi_trRemove(&vnidTree, curNode);
free(curNode);
}
cur = next;
}
}
endWriting(&handleData);
}
bool btIsAncestorNode(vnode_id vnid, bt_node *node)
{
bt_node *curNode = node->parent;
while (curNode)
{
if (curNode->vnid == vnid)
return true;
curNode = curNode->parent;
}
return false;
}
char *btGetLocalFileName(char *path, vnode_id vnid)
{
bt_node *node, *nodeStack[100];
int stackSize;
path[0] = 0;
stackSize = 1;
beginReading(&handleData);
node = btGetNodeFromVnid(vnid);
if (node == NULL)
{
endReading(&handleData);
return NULL;
}
nodeStack[0] = node;
while ((node = node->parent) != NULL)
nodeStack[stackSize++] = node;
while (--stackSize >= 0)
{
strcat(path, nodeStack[stackSize]->name);
if (stackSize)
{
int length = strlen(path);
if (length > 0 && path[length - 1] != '\\')
strcat(path, "\\");
}
}
endReading(&handleData);
return path;
}
bt_node *btFindNode(bt_node *parent, char *fileName)
{
bt_node search, *node;
search.parent = parent;
search.name = strdup(fileName);
if (search.name == NULL)
return NULL;
beginReading(&handleData);
node = (bt_node *) ubi_trFind(&nameTree, &search);
endReading(&handleData);
free(search.name);
return node;
}
char *btGetSharePath(char *shareName)
{
int i;
for (i = 0; i < BT_MAX_FILE_SHARES; i++)
if (fileShares[i].used)
if (stricmp(fileShares[i].name, shareName) == 0)
return fileShares[i].path;
return NULL;
}
int btGetShareId(char *shareName)
{
int i;
for (i = 0; i < BT_MAX_FILE_SHARES; i++)
if (fileShares[i].used)
if (stricmp(fileShares[i].name, shareName) == 0)
return i;
return -1;
}
int btGetShareIdByPath(char *path)
{
int i;
for (i = 0; i < BT_MAX_FILE_SHARES; i++)
if (fileShares[i].used)
if (stricmp(fileShares[i].path, path) == 0)
return i;
return -1;
}
bt_printer *btFindPrinter(char *printerName)
{
int i;
for (i = 0; i < BT_MAX_PRINTER_SHARES; i++)
if (sharedPrinters[i].used)
if (stricmp(printerName, sharedPrinters[i].printerName) == 0)
return &sharedPrinters[i];
return NULL;
}
void btGetRootPath(vnode_id vnid, char *path)
{
bt_node *curNode;
beginReading(&handleData);
curNode = btGetNodeFromVnid(vnid);
while (curNode && curNode->parent)
curNode = curNode->parent;
if (curNode)
strcpy(path, curNode->name);
else
path[0] = 0;
endReading(&handleData);
}
uint32 btGetWinInode(const char *path)
{
const int MAX_FOLDER_NESTING = 100;
char *folders[MAX_FOLDER_NESTING + 1];
char newPath[B_PATH_NAME_LENGTH + 1];
int i, level, len, charSum;
char *p, *s = strdup(path);
level = 0;
folders[level++] = s;
for (p = s; *p; p++)
if (*p == '\\')
{
folders[level++] = p + 1;
*p = 0;
}
folders[level] = 0;
for (i = 0; i < level; i++)
if (*folders[i])
if (strcmp(folders[i], ".") == 0)
folders[i] = NULL;
else if (strcmp(folders[i], "..") == 0)
{
int j = i;
folders[i] = 0;
while (j > 0 && folders[j] == NULL)
j--;
if (j >= 0)
folders[j] = 0;
}
newPath[0] = 0;
for (i = 0; i < level; i++)
if (folders[i])
{
strcat(newPath, folders[i]);
if (i < level - 1)
strcat(newPath, "\\");
}
len = strlen(newPath);
if (newPath[len - 1] == '\\')
newPath[--len] = 0;
free(s);
p = newPath;
for (charSum = len = 0; *p; p++, len++)
charSum += (*p * len);
return ((len << 24) + charSum);
}
int btGetBeosStat(char *fileName, beos_stat *st)
{
struct _stat _st;
if (_stat(fileName, &_st) != 0)
return BEOS_ENOENT;
st->st_atime = _st.st_atime;
st->st_blksize = 1024;
st->st_ctime = _st.st_ctime;
st->st_dev = 0;
st->st_gid = 0;
st->st_uid = 0;
st->st_ino = btGetWinInode(fileName);
st->st_mode = _st.st_mode;
st->st_mtime = _st.st_mtime;
st->st_nlink = 0;
st->st_rdev = 0;
st->st_size = _st.st_size;
return B_OK;
}
void btMakePath(char *path, char *dir, char *file)
{
int length;
strcpy(path, dir);
length = strlen(path);
if (length > 0)
if (path[length - 1] != '\\')
strcat(path, "\\");
strcat(path, file);
}
int btPreMount(bt_session_t *session, char *shareName)
{
int shareId = btGetShareId(shareName);
if (shareId < 0)
{
bt_printer *printer = btFindPrinter(shareName);
if (!printer)
return BEOS_ENOENT;
return printer->security;
}
return fileShares[shareId].security;
}
int btMount(bt_session_t *session, char *shareName, char *user, char *password, vnode_id *vnid)
{
bt_user_rights *ur;
struct stat st;
char *path, *groups[MAX_GROUPS_PER_USER];
int i, shareId;
bool authenticated = false;
for (i = 0; i < MAX_GROUPS_PER_USER; i++)
groups[i] = NULL;
shareId = btGetShareId(shareName);
if (shareId < 0)
return BEOS_ENOENT;
if (fileShares[shareId].security != BT_AUTH_NONE)
{
authenticated = authenticateUser(user, password);
if (!authenticated)
return BEOS_EACCES;
session->rights = 0;
for (ur = fileShares[shareId].rights; ur; ur = ur->next)
if (!ur->isGroup && stricmp(ur->user, user) == 0)
session->rights |= ur->rights;
getUserGroups(user, groups);
for (ur = fileShares[shareId].rights; ur; ur = ur->next)
if (ur->isGroup)
for (i = 0; i < MAX_GROUPS_PER_USER; i++)
if (groups[i] && stricmp(ur->user, groups[i]) == 0)
{
session->rights |= ur->rights;
break;
}
for (i = 0; i < MAX_GROUPS_PER_USER; i++)
if (groups[i])
free(groups[i]);
if (session->rights == 0)
return BEOS_EACCES;
if (fileShares[shareId].readOnly)
session->rights = BT_RIGHTS_READ;
}
else
session->rights = fileShares[shareId].readOnly
? BT_RIGHTS_READ
: BT_RIGHTS_READ | BT_RIGHTS_WRITE;
path = fileShares[shareId].path;
if (stat(path, &st) != 0)
return BEOS_ENOENT;
if (!S_ISDIR(st.st_mode))
return BEOS_EACCES;
strcpy(session->user, user);
return B_OK;
}
int btGetFSInfo(fs_info *fsInfo, char *path)
{
DWORD secsPerClstr, bytesPerSec, freeClstrs, totalClstrs;
char rootDir[5];
strncpy(rootDir, path, 3);
rootDir[3] = 0;
if (GetDiskFreeSpace(rootDir, &secsPerClstr, &bytesPerSec, &freeClstrs, &totalClstrs))
{
fsInfo->block_size = bytesPerSec;
fsInfo->total_blocks = secsPerClstr * totalClstrs;
fsInfo->free_blocks = secsPerClstr * freeClstrs;
return B_OK;
}
return ENOTSUP;
}
int btLookup(char *pathBuf, vnode_id dir_vnid, char *fileName, vnode_id *file_vnid)
{
struct _stat st;
if (_stat(fileName, &st) != 0)
return BEOS_ENOENT;
return B_OK;
}
int btStat(char *pathBuf, vnode_id vnid, beos_stat *st)
{
char *fileName;
int error;
fileName = btGetLocalFileName(pathBuf, vnid);
if (fileName)
{
error = btGetBeosStat(fileName, st);
return error;
}
return BEOS_ENOENT;
}
int btReadDir(char *pathBuf, vnode_id dir_vnid, long **dir, vnode_id *file_vnid, char *filename, beos_stat *st)
{
struct _finddata_t fileInfo;
char *folder, path[B_PATH_NAME_LENGTH];
long result = -1;
if (dir_vnid == 0 || !file_vnid || !filename)
return EINVAL;
if (!*dir)
{
folder = btGetLocalFileName(pathBuf, dir_vnid);
if (folder)
{
char search[B_PATH_NAME_LENGTH];
btMakePath(search, folder, "*.*");
result = _findfirst(search, &fileInfo);
*dir = (long *) malloc(sizeof(long *));
memcpy(*dir, &result, sizeof(result));
}
}
else
result = _findnext((long) **dir, &fileInfo);
if (result != -1)
{
folder = btGetLocalFileName(pathBuf, dir_vnid);
if (folder)
{
btMakePath(path, folder, fileInfo.name);
if (btGetBeosStat(path, st) != 0)
return BEOS_ENOENT;
strcpy(filename, fileInfo.name);
*file_vnid = (vnode_id) st->st_ino;
btAddHandle(dir_vnid, *file_vnid, filename);
return B_OK;
}
}
else if (*dir)
{
_findclose((long) **dir);
return BEOS_ENOENT;
}
return EINVAL;
}
int32 btRead(char *pathBuf, vnode_id vnid, beos_off_t pos, int32 len, char *buffer)
{
char *path;
int bytes;
path = btGetLocalFileName(pathBuf, vnid);
if (path)
{
FILE *fp = fopen(path, "rb");
if (!fp)
return EACCES;
fseek(fp, (int) pos, SEEK_SET);
bytes = fread(buffer, 1, len, fp);
fclose(fp);
buffer[bytes] = 0;
return bytes;
}
return 0;
}
int32 btWrite(bt_session_t *session, vnode_id vnid, beos_off_t pos, int32 len, int32 totalLen, char *buffer)
{
bt_block *block;
if (totalLen > 0)
{
if (totalLen > 10 * 1024 * 1024)
return 0;
block = (bt_block *) malloc(sizeof(bt_block));
if (block)
{
block->vnid = vnid;
block->pos = pos;
block->len = totalLen;
block->count = 0;
block->buffer = (char *) malloc(totalLen + 1);
if (!block->buffer)
{
free(block);
return 0;
}
btInsertWriteBlock(session, block);
}
else
return 0;
}
else
{
block = btGetWriteBlock(session, vnid);
if (!block)
return 0;
}
memcpy(block->buffer + block->count, buffer, len);
block->count += len;
return len;
}
bt_block *btGetWriteBlock(bt_session_t *session, vnode_id vnid)
{
bt_block *block;
WaitForSingleObject(session->blockSem, INFINITE);
block = session->rootBlock;
while (block && block->vnid != vnid)
block = block->next;
ReleaseSemaphore(session->blockSem, 1, NULL);
return block;
}
void btInsertWriteBlock(bt_session_t *session, bt_block *block)
{
WaitForSingleObject(session->blockSem, INFINITE);
block->next = session->rootBlock;
block->prev = NULL;
if (session->rootBlock)
session->rootBlock->prev = block;
session->rootBlock = block;
ReleaseSemaphore(session->blockSem, 1, NULL);
}
int btCommit(bt_session_t *session, vnode_id vnid)
{
bt_block *block;
char *path;
int file;
path = btGetLocalFileName(session->pathBuffer, vnid);
if (!path)
return BEOS_ENOENT;
block = btGetWriteBlock(session, vnid);
if (!block)
return BEOS_ENOENT;
file = _open(path, _O_WRONLY | _O_CREAT | _O_BINARY);
if (file < 0)
return errno;
WaitForSingleObject(session->blockSem, INFINITE);
_lseek(file, (int32) block->pos, SEEK_SET);
_write(file, block->buffer, block->len);
btRemoveWriteBlock(session, block);
ReleaseSemaphore(session->blockSem, 1, NULL);
_close(file);
return B_OK;
}
void btRemoveWriteBlock(bt_session_t *session, bt_block *block)
{
if (session->rootBlock == block)
session->rootBlock = block->next;
if (block->prev)
block->prev->next = block->next;
if (block->next)
block->next->prev = block->prev;
free(block->buffer);
free(block);
}
int btCreate(char *pathBuf, vnode_id dir_vnid, char *name, int omode, int perms, vnode_id *file_vnid)
{
beos_stat st;
char path[B_PATH_NAME_LENGTH], *folder;
int fh;
folder = btGetLocalFileName(pathBuf, dir_vnid);
if (folder)
{
btMakePath(path, folder, name);
fh = open(path, O_WRONLY | O_CREAT | O_TRUNC, _S_IREAD | _S_IWRITE);
if (fh == -1)
return errno;
else
{
close(fh);
if (btGetBeosStat(path, &st) == 0)
{
*file_vnid = (vnode_id) st.st_ino;
btAddHandle(dir_vnid, *file_vnid, name);
}
else
return BEOS_EACCES;
}
}
return B_OK;
}
int btTruncate(char *pathBuf, vnode_id vnid, int64 len)
{
char *path;
path = btGetLocalFileName(pathBuf, vnid);
if (path)
{
FILE *fp = fopen(path, "w");
fclose(fp);
return B_OK;
}
return BEOS_EACCES;
}
int btCreateDir(char *pathBuf, vnode_id dir_vnid, char *name, int perms, vnode_id *file_vnid, beos_stat *st)
{
char path[B_PATH_NAME_LENGTH], *folder;
folder = btGetLocalFileName(pathBuf, dir_vnid);
if (folder)
{
btMakePath(path, folder, name);
if (_mkdir(path) == -1)
return errno;
if (btGetBeosStat(path, st) != 0)
return BEOS_ENOENT;
*file_vnid = (vnode_id) st->st_ino;
btAddHandle(dir_vnid, *file_vnid, name);
return B_OK;
}
return BEOS_ENOENT;
}
int btDeleteDir(char *pathBuf, vnode_id vnid, char *name)
{
struct _stat st;
char path[B_PATH_NAME_LENGTH], *folder;
folder = btGetLocalFileName(pathBuf, vnid);
if (folder)
{
btMakePath(path, folder, name);
if (_stat(path, &st) != 0)
return errno;
if (_rmdir(path) == -1)
return errno;
btPurgeNodes(btGetWinInode(path));
return B_OK;
}
return BEOS_ENOENT;
}
int btRename(char *pathBuf, vnode_id old_vnid, char *oldName, vnode_id new_vnid, char *newName)
{
struct _stat st;
char oldPath[B_PATH_NAME_LENGTH], newPath[B_PATH_NAME_LENGTH], *oldFolder, *newFolder;
oldFolder = btGetLocalFileName(pathBuf, old_vnid);
if (oldFolder)
{
btMakePath(oldPath, oldFolder, oldName);
newFolder = btGetLocalFileName(pathBuf, new_vnid);
if (newFolder)
{
btMakePath(newPath, newFolder, newName);
if (_stat(oldPath, &st) != 0)
return errno;
btPurgeNodes(btGetWinInode(oldPath));
if (rename(oldPath, newPath) == -1)
return errno;
return B_OK;
}
}
return BEOS_ENOENT;
}
int btUnlink(char *pathBuf, vnode_id vnid, char *name)
{
struct _stat st;
char path[B_PATH_NAME_LENGTH], *folder;
int error;
folder = btGetLocalFileName(pathBuf, vnid);
if (folder)
{
btMakePath(path, folder, name);
if (_stat(path, &st) != 0)
return errno;
btRemoveHandle(btGetWinInode(path));
error = unlink(path);
return (error == -1 ? errno : B_OK);
}
return BEOS_EACCES;
}
int btReadLink(char *pathBuf, vnode_id vnid, char *buffer, int length)
{
return BEOS_ENOENT;
}
int btSymLink(char *pathBuf, vnode_id vnid, char *name, char *dest)
{
return BEOS_ENOENT;
}
int btWStat(char *pathBuf, vnode_id vnid, long mask, int32 mode, int32 uid, int32 gid, int64 size, int32 atime, int32 mtime)
{
struct _utimbuf ftimes;
struct _stat st;
char *path;
path = btGetLocalFileName(pathBuf, vnid);
if (path)
{
if (_stat(path, &st) == 0)
if (mask & WSTAT_ATIME || mask & WSTAT_MTIME)
{
ftimes.actime = mask & WSTAT_ATIME ? atime : st.st_atime;
ftimes.modtime = mask & WSTAT_MTIME ? mtime : st.st_mtime;
_utime(path, &ftimes);
}
return B_OK;
}
return BEOS_ENOENT;
}
int btReadAttrib(char *pathBuf, vnode_id vnid, char *name, char *buffer)
{
bt_mime_mapping *map;
char *path;
path = btGetLocalFileName(pathBuf, vnid);
if (path)
{
char *ext = strrchr(path, '.');
if (ext)
{
ext++;
for (map = mimeMap; map; map = map->next)
if (stricmp(ext, map->extension) == 0)
{
strcpy(buffer, map->mimeType);
return (strlen(buffer));
}
}
}
return 0;
}
int btAuthenticate(char *resource, char *user, char *password)
{
bt_user_rights *ur, *rootUr;
bt_printer *printer;
char *groups[MAX_GROUPS_PER_USER];
int i, rights, share;
bool authenticated = false;
share = btGetShareId(resource);
if (share >= 0)
{
if (fileShares[share].security == BT_AUTH_NONE)
return B_OK;
rootUr = fileShares[share].rights;
}
else
{
printer = btFindPrinter(resource);
if (printer)
if (printer->security == BT_AUTH_NONE)
return B_OK;
rootUr = printer->rights;
}
authenticated = authenticateUser(user, password);
if (!authenticated)
return BEOS_EACCES;
rights = 0;
for (ur = rootUr; ur; ur = ur->next)
if (!ur->isGroup && stricmp(ur->user, user) == 0)
rights |= ur->rights;
for (i = 0; i < MAX_GROUPS_PER_USER; i++)
groups[i] = NULL;
getUserGroups(user, groups);
for (ur = rootUr; ur; ur = ur->next)
if (ur->isGroup)
for (i = 0; i < MAX_GROUPS_PER_USER; i++)
if (groups[i] && stricmp(ur->user, groups[i]) == 0)
{
rights |= ur->rights;
break;
}
for (i = 0; i < MAX_GROUPS_PER_USER; i++)
if (groups[i])
free(groups[i]);
if (!rights)
return BEOS_EACCES;
return B_OK;
}
void netbtPreMount(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client, security;
client = session->socket;
security = btPreMount(session, argv[0].data);
btRPCCreateAck(&packet, xid, security);
btRPCSendAck(session->socket, &packet);
}
void netbtMount(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
vnode_id vnid;
int client, error;
char *shareName = argv[0].data;
char *user = argv[1].data;
char *password = argv[2].data;
client = session->socket;
error = btMount(session, shareName, user, password, &vnid);
if (error == B_OK)
{
session->share = btGetShareId(shareName);
session->logon = time(NULL);
btRPCCreateAck(&packet, xid, error);
btRPCPutInt64(&packet, vnid);
}
else
btRPCCreateAck(&packet, xid, error);
btRPCSendAck(client, &packet);
}
void netbtFSInfo(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client, error;
fs_info info;
client = session->socket;
error = btGetFSInfo(&info, fileShares[session->share].path);
if (error == B_OK)
{
btRPCCreateAck(&packet, xid, error);
btRPCPutInt32(&packet, info.block_size);
btRPCPutInt32(&packet, info.total_blocks);
btRPCPutInt32(&packet, info.free_blocks);
}
else
btRPCCreateAck(&packet, xid, error);
btRPCSendAck(client, &packet);
}
void netbtLookup(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
beos_stat st;
int client, error;
vnode_id dir_vnid = *((vnode_id *) argv[0].data);
vnode_id file_vnid;
client = session->socket;
error = btLookup(session->pathBuffer, dir_vnid, argv[1].data, &file_vnid);
if (error == B_OK)
error = btStat(session->pathBuffer, file_vnid, &st);
if (error == B_OK)
{
btRPCCreateAck(&packet, xid, B_OK);
btRPCPutInt64(&packet, file_vnid);
btRPCPutStat(&packet, &st);
}
else
btRPCCreateAck(&packet, xid, error);
btRPCSendAck(client, &packet);
}
void netbtReadDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
const int MAX_FOLDER_ENTRIES = 128;
bt_outPacket packet;
beos_stat st;
int client, error;
vnode_id dir_vnid = *((vnode_id *) argv[0].data);
vnode_id file_vnid;
long *dir;
char filename[B_PATH_NAME_LENGTH];
int entries = 0;
client = session->socket;
dir = (long *)(*((int32 *) argv[1].data));
error = btReadDir(session->pathBuffer, dir_vnid, &dir, &file_vnid, filename, &st);
if (error != B_OK)
{
btRPCCreateAck(&packet, xid, error);
btRPCSendAck(client, &packet);
return;
}
btRPCCreateAck(&packet, xid, B_OK);
while (error == B_OK)
{
btRPCPutInt64(&packet, file_vnid);
btRPCPutString(&packet, filename, strlen(filename));
btRPCPutInt32(&packet, (int32) dir);
btRPCPutStat(&packet, &st);
if (++entries >= MAX_FOLDER_ENTRIES)
break;
error = btReadDir(session->pathBuffer, dir_vnid, &dir, &file_vnid, filename, &st);
btRPCPutInt32(&packet, error);
}
if (entries < MAX_FOLDER_ENTRIES)
btRPCPutInt32(&packet, BEOS_ENOENT);
btRPCSendAck(client, &packet);
}
void netbtStat(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client, error;
beos_stat info;
vnode_id vnid = *((vnode_id *) argv[0].data);
client = session->socket;
error = btStat(session->pathBuffer, vnid, &info);
if (error == B_OK)
{
btRPCCreateAck(&packet, xid, error);
btRPCPutStat(&packet, &info);
}
else
btRPCCreateAck(&packet, xid, error);
btRPCSendAck(client, &packet);
}
void netbtRead(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client;
vnode_id vnid = *((vnode_id *) argv[0].data);
beos_off_t pos = *((beos_off_t *) argv[1].data);
int32 len = *((int32 *) argv[2].data);
int32 bytes = 0;
client = session->socket;
session->ioBuffer[len] = 0;
bytes = btRead(session->pathBuffer, vnid, pos, len, session->ioBuffer);
btRPCCreateAck(&packet, xid, B_OK);
btRPCPutString(&packet, session->ioBuffer, bytes);
btRPCSendAck(client, &packet);
}
void netbtWrite(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
int client;
vnode_id vnid = *((vnode_id *) argv[0].data);
beos_off_t pos = *((beos_off_t *) argv[1].data);
int32 len = *((int32 *) argv[2].data);
int32 totalLen = *((int32 *) argv[3].data);
client = session->socket;
if (session->rights & BT_RIGHTS_WRITE)
btWrite(session, vnid, pos, len, totalLen, argv[4].data);
}
void netbtCreate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
beos_stat st;
int client, error;
vnode_id dir_vnid = *((vnode_id *) argv[0].data);
vnode_id file_vnid;
int omode = *((int *) argv[2].data);
int perms = *((int *) argv[3].data);
client = session->socket;
if (!(session->rights & BT_RIGHTS_WRITE))
{
btRPCCreateAck(&packet, xid, BEOS_EACCES);
btRPCSendAck(client, &packet);
return;
}
error = btCreate(session->pathBuffer, dir_vnid, argv[1].data, omode, perms, &file_vnid);
if (error == B_OK)
error = btStat(session->pathBuffer, file_vnid, &st);
if (error == B_OK)
{
btRPCCreateAck(&packet, xid, B_OK);
btRPCPutInt64(&packet, file_vnid);
btRPCPutStat(&packet, &st);
}
else
btRPCCreateAck(&packet, xid, error);
btRPCSendAck(client, &packet);
}
void netbtTruncate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client, error;
vnode_id vnid = *((vnode_id *) argv[0].data);
client = session->socket;
if (!(session->rights & BT_RIGHTS_WRITE))
{
btRPCCreateAck(&packet, xid, BEOS_EACCES);
btRPCSendAck(client, &packet);
return;
}
error = btTruncate(session->pathBuffer, vnid, *((int64 *) argv[1].data));
btRPCCreateAck(&packet, xid, error);
btRPCSendAck(client, &packet);
}
void netbtUnlink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client, error;
vnode_id vnid = *((vnode_id *) argv[0].data);
client = session->socket;
if (!(session->rights & BT_RIGHTS_WRITE))
{
btRPCCreateAck(&packet, xid, BEOS_EACCES);
btRPCSendAck(client, &packet);
return;
}
error = btUnlink(session->pathBuffer, vnid, argv[1].data);
btRPCCreateAck(&packet, xid, error);
btRPCSendAck(client, &packet);
}
void netbtRename(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client, error;
vnode_id old_vnid = *((vnode_id *) argv[0].data);
vnode_id new_vnid = *((vnode_id *) argv[2].data);
client = session->socket;
if (!(session->rights & BT_RIGHTS_WRITE))
{
btRPCCreateAck(&packet, xid, BEOS_EACCES);
btRPCSendAck(client, &packet);
return;
}
error = btRename(session->pathBuffer, old_vnid, argv[1].data, new_vnid, argv[3].data);
btRPCCreateAck(&packet, xid, error);
btRPCSendAck(client, &packet);
}
void netbtCreateDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client, error;
vnode_id dir_vnid = *((vnode_id *) argv[0].data);
vnode_id file_vnid;
beos_stat st;
client = session->socket;
if (!(session->rights & BT_RIGHTS_WRITE))
{
btRPCCreateAck(&packet, xid, BEOS_EACCES);
btRPCSendAck(client, &packet);
return;
}
error = btCreateDir(session->pathBuffer, dir_vnid, argv[1].data, *((int *) argv[2].data), &file_vnid, &st);
if (error == B_OK)
{
btRPCCreateAck(&packet, xid, B_OK);
btRPCPutInt64(&packet, file_vnid);
btRPCPutStat(&packet, &st);
}
else
btRPCCreateAck(&packet, xid, error);
btRPCSendAck(client, &packet);
}
void netbtDeleteDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client, error;
vnode_id vnid = *((vnode_id *) argv[0].data);
client = session->socket;
if (!(session->rights & BT_RIGHTS_WRITE))
{
btRPCCreateAck(&packet, xid, BEOS_EACCES);
btRPCSendAck(client, &packet);
return;
}
error = btDeleteDir(session->pathBuffer, vnid, argv[1].data);
btRPCCreateAck(&packet, xid, error);
btRPCSendAck(client, &packet);
}
void netbtReadLink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client;
client = session->socket;
btRPCCreateAck(&packet, xid, ENOTSUP);
btRPCSendAck(client, &packet);
}
void netbtSymLink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client;
client = session->socket;
btRPCCreateAck(&packet, xid, ENOTSUP);
btRPCSendAck(client, &packet);
}
void netbtWStat(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client, error;
vnode_id vnid = *((vnode_id *) argv[0].data);
int32 mask = *((int32 *) argv[1].data);
int32 mode = *((int32 *) argv[2].data);
int32 uid = *((int32 *) argv[3].data);
int32 gid = *((int32 *) argv[4].data);
int64 size = (int64) *((int32 *) argv[5].data);
int32 atime = *((int32 *) argv[6].data);
int32 mtime = *((int32 *) argv[7].data);
client = session->socket;
if (!(session->rights & BT_RIGHTS_WRITE))
{
btRPCCreateAck(&packet, xid, BEOS_EACCES);
btRPCSendAck(client, &packet);
return;
}
error = btWStat(session->pathBuffer, vnid, mask, mode, uid, gid, size, atime, mtime);
btRPCCreateAck(&packet, xid, error);
btRPCSendAck(client, &packet);
}
void netbtReadAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client, bytesRead;
client = session->socket;
if (stricmp(argv[1].data, "BEOS:TYPE") == 0)
{
vnode_id vnid = *((vnode_id *) argv[0].data);
bytesRead = btReadAttrib(session->pathBuffer, vnid, argv[1].data, session->attrBuffer);
if (bytesRead > 0)
{
btRPCCreateAck(&packet, xid, B_OK);
btRPCPutInt32(&packet, (int32) bytesRead + 1);
btRPCPutString(&packet, session->attrBuffer, bytesRead + 1);
btRPCSendAck(client, &packet);
return;
}
}
btRPCCreateAck(&packet, xid, ENOTSUP);
btRPCSendAck(client, &packet);
}
void netbtWriteAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client;
client = session->socket;
btRPCCreateAck(&packet, xid, ENOTSUP);
btRPCSendAck(client, &packet);
}
void netbtReadAttribDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client;
client = session->socket;
btRPCCreateAck(&packet, xid, ENOTSUP);
btRPCSendAck(client, &packet);
}
void netbtRemoveAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client;
client = session->socket;
btRPCCreateAck(&packet, xid, ENOTSUP);
btRPCSendAck(client, &packet);
}
void netbtStatAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client, bytesRead;
client = session->socket;
if (strcmp(argv[1].data, "BEOS:TYPE") == 0)
{
vnode_id vnid = *((vnode_id *) argv[0].data);
bytesRead = btReadAttrib(session->pathBuffer, vnid, argv[1].data, session->attrBuffer);
btRPCCreateAck(&packet, xid, B_OK);
btRPCPutInt32(&packet, B_STRING_TYPE);
btRPCPutInt64(&packet, bytesRead + 1);
btRPCSendAck(client, &packet);
return;
}
btRPCCreateAck(&packet, xid, ENOTSUP);
btRPCSendAck(client, &packet);
}
void netbtReadIndexDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client;
client = session->socket;
btRPCCreateAck(&packet, xid, ENOTSUP);
btRPCSendAck(client, &packet);
}
void netbtCreateIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client;
client = session->socket;
btRPCCreateAck(&packet, xid, ENOTSUP);
btRPCSendAck(client, &packet);
}
void netbtRemoveIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client;
client = session->socket;
btRPCCreateAck(&packet, xid, ENOTSUP);
btRPCSendAck(client, &packet);
}
void netbtStatIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client;
client = session->socket;
btRPCCreateAck(&packet, xid, ENOTSUP);
btRPCSendAck(client, &packet);
}
void netbtReadQuery(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client;
client = session->socket;
btRPCCreateAck(&packet, xid, ENOTSUP);
btRPCSendAck(client, &packet);
}
void netbtCommit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client, error;
vnode_id vnid = *((vnode_id *) argv[0].data);
client = session->socket;
if (!(session->rights & BT_RIGHTS_WRITE))
{
btRPCCreateAck(&packet, xid, BEOS_EACCES);
btRPCSendAck(client, &packet);
return;
}
error = btCommit(session, vnid);
btRPCCreateAck(&packet, xid, error);
btRPCSendAck(client, &packet);
}
void netbtPrintJobNew(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client, error;
char jobId[MAX_NAME_LENGTH];
char *printerName = argv[0].data;
char *user = argv[1].data;
char *password = argv[2].data;
char *jobName = argv[3].data;
client = session->socket;
error = btPrintJobNew(printerName, user, password, session->client_s_addr, jobName, jobId);
btRPCCreateAck(&packet, xid, error);
if (error == B_OK)
btRPCPutString(&packet, jobId, strlen(jobId));
btRPCSendAck(client, &packet);
}
void netbtPrintJobData(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client, error;
char *printerName = argv[0].data;
char *jobId = argv[1].data;
char *jobData = argv[2].data;
int32 dataLen = *((int32 *) argv[3].data);
client = session->socket;
error = btPrintJobData(printerName, jobId, jobData, dataLen);
btRPCCreateAck(&packet, xid, error);
btRPCSendAck(client, &packet);
}
void netbtPrintJobCommit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client, error;
char *printerName = argv[0].data;
char *jobId = argv[1].data;
client = session->socket;
error = btPrintJobCommit(printerName, jobId);
btRPCCreateAck(&packet, xid, error);
btRPCSendAck(client, &packet);
}
void netbtAuthenticate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client, error;
char *resource = argv[0].data;
char *user = argv[1].data;
char *password = argv[2].data;
client = session->socket;
error = btAuthenticate(resource, user, password);
btRPCCreateAck(&packet, xid, error);
btRPCSendAck(client, &packet);
}
void netbtQuit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[])
{
bt_outPacket packet;
int client;
client = session->socket;
btRPCCreateAck(&packet, xid, B_OK);
btRPCSendAck(client, &packet);
}
bool IsValidUser(char *user, char *domain, char *password)
{
HANDLE hUser, hTok;
OSVERSIONINFO osInfo;
bool authenticated;
authenticated = false;
osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx(&osInfo))
if (osInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
return true;
hTok = 0;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hTok))
{
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (LookupPrivilegeValue(0, SE_TCB_NAME, &tp.Privileges[0].Luid))
if (AdjustTokenPrivileges(hTok, FALSE, &tp, 0, NULL, NULL))
if (LogonUser(user, domain, password, LOGON32_LOGON_BATCH, LOGON32_PROVIDER_DEFAULT, &hUser))
{
CloseHandle(hUser);
authenticated = true;
}
CloseHandle(hTok);
}
return authenticated;
}
*/
void loadFolder(const char *path)
{
struct _finddata_t fileInfo;
struct _stat st;
char *search;
long dir, result;
uint32 dir_vnid;
search = (char *) malloc(MAX_PATH);
if (search == NULL)
return;
dir_vnid = btGetWinInode(path);
sprintf(search, "%s\\*.*", path);
dir = result = _findfirst(search, &fileInfo);
while (result != -1)
{
btMakePath(search, (char *) path, fileInfo.name);
btAddHandle(dir_vnid, btGetWinInode(search), fileInfo.name);
_stat(search, &st);
if (st.st_mode & _S_IFDIR)
if (strcmp(fileInfo.name, ".") && strcmp(fileInfo.name, ".."))
loadFolder(search);
result = _findnext(dir, &fileInfo);
}
_findclose(dir);
free(search);
}
void KillNode(ubi_trNodePtr node)
{
bt_node *bn = (bt_node *) node;
free(bn->name);
free(node);
}
int CompareVnidNodes(ubi_trItemPtr item, ubi_trNodePtr node)
{
vnode_id vnid1 = *((vnode_id *) item);
vnode_id vnid2 = ((bt_node *) node)->vnid;
if (vnid1 < vnid2)
return -1;
else if (vnid1 > vnid2)
return 1;
else
return 0;
}
int CompareNameNodes(ubi_trItemPtr item, ubi_trNodePtr node)
{
bt_node *node1 = (bt_node *) item;
bt_node *node2 = (bt_node *) node;
if (node1->parent < node2->parent)
return -1;
else if (node1->parent > node2->parent)
return 1;
else
return strcmp(node1->name, node2->name);
}