1// BeServed.cpp : Defines the entry point for the application. 2// 3 4#include "stdafx.h" 5 6#include "beCompat.h" 7#include "betalk.h" 8#include "authentication.h" 9#include "readerWriter.h" 10#include "printing.h" 11#include "ubi_SplayTree.h" 12 13// Windows service-specific header files. 14#include "winsvc.h" 15#include "NTServApp.h" 16#include "myservice.h" 17 18#define BT_MAX_THREADS 100 19#define BT_MAX_RETRIES 3 20#define BT_MAX_FILE_SHARES 128 21#define BT_MAX_PRINTER_SHARES 16 22 23#define BT_THREAD_NAME "BeServed Handler" 24#define BT_HOST_THREAD_NAME "BeServed Host Publisher" 25 26#define PATH_ROOT "/boot" 27#define PATH_DELIMITER '/' 28 29#ifndef iswhite 30#define iswhite(c) ((c == ' ' || c == '\t')) 31#endif 32 33typedef struct 34{ 35 unsigned int type; 36 unsigned int length; 37 char *data; 38} bt_arg_t; 39 40typedef struct btblock 41{ 42 vnode_id vnid; 43 beos_off_t pos; 44 int32 len; 45 int32 count; 46 char *buffer; 47 struct btblock *next; 48 struct btblock *prev; 49} bt_block; 50 51typedef struct session 52{ 53 int socket; 54 unsigned int client_s_addr; 55 HANDLE handlerID; 56 57 bool killed; 58 59 // The user that is connected. 60 char user[MAX_NAME_LENGTH + 1]; 61 62 // What share did the client connect to? And when? 63 int share; 64 int rights; 65 time_t logon; 66 67 // Buffered write support. 68 bt_block *rootBlock; 69 sem_id blockSem; 70 71 char ioBuffer[BT_MAX_IO_BUFFER + 1]; 72 char attrBuffer[BT_MAX_ATTR_BUFFER + 1]; 73 char pathBuffer[B_PATH_NAME_LENGTH]; 74 75 struct session *next; 76} bt_session_t; 77 78typedef void (*bt_net_func)(bt_session_t *, unsigned int, int, bt_arg_t *); 79 80typedef struct dirCommand 81{ 82 unsigned char command; 83 bt_net_func handler; 84 bool supported; 85 uint8 args; 86 uint32 argTypes[MAX_COMMAND_ARGS]; 87} bt_command_t; 88 89typedef struct 90{ 91 vnode_id vnid; 92 int shareId; 93 char unused[20]; 94} bt_fdesc; 95 96typedef struct btnode 97{ 98 ubi_trNode node; 99 vnode_id vnid; 100 char *name; 101 bool invalid; 102 struct btnode *parent; 103} bt_node; 104 105typedef struct fileShare 106{ 107 char path[B_PATH_NAME_LENGTH]; 108 char name[B_FILE_NAME_LENGTH]; 109 110 bool used; 111 bool readOnly; 112 113 // What rights does each user have? 114 bt_user_rights *rights; 115 int security; 116 117 struct fileShare *next; 118} bt_fileShare_t; 119 120typedef struct mime_mapping 121{ 122 char extension[7]; 123 char *mimeType; 124 struct mime_mapping *next; 125} bt_mime_mapping; 126 127 128void BeServedStartup(CMyService *service); 129bool dateCheck(); 130DWORD WINAPI btSendHost(LPVOID data); 131void getHostInfo(bt_hostinfo *info); 132int getSharedResources(char *buffer, int bufSize, bool shares, bool printers); 133int getHostUsers(char *buffer); 134void startService(); 135void endService(int sig); 136void initMimeMap(); 137void closeMimeMap(); 138void closePrinters(); 139void freeFileShares(); 140void waitForThread(HANDLE threadId); 141 142void initShares(); 143void initPrinters(); 144void loadShares(); 145void getFileShare(const char *buffer); 146void loadFolder(const char *path); 147void getShareProperty(const char *buffer); 148void getAuthenticate(const char *buffer); 149bool getAuthServerAddress(const char *name); 150void addUserRights(char *share, char *user, int rights, bool isGroup); 151void getGrant(const char *buffer); 152void getPrinter(const char *buffer); 153int getToken(); 154 155int receiveRequest(bt_session_t *session); 156void handleRequest(bt_session_t *session, unsigned int xid, unsigned char command, int argc, bt_arg_t argv[]); 157void launchThread(int client, struct sockaddr_in *addr); 158int tooManyConnections(unsigned int _s_addr); 159void sendErrorToClient(int client, unsigned int xid, int error); 160void getArguments(bt_session_t *session, bt_inPacket *packet, unsigned char command); 161DWORD WINAPI requestThread(LPVOID data); 162DWORD WINAPI printerThread(LPVOID data); 163 164void KillNode(ubi_trNodePtr node); 165int CompareVnidNodes(ubi_trItemPtr item, ubi_trNodePtr node); 166int CompareNameNodes(ubi_trItemPtr item, ubi_trNodePtr node); 167 168bt_node *btGetNodeFromVnid(vnode_id vnid); 169void btAddHandle(vnode_id dir_vnid, vnode_id file_vnid, char *name); 170void btRemoveHandle(vnode_id vnid); 171void btPurgeNodes(vnode_id vnid); 172bool btIsAncestorNode(vnode_id vnid, bt_node *node); 173char *btGetLocalFileName(char *path, vnode_id vnid); 174void btMakeHandleFromNode(bt_node *node, vnode_id vnid); 175bt_node *btFindNode(bt_node *parent, char *fileName); 176char *btGetSharePath(char *shareName); 177int btGetShareId(char *shareName); 178int btGetShareIdByPath(char *path); 179bt_printer *btFindPrinter(char *printerName); 180uint32 btGetWinInode(const char *path); 181int btGetBeosStat(char *fileName, beos_stat *st); 182void btMakePath(char *path, char *dir, char *file); 183 184int btPreMount(bt_session_t *session, char *shareName); 185int btMount(bt_session_t *session, char *shareName, char *user, char *password, vnode_id *vnid); 186int btGetFSInfo(fs_info *fsInfo, char *path); 187int btLookup(char *pathBuf, vnode_id dir_vnid, char *fileName, vnode_id *file_vnid); 188int btStat(char *pathBuf, vnode_id vnid, beos_stat *st); 189int btReadDir(char *pathBuf, vnode_id dir_vnid, long **dir, vnode_id *file_vnid, char *filename, beos_stat *st); 190int32 btRead(char *pathBuf, vnode_id vnid, beos_off_t pos, int32 len, char *buffer); 191int32 btWrite(bt_session_t *session, vnode_id vnid, beos_off_t pos, int32 len, int32 totalLen, char *buffer); 192int btCreate(char *pathBuf, vnode_id dir_vnid, char *name, int omode, int perms, vnode_id *file_vnid); 193int btTruncate(char *pathBuf, vnode_id vnid, int64 len); 194int btCreateDir(char *pathBuf, vnode_id dir_vnid, char *name, int perms, vnode_id *file_vnid, beos_stat *st); 195int btDeleteDir(char *pathBuf, vnode_id dir_vnid, char *name); 196int btRename(char *pathBuf, vnode_id old_vnid, char *oldName, vnode_id new_vnid, char *newName); 197int btUnlink(char *pathBuf, vnode_id vnid, char *name); 198int btReadLink(char *pathBuf, vnode_id vnid, char *buffer, int length); 199int btSymLink(char *pathBuf, vnode_id vnid, char *name, char *dest); 200int btWStat(char *pathBuf, vnode_id vnid, long mask, int32 mode, int32 uid, int32 gid, int64 size, int32 atime, int32 mtime); 201int btCommit(bt_session_t *session, vnode_id vnid); 202int btReadAttrib(char *pathBuf, vnode_id vnid, char *name, char *buffer); 203int btAuthenticate(char *resource, char *user, char *password); 204 205bt_block *btGetWriteBlock(bt_session_t *session, vnode_id vnid); 206void btInsertWriteBlock(bt_session_t *session, bt_block *block); 207void btRemoveWriteBlock(bt_session_t *session, bt_block *block); 208 209void netbtPreMount(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 210void netbtMount(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 211void netbtFSInfo(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 212void netbtLookup(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 213void netbtStat(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 214void netbtReadDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 215void netbtRead(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 216void netbtWrite(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 217void netbtCreate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 218void netbtTruncate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 219void netbtCreateDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 220void netbtDeleteDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 221void netbtRename(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 222void netbtUnlink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 223void netbtReadLink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 224void netbtSymLink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 225void netbtWStat(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 226void netbtReadAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 227void netbtWriteAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 228void netbtReadAttribDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 229void netbtRemoveAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 230void netbtStatAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 231void netbtReadIndexDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 232void netbtCreateIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 233void netbtRemoveIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 234void netbtStatIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 235void netbtReadQuery(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 236void netbtCommit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 237void netbtPrintJobNew(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 238void netbtPrintJobData(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 239void netbtPrintJobCommit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 240void netbtAuthenticate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 241void netbtQuit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]); 242 243CMyService *winService; 244bt_node *rootNode = NULL; 245ubi_btRoot vnidTree; 246ubi_btRoot nameTree; 247bt_mime_mapping *mimeMap = NULL; 248bt_session_t *rootSession = NULL; 249bt_fileShare_t fileShares[BT_MAX_FILE_SHARES]; 250bt_printer sharedPrinters[BT_MAX_PRINTER_SHARES]; 251char tokBuffer[MAX_NAME_LENGTH + 1], *tokPtr; 252bool running = true; 253bool preload = false; 254int server; 255char authServerName[B_FILE_NAME_LENGTH]; 256unsigned int authServerIP; 257bt_managed_data handleData; 258bt_managed_data sessionData; 259HANDLE hostThread; 260 261char *keywords[] = 262{ 263 "share", 264 "as", 265 "set", 266 "read", 267 "write", 268 "read-write", 269 "promiscuous", 270 "on", 271 "to", 272 "authenticate", 273 "with", 274 "group", 275 "printer", 276 "print", 277 "is", 278 "spooled", 279 "device", 280 "type", 281 "preload", 282 NULL 283}; 284 285bt_command_t dirCommands[] = 286{ 287 { BT_CMD_PREMOUNT, netbtPreMount, true, 1, { B_STRING_TYPE } }, 288 { BT_CMD_MOUNT, netbtMount, true, 3, { B_STRING_TYPE, B_STRING_TYPE, B_STRING_TYPE } }, 289 { BT_CMD_FSINFO, netbtFSInfo, true, 1, { B_INT64_TYPE } }, 290 { BT_CMD_LOOKUP, netbtLookup, true, 2, { B_INT64_TYPE, B_STRING_TYPE } }, 291 { BT_CMD_STAT, netbtStat, true, 1, { B_INT64_TYPE } }, 292 { BT_CMD_READDIR, netbtReadDir, true, 2, { B_INT64_TYPE, B_STRING_TYPE } }, 293 { BT_CMD_READ, netbtRead, true, 3, { B_INT64_TYPE, B_INT32_TYPE, B_INT32_TYPE } }, 294 { BT_CMD_WRITE, netbtWrite, true, 5, { B_INT64_TYPE, B_INT64_TYPE, B_INT32_TYPE, B_INT32_TYPE, B_STRING_TYPE } }, 295 { BT_CMD_CREATE, netbtCreate, true, 4, { B_INT64_TYPE, B_STRING_TYPE, B_INT32_TYPE, B_INT32_TYPE } }, 296 { BT_CMD_TRUNCATE, netbtTruncate, true, 2, { B_INT64_TYPE, B_INT64_TYPE } }, 297 { BT_CMD_MKDIR, netbtCreateDir, true, 3, { B_INT64_TYPE, B_STRING_TYPE, B_INT32_TYPE } }, 298 { BT_CMD_RMDIR, netbtDeleteDir, true, 2, { B_INT64_TYPE, B_STRING_TYPE } }, 299 { BT_CMD_RENAME, netbtRename, true, 4, { B_INT64_TYPE, B_STRING_TYPE, B_INT64_TYPE, B_STRING_TYPE } }, 300 { BT_CMD_UNLINK, netbtUnlink, true, 2, { B_INT64_TYPE, B_STRING_TYPE } }, 301 { BT_CMD_READLINK, netbtReadLink, false, 1, { B_INT64_TYPE } }, 302 { BT_CMD_SYMLINK, netbtSymLink, false, 3, { B_INT64_TYPE, B_STRING_TYPE, B_STRING_TYPE } }, 303 { 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 } }, 304 { BT_CMD_READATTRIB, netbtReadAttrib, true, 5, { B_STRING_TYPE, B_STRING_TYPE, B_INT32_TYPE, B_INT32_TYPE, B_INT32_TYPE } }, 305 { BT_CMD_WRITEATTRIB, netbtWriteAttrib, false, 6, { B_STRING_TYPE, B_STRING_TYPE, B_INT32_TYPE, B_STRING_TYPE, B_INT32_TYPE, B_INT32_TYPE } }, 306 { BT_CMD_READATTRIBDIR, netbtReadAttribDir, false, 2, { B_STRING_TYPE, B_STRING_TYPE } }, 307 { BT_CMD_REMOVEATTRIB, netbtRemoveAttrib, false, 2, { B_STRING_TYPE, B_STRING_TYPE } }, 308 { BT_CMD_STATATTRIB, netbtStatAttrib, true, 2, { B_STRING_TYPE, B_STRING_TYPE } }, 309 { BT_CMD_READINDEXDIR, netbtReadIndexDir, false, 1, { B_STRING_TYPE } }, 310 { BT_CMD_CREATEINDEX, netbtCreateIndex, false, 3, { B_STRING_TYPE, B_INT32_TYPE, B_INT32_TYPE } }, 311 { BT_CMD_REMOVEINDEX, netbtRemoveIndex, false, 1, { B_STRING_TYPE } }, 312 { BT_CMD_STATINDEX, netbtStatIndex, false, 1, { B_STRING_TYPE } }, 313 { BT_CMD_READQUERY, netbtReadQuery, false, 2, { B_STRING_TYPE, B_STRING_TYPE } }, 314 { BT_CMD_COMMIT, netbtCommit, true, 1, { B_INT64_TYPE } }, 315 { BT_CMD_PRINTJOB_NEW, netbtPrintJobNew, true, 4, { B_STRING_TYPE, B_STRING_TYPE, B_STRING_TYPE, B_STRING_TYPE } }, 316 { BT_CMD_PRINTJOB_DATA, netbtPrintJobData, true, 4, { B_STRING_TYPE, B_STRING_TYPE, B_STRING_TYPE, B_INT32_TYPE } }, 317 { BT_CMD_PRINTJOB_COMMIT, netbtPrintJobCommit, true, 2, { B_STRING_TYPE, B_STRING_TYPE } }, 318 { BT_CMD_AUTHENTICATE, netbtAuthenticate, true, 3, { B_STRING_TYPE, B_STRING_TYPE, B_STRING_TYPE } }, 319 { BT_CMD_QUIT, netbtQuit, true, 0, { 0 } }, 320 { 0, NULL, false, 0, { 0 } } 321}; 322 323 324//int APIENTRY WinMain(HINSTANCE hInstance, 325// HINSTANCE hPrevInstance, 326// LPSTR lpCmdLine, 327// int nCmdShow) 328void BeServedStartup(CMyService *service) 329{ 330 WSADATA wsaData; 331 DWORD threadId; 332 333 ASSERT(service); 334 winService = service; 335 336 initPrinters(); 337 338 initMimeMap(); 339 initShares(); 340 signal(SIGINT, endService); 341 signal(SIGTERM, endService); 342 343 // Initialize the trees sorted by vnode_id and by name. 344 ubi_trInitTree(&vnidTree, CompareVnidNodes, 0); 345 ubi_trInitTree(&nameTree, CompareNameNodes, 0); 346 347 if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) 348 return; 349 350 if (initManagedData(&handleData)) 351 if (initManagedData(&sessionData)) 352 hostThread = CreateThread(NULL, 0, btSendHost, NULL, 0, &threadId); 353} 354 355bool dateCheck() 356{ 357 struct _stat st; 358 time_t curTime; 359 360 time(&curTime); 361 if (curTime > 1012537700) 362 return false; 363 364 if (_stat("/boot/home/config/servers/beserved_server", &st) == 0) 365 if (curTime < st.st_ctime || curTime > st.st_ctime + 7776000) 366 return false; 367 368 return true; 369} 370 371void restartService() 372{ 373 bt_fileShare_t *oldShares; 374 int i; 375 376 // Printers are easier because the printer name is sent with each print request. 377 // If the printer is no longer available, the next transmission sent regarding 378 // that printer will result in an error, terminating the print job on the client. 379 // All we have to do is clear out the structures, and initShares will read the 380 // configuration file. 381 initPrinters(); 382 383 // Delay all mounting and other file system operations. 384 beginWriting(&handleData); 385 beginWriting(&sessionData); 386 387 // Copy existing share data. 388 oldShares = (bt_fileShare_t *) malloc(sizeof(bt_fileShare_t) * BT_MAX_FILE_SHARES); 389 if (oldShares) 390 { 391 for (i = 0; i < BT_MAX_FILE_SHARES; i++) 392 memcpy(&oldShares[i], &fileShares[i], sizeof(bt_fileShare_t)); 393 394 // Reload the share data. 395 initShares(); 396 397 // Now loop through the old file shares. For each one, check if the same 398 // path exists in the new shares. 399 for (i = 0; i < BT_MAX_FILE_SHARES; i++) 400 if (oldShares[i].used) 401 { 402 bt_session_t *s; 403 int share = btGetShareIdByPath(oldShares[i].path); 404 if (share == -1) 405 { 406 for (s = rootSession; s; s = s->next) 407 if (s->share == i) 408 s->killed = true; 409 } 410 else if (share != i) 411 { 412 for (s = rootSession; s; s = s->next) 413 if (s->share == i) 414 s->share = share; 415 } 416 } 417 418 free(oldShares); 419 } 420 421 // Resume normal operation. 422 endWriting(&sessionData); 423 endWriting(&handleData); 424} 425 426DWORD WINAPI btSendHost(LPVOID data) 427{ 428 bt_request request; 429 bt_hostinfo info; 430 struct sockaddr_in serverAddr, clientAddr; 431 char buffer[4096]; 432 int server, addrLen, bufLen, replyLen; 433 434 buffer[0] = 0; 435 bufLen = sizeof(buffer); 436 437 server = socket(AF_INET, SOCK_DGRAM, 0); 438 if (server == INVALID_SOCKET) 439 return 0; 440 441 memset(&serverAddr, 0, sizeof(serverAddr)); 442 serverAddr.sin_family = AF_INET; 443 serverAddr.sin_port = htons(BT_QUERYHOST_PORT); 444 serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); 445 446 // Bind that socket to the address constructed above. 447 if (bind(server, (struct sockaddr *) &serverAddr, sizeof(serverAddr))) 448 return 0; 449 450 while (running) 451 { 452 addrLen = sizeof(struct sockaddr_in); 453 replyLen = 0; 454 if (recvfrom(server, (char *) &request, sizeof(request), 0, (struct sockaddr *) &clientAddr, &addrLen) <= 0) 455 continue; 456 457 switch (request.command) 458 { 459 case BT_REQ_HOST_PROBE: 460 gethostname(buffer, bufLen); 461 break; 462 463 case BT_REQ_SHARE_PROBE: 464 replyLen = getSharedResources(buffer, sizeof(buffer), true, true); 465 break; 466 467 case BT_REQ_PRINTER_PROBE: 468 replyLen = getSharedResources(buffer, sizeof(buffer), false, true); 469 break; 470 471 case BT_REQ_HOST_INFO: 472 getHostInfo(&info); 473 memcpy(buffer, &info, sizeof(bt_hostinfo)); 474 replyLen = sizeof(bt_hostinfo); 475 break; 476 477 case BT_REQ_HOST_USERS: 478 replyLen = getHostUsers(buffer); 479 break; 480 } 481 482 // If no reply length has been specified, calculate it now by taking the 483 // length of the buffer. 484 if (replyLen == 0) 485 replyLen = strlen(buffer); 486 487 sendto(server, buffer, replyLen, 0, (struct sockaddr *) &clientAddr, addrLen); 488 } 489 490 // Close the socket. Technically, I believe we should call shutdown() 491 // first, but the BeOS header file socket.h indicates that this 492 // function is not currently working. It is present but may not have 493 // any effect. 494 shutdown(server, 2); 495 closesocket(server); 496 return 0; 497} 498 499// getSharedResources() 500// 501int getSharedResources(char *buffer, int bufSize, bool shares, bool printers) 502{ 503 bt_resource resource; 504 int i, bufPos = 0; 505 506 // If the supplied buffer can't hold at least two resource structures, one 507 // for a shared resource and one to terminate the list, then don't bother 508 // building the list. 509 if (bufSize < 2 * sizeof(bt_resource)) 510 return 0; 511 512 if (shares) 513 for (i = 0; i < BT_MAX_FILE_SHARES; i++) 514 if (fileShares[i].used) 515 { 516 // If this is the last resource structure that will fit in the 517 // buffer, then don't add any more into the list. 518 if (bufPos + sizeof(bt_resource) >= bufSize) 519 break; 520 521 // Fill out the resource structure. 522 resource.type = BT_SHARED_FOLDER; 523 resource.subType = 0; 524 strcpy(resource.name, fileShares[i].name); 525 526 // Copy the resource structure into the buffer at the current offset. 527 memcpy(buffer + bufPos, &resource, sizeof(bt_resource)); 528 bufPos += sizeof(bt_resource); 529 } 530 531 if (printers) 532 for (i = 0; i < BT_MAX_PRINTER_SHARES; i++) 533 if (sharedPrinters[i].used) 534 { 535 // If this is the last resource structure that will fit in the 536 // buffer, then don't add any more into the list. 537 if (bufPos + sizeof(bt_resource) >= bufSize) 538 break; 539 540 // Fill out the resource structure. 541 resource.type = BT_SHARED_PRINTER; 542 resource.subType = BT_PRINTER_PCL3; 543 strcpy(resource.name, sharedPrinters[i].printerName); 544 545 // Copy the resource structure into the buffer at the current offset. 546 memcpy(buffer + bufPos, &resource, sizeof(bt_resource)); 547 bufPos += sizeof(bt_resource); 548 } 549 550 // Copy the null terminating structure. 551 resource.type = BT_SHARED_NULL; 552 resource.subType = 0; 553 resource.name[0] = 0; 554 memcpy(buffer + bufPos, &resource, sizeof(bt_resource)); 555 bufPos += sizeof(bt_resource); 556 557 return bufPos; 558} 559 560// getHostInfo() 561// 562void getHostInfo(bt_hostinfo *info) 563{ 564 SYSTEM_INFO systemInfo; 565 OSVERSIONINFOEX osInfo; 566 bt_session_t *s; 567 568 osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); 569 if (!GetVersionEx((OSVERSIONINFO *) &osInfo)) 570 { 571 osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 572 GetVersionEx((OSVERSIONINFO *) &osInfo); 573 } 574 575 GetSystemInfo(&systemInfo); 576 577 switch (osInfo.dwPlatformId) 578 { 579 case VER_PLATFORM_WIN32_WINDOWS: 580 if (osInfo.dwMinorVersion == 0) 581 { 582 strcpy(info->system, "Windows 95"); 583 if (osInfo.szCSDVersion[1] == 'C' || osInfo.szCSDVersion[1] == 'B') 584 strcat(info->system, " OSR2"); 585 } 586 else if (osInfo.dwMinorVersion == 10) 587 { 588 strcpy(info->system, "Windows 98"); 589 if (osInfo.szCSDVersion[1] == 'A') 590 strcat(info->system, " SE"); 591 } 592 else if (osInfo.dwMinorVersion == 90) 593 strcpy(info->system, "Windows Me"); 594 break; 595 596 case VER_PLATFORM_WIN32_NT: 597 if (osInfo.dwMajorVersion <= 4) 598 sprintf(info->system, "Windows NT %d.%d %s (Build %d)", 599 osInfo.dwMajorVersion, osInfo.dwMinorVersion, osInfo.szCSDVersion, 600 osInfo.dwBuildNumber); 601 else if (osInfo.dwMajorVersion == 5) 602 if (osInfo.dwMinorVersion == 0) 603 sprintf(info->system, "Windows 2000 %s (Build %d)", 604 osInfo.szCSDVersion, osInfo.dwBuildNumber & 0xffff); 605 else 606 sprintf(info->system, "Windows XP %s (Build %d)", 607 osInfo.szCSDVersion, osInfo.dwBuildNumber & 0xffff); 608 609 break; 610 } 611 612 strcpy(info->beServed, "BeServed 1.2.6"); 613 614 info->cpus = systemInfo.dwNumberOfProcessors; 615 info->maxConnections = BT_MAX_THREADS; 616 617 switch (systemInfo.wProcessorArchitecture) 618 { 619 case PROCESSOR_ARCHITECTURE_MIPS: 620 strcpy(info->platform, "MIPS"); 621 break; 622 623 case PROCESSOR_ARCHITECTURE_ALPHA: 624 strcpy(info->platform, "DEC Alpha"); 625 break; 626 627 case PROCESSOR_ARCHITECTURE_PPC: 628 strcpy(info->platform, "PowerPC"); 629 break; 630 631 case PROCESSOR_ARCHITECTURE_INTEL: 632 strcpy(info->platform, "Intel x86"); 633 break; 634 635 default: 636 strcpy(info->platform, "Unknown"); 637 } 638 639 // Delay all new session creation. 640 beginReading(&sessionData); 641 642 info->connections = 0; 643 for (s = rootSession; s; s = s->next) 644 if (s->socket != INVALID_SOCKET) 645 info->connections++; 646 647 info->connections = B_HOST_TO_LENDIAN_INT32(info->connections); 648 endReading(&sessionData); 649} 650 651// getHostUsers() 652// 653int getHostUsers(char *buffer) 654{ 655 bt_session_t *s; 656 char addr[20]; 657 int len, bufSize; 658 659 // Initialize the buffer to be empty. 660 buffer[0] = 0; 661 bufSize = 0; 662 663 // Delay all new session creation. 664 beginReading(&sessionData); 665 666 for (s = rootSession; s; s = s->next) 667 if (s->socket != INVALID_SOCKET) 668 { 669 uint8 *client_s_addr = (uint8 *) s->client_s_addr; 670 sprintf(addr, "%d.%d.%d.%d", client_s_addr[0], client_s_addr[1], client_s_addr[2], client_s_addr[3]); 671 len = strlen(buffer); 672 strcpy(&buffer[len > 0 ? len + 1 : 0], addr); 673 bufSize += len + 1; 674 } 675 676 endReading(&sessionData); 677 678 buffer[bufSize++] = 0; 679 return bufSize; 680} 681 682// initMimeMap() 683// 684void initMimeMap() 685{ 686 FILE *fp; 687 bt_mime_mapping *map; 688 char mimeLine[256]; 689 int i, mimeLen; 690 691 fp = fopen("BeServed-MimeMap", "r"); 692 if (fp) 693 { 694 while (fgets(mimeLine, sizeof(mimeLine) - 1, fp)) 695 { 696 // Strip off the carriage return. 697 mimeLine[strlen(mimeLine) - 1] = 0; 698 699 // Create a new MIME map entry. 700 map = (bt_mime_mapping *) malloc(sizeof(bt_mime_mapping)); 701 if (!map) 702 continue; 703 704 map->next = mimeMap; 705 mimeMap = map; 706 707 // Grab the extension. 708 for (i = 0; mimeLine[i] != ' '; i++) 709 map->extension[i] = mimeLine[i]; 710 711 map->extension[i] = 0; 712 713 // Skip to the start of the MIME type. 714 while (mimeLine[i] == ' ') 715 i++; 716 717 // Grab the MIME type. 718 mimeLen = strlen(&mimeLine[i]); 719 map->mimeType = (char *) malloc(mimeLen + 1); 720 if (map->mimeType) 721 strncpy(map->mimeType, &mimeLine[i], mimeLen + 1); 722 } 723 724 fclose(fp); 725 } 726} 727 728void closeMimeMap() 729{ 730 bt_mime_mapping *map = mimeMap; 731 732 while (map) 733 { 734 map = mimeMap->next; 735 free(mimeMap->mimeType); 736 free(mimeMap); 737 mimeMap = map; 738 } 739} 740 741void initShares() 742{ 743 FILE *fp; 744 char buffer[512]; 745 int i, length; 746 747 for (i = 0; i < BT_MAX_FILE_SHARES; i++) 748 { 749 fileShares[i].name[0] = 0; 750 fileShares[i].path[0] = 0; 751 fileShares[i].used = false; 752 fileShares[i].readOnly = true; 753 fileShares[i].security = BT_AUTH_NONE; 754 fileShares[i].rights = NULL; 755 fileShares[i].next = NULL; 756 } 757 758 fp = fopen("BeServed-Settings", "r"); 759 if (fp) 760 { 761 while (fgets(buffer, sizeof(buffer) - 1, fp)) 762 { 763 length = strlen(buffer); 764 if (length <= 1 || buffer[0] == '#') 765 continue; 766 767 if (buffer[length - 1] == '\n') 768 buffer[--length] = 0; 769 770 if (strncmp(buffer, "share ", 6) == 0) 771 getFileShare(buffer); 772 else if (strncmp(buffer, "set ", 4) == 0) 773 getShareProperty(buffer); 774 else if (strncmp(buffer, "grant ", 6) == 0) 775 getGrant(buffer); 776 else if (strncmp(buffer, "authenticate ", 13) == 0) 777 getAuthenticate(buffer); 778 else if (strncmp(buffer, "printer ", 8) == 0) 779 getPrinter(buffer); 780 else if (strcmp(buffer, "preload") == 0) 781 preload = true; 782 } 783 784 fclose(fp); 785 } 786} 787 788void initPrinters() 789{ 790 int i; 791 792 for (i = 0; i < BT_MAX_PRINTER_SHARES; i++) 793 { 794 sharedPrinters[i].printerName[0] = 0; 795 sharedPrinters[i].deviceName[0] = 0; 796 sharedPrinters[i].spoolDir[0] = 0; 797 sharedPrinters[i].rights = NULL; 798 sharedPrinters[i].security = BT_AUTH_NONE; 799 sharedPrinters[i].used = false; 800 sharedPrinters[i].killed = false; 801 } 802} 803 804void loadShares() 805{ 806 int i; 807 808 if (preload) 809 for (i = 0; i < BT_MAX_FILE_SHARES; i++) 810 if (fileShares[i].used) 811 loadFolder(fileShares[i].path); 812} 813 814void getFileShare(const char *buffer) 815{ 816 struct _stat st; 817 char path[B_PATH_NAME_LENGTH], share[MAX_NAME_LENGTH + 1], *folder; 818 int i, tok; 819 820 // Skip over SHARE command. 821 tokPtr = (char *) buffer + (6 * sizeof(char)); 822 823 tok = getToken(); 824 if (tok != BT_TOKEN_STRING) 825 return; 826 827 strcpy(path, tokBuffer); 828 tok = getToken(); 829 if (tok != BT_TOKEN_AS) 830 return; 831 832 tok = getToken(); 833 if (tok != BT_TOKEN_STRING) 834 return; 835 836 strcpy(share, tokBuffer); 837 838 // Now verify that the share name specified has not already been 839 // used to share another path. 840 folder = btGetSharePath(share); 841 if (folder) 842 { 843 winService->LogEvent(EVENTLOG_WARNING_TYPE, EVMSG_DUPLICATE_SHARE, share); 844 return; 845 } 846 847 // Check the path to ensure its validity. 848 if (_stat(path, &st) != 0) 849 { 850 winService->LogEvent(EVENTLOG_WARNING_TYPE, EVMSG_INVALID_SHARE_PATH, path); 851 return; 852 } 853 854 for (i = 0; i < BT_MAX_FILE_SHARES; i++) 855 if (!fileShares[i].used) 856 { 857 strcpy(fileShares[i].name, share); 858 strcpy(fileShares[i].path, path); 859 fileShares[i].used = true; 860 return; 861 } 862 863 winService->LogEvent(EVENTLOG_WARNING_TYPE, EVMSG_TOO_MANY_SHARES, share); 864} 865 866void getShareProperty(const char *buffer) 867{ 868 char share[B_FILE_NAME_LENGTH + 1]; 869 int tok, shareId; 870 871 // Skip over SET command. 872 tokPtr = (char *) buffer + (4 * sizeof(char)); 873 874 tok = getToken(); 875 if (tok != BT_TOKEN_STRING) 876 return; 877 878 strcpy(share, tokBuffer); 879 880 // Get the index of the share referred to. If the named share cannot be 881 // found, then abort. 882 shareId = btGetShareId(share); 883 if (shareId < 0) 884 return; 885 886 tok = getToken(); 887 if (tok == BT_TOKEN_READWRITE) 888 fileShares[shareId].readOnly = false; 889} 890 891void getGrant(const char *buffer) 892{ 893 char share[MAX_NAME_LENGTH + 1]; 894 int tok, rights; 895 bool isGroup = false; 896 897 // Skip over GRANT command. 898 tokPtr = (char *) buffer + (6 * sizeof(char)); 899 rights = 0; 900 901 do 902 { 903 tok = getToken(); 904 if (tok == BT_TOKEN_READ) 905 { 906 rights |= BT_RIGHTS_READ; 907 tok = getToken(); 908 } 909 else if (tok == BT_TOKEN_WRITE) 910 { 911 rights |= BT_RIGHTS_WRITE; 912 tok = getToken(); 913 } 914 else if (tok == BT_TOKEN_PRINT) 915 { 916 rights |= BT_RIGHTS_PRINT; 917 tok = getToken(); 918 } 919 } while (tok == BT_TOKEN_COMMA); 920 921 if (tok != BT_TOKEN_ON) 922 return; 923 924 tok = getToken(); 925 if (tok != BT_TOKEN_STRING) 926 return; 927 928 strcpy(share, tokBuffer); 929 tok = getToken(); 930 if (tok != BT_TOKEN_TO) 931 return; 932 933 tok = getToken(); 934 if (tok == BT_TOKEN_GROUP) 935 { 936 isGroup = true; 937 tok = getToken(); 938 } 939 940 if (tok != BT_TOKEN_STRING) 941 return; 942 943 addUserRights(share, tokBuffer, rights, isGroup); 944} 945 946void getAuthenticate(const char *buffer) 947{ 948 int i, tok; 949 950 // Skip over AUTHENTICATE command. 951 tokPtr = (char *) buffer + (13 * sizeof(char)); 952 953 tok = getToken(); 954 if (tok != BT_TOKEN_WITH) 955 return; 956 957 tok = getToken(); 958 if (tok != BT_TOKEN_STRING) 959 return; 960 961 // Loop up address for given host. 962 getAuthServerAddress(tokBuffer); 963 964 for (i = 0; i < BT_MAX_FILE_SHARES; i++) 965 fileShares[i].security = BT_AUTH_BESURE; 966 967 for (i = 0; i < BT_MAX_PRINTER_SHARES; i++) 968 sharedPrinters[i].security = BT_AUTH_BESURE; 969} 970 971bool getAuthServerAddress(const char *name) 972{ 973 // Look up address for given host. 974 struct hostent *ent = gethostbyname(name); 975 if (ent == NULL) 976 { 977 unsigned long addr = inet_addr(tokBuffer); 978 authServerIP = ntohl(addr); 979 } 980 else 981 authServerIP = ntohl(*((unsigned int *) ent->h_addr)); 982 983 strcpy(authServerName, name); 984 return true; 985} 986 987void addUserRights(char *share, char *user, int rights, bool isGroup) 988{ 989 bt_printer *printer; 990 bt_user_rights *ur; 991 bool isPrinter = false; 992 int shareId; 993 994 // Now make sure that the rights make sense. If we're granting the 995 // right to print, we should not have granted the right to read or write. 996 // We should also be working exclusively with a printer. 997 if (rights & BT_RIGHTS_PRINT) 998 { 999 if (rights & BT_RIGHTS_READ || rights & BT_RIGHTS_WRITE) 1000 return; 1001 1002 printer = btFindPrinter(share); 1003 if (!printer) 1004 return; 1005 1006 isPrinter = true; 1007 } 1008 else 1009 { 1010 shareId = btGetShareId(share); 1011 if (shareId < 0) 1012 return; 1013 } 1014 1015 // Allocate a new user rights structure, populate it, and attach it to 1016 // either a file share or printer. 1017 ur = (bt_user_rights *) malloc(sizeof(bt_user_rights)); 1018 if (ur) 1019 { 1020 ur->user = (char *) malloc(strlen(user) + 1); 1021 if (ur->user) 1022 { 1023 strcpy(ur->user, user); 1024 ur->rights = rights; 1025 ur->isGroup = isGroup; 1026 1027 if (isPrinter) 1028 { 1029 ur->next = printer->rights; 1030 printer->rights = ur; 1031 } 1032 else 1033 { 1034 ur->next = fileShares[shareId].rights; 1035 fileShares[shareId].rights = ur; 1036 } 1037 } 1038 else 1039 free(ur); 1040 } 1041} 1042 1043void getPrinter(const char *buffer) 1044{ 1045 bt_printer printer; 1046 DWORD threadId; 1047 int i, tok; 1048 1049 // Skip over PRINTER command. 1050 tokPtr = (char *) buffer + (8 * sizeof(char)); 1051 1052 // Now get the name this printer will be shared as. 1053 tok = getToken(); 1054 if (tok != BT_TOKEN_STRING) 1055 return; 1056 1057 strcpy(printer.printerName, tokBuffer); 1058 1059 // Bypass the IS and TYPE keywords. 1060 tok = getToken(); 1061 if (tok != BT_TOKEN_IS) 1062 return; 1063 1064 tok = getToken(); 1065 if (tok != BT_TOKEN_TYPE) 1066 return; 1067 1068 // Get the device type of the printer. 1069 tok = getToken(); 1070 if (tok != BT_TOKEN_STRING) 1071 return; 1072 1073 strcpy(printer.deviceType, tokBuffer); 1074 1075 // Bypass the DEVICE keyword. 1076 tok = getToken(); 1077 if (tok != BT_TOKEN_DEVICE) 1078 return; 1079 1080 // Get the system device name of the printer. 1081 tok = getToken(); 1082 if (tok != BT_TOKEN_STRING) 1083 return; 1084 1085 strcpy(printer.deviceName, tokBuffer); 1086 1087 // Bypass the SPOOLED TO keywords. 1088 tok = getToken(); 1089 if (tok != BT_TOKEN_SPOOLED) 1090 return; 1091 1092 tok = getToken(); 1093 if (tok != BT_TOKEN_TO) 1094 return; 1095 1096 // Get the spooling folder, where temporary files will be stored. 1097 tok = getToken(); 1098 if (tok != BT_TOKEN_STRING) 1099 return; 1100 1101 strcpy(printer.spoolDir, tokBuffer); 1102 1103 for (i = 0; i < BT_MAX_PRINTER_SHARES; i++) 1104 if (!sharedPrinters[i].used) 1105 { 1106 sharedPrinters[i].used = true; 1107 strcpy(sharedPrinters[i].printerName, printer.printerName); 1108 strcpy(sharedPrinters[i].deviceType, printer.deviceType); 1109 strcpy(sharedPrinters[i].deviceName, printer.deviceName); 1110 strcpy(sharedPrinters[i].spoolDir, printer.spoolDir); 1111 sharedPrinters[i].handlerID = CreateThread(NULL, 0, printerThread, (void *) &sharedPrinters[i], 0, &threadId); 1112 break; 1113 } 1114} 1115 1116int getToken() 1117{ 1118 bool quoted = false; 1119 1120 tokBuffer[0] = 0; 1121 while (*tokPtr && iswhite(*tokPtr)) 1122 tokPtr++; 1123 1124 if (*tokPtr == ',') 1125 { 1126 *tokPtr++; 1127 return BT_TOKEN_COMMA; 1128 } 1129 else if (*tokPtr == '\"') 1130 { 1131 quoted = true; 1132 tokPtr++; 1133 } 1134 1135 if (isalnum(*tokPtr) || *tokPtr == '\\') 1136 { 1137 int i = 0; 1138 while (isalnum(*tokPtr) || isValid(*tokPtr) || (quoted && *tokPtr == ' ')) 1139 if (i < MAX_NAME_LENGTH) 1140 tokBuffer[i++] = *tokPtr++; 1141 else 1142 tokPtr++; 1143 1144 tokBuffer[i] = 0; 1145 1146 if (!quoted) 1147 for (i = 0; keywords[i]; i++) 1148 if (stricmp(tokBuffer, keywords[i]) == 0) 1149 return ++i; 1150 1151 if (quoted) 1152 if (*tokPtr != '\"') 1153 return BT_TOKEN_ERROR; 1154 else 1155 tokPtr++; 1156 1157 return BT_TOKEN_STRING; 1158 } 1159 1160 return BT_TOKEN_ERROR; 1161} 1162 1163void startService() 1164{ 1165 struct sockaddr_in serverAddr, clientAddr; 1166 int client, addrLen; 1167 char flags; 1168 1169 // Store the length of the socket addressing structure for accept(). 1170 addrLen = sizeof(struct sockaddr_in); 1171 1172 // Initialize the server address structure. 1173 memset(&serverAddr, 0, sizeof(serverAddr)); 1174 serverAddr.sin_port = htons(BT_TCPIP_PORT); 1175 serverAddr.sin_family = AF_INET; 1176 serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); 1177 1178 // Create a new socket to receive incoming requests. 1179 server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 1180 if (server == INVALID_SOCKET) 1181 return; 1182 1183 // Set the socket option to reuse the current address in case it was 1184 // in use by a prior version of the service that has not yet relinquished 1185 // the socket. 1186 flags = 1; 1187 setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags)); 1188 1189 // Bind that socket to the address constructed above. 1190 if (bind(server, (struct sockaddr *) &serverAddr, sizeof(serverAddr))) 1191 return; 1192 1193 // Listen for incoming connections. 1194 if (listen(server, 5)) 1195 return; 1196 1197 // Continually accept incoming connections. When one is found, 1198 // fire off a handler thread to accept commands. 1199 while (running) 1200 { 1201 client = accept(server, (struct sockaddr *) &clientAddr, &addrLen); 1202 if (client != INVALID_SOCKET) 1203 launchThread(client, &clientAddr); 1204 } 1205 1206 // Close the socket. Technically, I believe we should call shutdown() 1207 // first, but the BeOS header file socket.h indicates that this 1208 // function is not currently working. It is present but may not have 1209 // any effect. 1210 shutdown(server, 2); 1211 closesocket(server); 1212 server = INVALID_SOCKET; 1213} 1214 1215void endService(int sig) 1216{ 1217 WSACleanup(); 1218 1219 TerminateThread(hostThread, 0); 1220 closeManagedData(&sessionData); 1221 closeManagedData(&handleData); 1222 1223 closePrinters(); 1224 closeMimeMap(); 1225 freeFileShares(); 1226 1227 ubi_trKillTree(&vnidTree, KillNode); 1228 ubi_trKillTree(&nameTree, KillNode); 1229 1230 signal(SIGINT, SIG_DFL); 1231 signal(SIGTERM, SIG_DFL); 1232} 1233 1234void closePrinters() 1235{ 1236 int i; 1237 1238 // Close down shared printer spooling threads. 1239 for (i = 0; i < BT_MAX_PRINTER_SHARES; i++) 1240 if (sharedPrinters[i].used) 1241 { 1242 sharedPrinters[i].killed = true; 1243 waitForThread(sharedPrinters[i].handlerID); 1244 } 1245} 1246 1247// waitForThread() 1248// 1249void waitForThread(HANDLE threadId) 1250{ 1251 DWORD exitCode; 1252 1253 while (true) 1254 { 1255 // Get the exit code of the thread. If the function fails, the 1256 // thread is invalid and thus already gone. 1257 if (!GetExitCodeThread(threadId, &exitCode)) 1258 break; 1259 1260 // If we have an exit code, the thread isn't running. 1261 if (exitCode != STILL_ACTIVE) 1262 break; 1263 1264 // Otherwise, wait and retry. 1265 Sleep(100); 1266 } 1267} 1268 1269// freeFileShares() 1270// 1271void freeFileShares() 1272{ 1273 bt_user_rights *ur, *nextUr; 1274 int i; 1275 1276 for (i = 0; i < BT_MAX_FILE_SHARES; i++) 1277 for (ur = fileShares[i].rights; ur; ) 1278 { 1279 nextUr = ur->next; 1280 if (ur->user) 1281 free(ur->user); 1282 1283 free(ur); 1284 ur = nextUr; 1285 } 1286} 1287 1288// launchThread() 1289// 1290void launchThread(int client, struct sockaddr_in *addr) 1291{ 1292 bt_session_t *s, *cur, *last = NULL; 1293 DWORD threadId; 1294 int count = 0; 1295 1296 // First verify that the server's not too busy by scanning the list of active 1297 // sessions. This is also useful because we need to eliminate unused sessions 1298 // from the list, i.e., sessions that have closed. 1299 beginWriting(&sessionData); 1300 1301 s = rootSession; 1302 while (s) 1303 { 1304 if (s->socket == INVALID_SOCKET) 1305 { 1306 if (last) 1307 last->next = s->next; 1308 else 1309 rootSession = s->next; 1310 1311 cur = s->next; 1312 free(s); 1313 s = cur; 1314 continue; 1315 } 1316 1317 last = s; 1318 s = s->next; 1319 count++; 1320 } 1321 1322 // If the total number of valid sessions was less than our allowed maximum, then 1323 // we can create a new session. 1324 if (count < BT_MAX_THREADS) 1325 { 1326 // We need to create an available session for this connection. 1327 bt_session_t *session = (bt_session_t *) malloc(sizeof(bt_session_t)); 1328 if (session) 1329 { 1330 session->socket = client; 1331 session->client_s_addr = addr->sin_addr.s_addr; 1332 session->rootBlock = NULL; 1333 session->killed = false; 1334 session->rights = 0; 1335 session->handlerID = CreateThread(NULL, 0, requestThread, (void *) session, 0, &threadId); 1336 1337 // Add this to the session list. 1338 session->next = rootSession; 1339 rootSession = session; 1340 endWriting(&sessionData); 1341 return; 1342 } 1343 } 1344 1345 endWriting(&sessionData); 1346 1347 // We must have too many threads active, so let the client know we're busy. 1348 sendErrorToClient(client, 0, EBUSY); 1349 shutdown(client, 2); 1350 closesocket(client); 1351} 1352 1353DWORD WINAPI requestThread(LPVOID data) 1354{ 1355 bt_session_t *session = (bt_session_t *) data; 1356 1357 if (!session) 1358 return 0; 1359 1360 session->blockSem = CreateSemaphore(NULL, 1, 1, NULL); 1361 if (session->blockSem) 1362 { 1363 session->rootBlock = NULL; 1364 while (!session->killed && receiveRequest(session)); 1365 CloseHandle(session->blockSem); 1366 } 1367 1368 shutdown(session->socket, 2); 1369 closesocket(session->socket); 1370 session->socket = INVALID_SOCKET; 1371 return 0; 1372} 1373 1374int receiveRequest(bt_session_t *session) 1375{ 1376 bt_inPacket packet; 1377 char signature[20], *buffer; 1378 unsigned char command; 1379 int client, sigLen; 1380 int32 length; 1381 1382 client = session->socket; 1383 1384 // Read the BeTalk RPC header. 1385 sigLen = strlen(BT_RPC_SIGNATURE); 1386 if (btRecvMsg(client, signature, sigLen, 0) == -1) 1387 return 0; 1388 1389// recv(client, &verHi, sizeof(verHi), 0); 1390// recv(client, &verLo, sizeof(verLo), 0); 1391 1392 signature[sigLen] = 0; 1393 if (strcmp(signature, BT_RPC_SIGNATURE)) 1394 return 0; 1395 1396 // Read in the rest of the packet. 1397 if (btRecvMsg(client, (char *) &length, sizeof(int32), 0) == -1) 1398 return 0; 1399 1400 length = B_LENDIAN_TO_HOST_INT32(length); 1401 if (length == 0 || length > BT_RPC_MAX_PACKET_SIZE) 1402 return 0; 1403 1404 buffer = (char *) malloc(length + 1); 1405 if (!buffer) 1406 return 0; 1407 1408 if (btRecvMsg(client, buffer, length, 0) == -1) 1409 { 1410 free(buffer); 1411 return 0; 1412 } 1413 1414 buffer[length] = 0; 1415 packet.buffer = buffer; 1416 packet.length = length; 1417 packet.offset = 0; 1418 1419 // Read the transmission ID and command. 1420 command = btRPCGetChar(&packet); 1421 getArguments(session, &packet, command); 1422 free(buffer); 1423 return (command != BT_CMD_QUIT && command != BT_CMD_PREMOUNT); 1424} 1425 1426void getArguments(bt_session_t *session, bt_inPacket *packet, unsigned char command) 1427{ 1428 bt_arg_t args[MAX_COMMAND_ARGS]; 1429 int i, client; 1430 bool error; 1431 unsigned char argc, terminator; 1432 int32 xid; 1433 1434 error = false; 1435 client = session->socket; 1436 argc = btRPCGetChar(packet); 1437 if (argc > MAX_COMMAND_ARGS) 1438 return; 1439 1440 for (i = 0; i < argc && !error; i++) 1441 { 1442 args[i].type = btRPCGetInt32(packet); 1443 args[i].data = btRPCGetNewString(packet); 1444 if (args[i].data == NULL) 1445 error = true; 1446 } 1447 1448 if (!error) 1449 { 1450 xid = btRPCGetInt32(packet); 1451 terminator = btRPCGetChar(packet); 1452 if (terminator == BT_CMD_TERMINATOR) 1453 handleRequest(session, xid, command, argc, args); 1454 } 1455 1456 while (--i >= 0) 1457 free(args[i].data); 1458} 1459 1460void handleRequest(bt_session_t *session, unsigned int xid, unsigned char command, int argc, bt_arg_t argv[]) 1461{ 1462 bool validated = true; 1463 int i, j; 1464 1465 for (i = 0; dirCommands[i].handler; i++) 1466 if (command == dirCommands[i].command) 1467 { 1468 // We may have received a valid command, but one that is not supported by this 1469 // server. In this case, we'll want to return an operation not supported error, 1470 // as opposed to an invalid command error. 1471 if (!dirCommands[i].supported) 1472 { 1473 sendErrorToClient(session->socket, xid, ENOTSUP); 1474 return; 1475 } 1476 1477 // Now verify that the argument count is correct, and if so, the type of all 1478 // arguments is correct. If not, an invalid command error is returned. 1479 // Otherise, the command is executed, and the handler returns any necessary 1480 // acknowledgement. 1481 if (argc == dirCommands[i].args) 1482 { 1483 for (j = 0; j < argc; j++) 1484 if (dirCommands[i].argTypes[j] != argv[j].type) 1485 { 1486 validated = false; 1487 break; 1488 } 1489 1490 if (validated) 1491 { 1492 (*dirCommands[i].handler)(session, xid, argc, argv); 1493 return; 1494 } 1495 } 1496 } 1497 1498 sendErrorToClient(session->socket, xid, EINVAL); 1499} 1500 1501void sendErrorToClient(int client, unsigned int xid, int error) 1502{ 1503 bt_outPacket packet; 1504 btRPCCreateAck(&packet, xid, error); 1505 btRPCSendAck(client, &packet); 1506} 1507 1508// btRecvMsg() 1509// 1510int btRecvMsg(int sock, void *data, int dataLen, int flags) 1511{ 1512 int bytesRead = 0; 1513 do 1514 { 1515 int bytes = btRecv(sock, (char *) data + bytesRead, dataLen - bytesRead, flags); 1516 if (bytes == -1) 1517 return -1; 1518 1519 bytesRead += bytes; 1520 } while (bytesRead < dataLen); 1521 1522 return bytesRead; 1523} 1524 1525// btRecv() 1526// 1527int btRecv(int sock, void *data, int dataLen, int flags) 1528{ 1529 int bytes; 1530 1531 for (;;) 1532 { 1533 bytes = recv(sock, (char *) data, dataLen, flags); 1534 if (bytes == 0) 1535 return -1; 1536 else if (bytes == -1) 1537 if (errno == EINTR) 1538 continue; 1539 else 1540 return -1; 1541 else 1542 break; 1543 } 1544 1545 return bytes; 1546} 1547 1548// btSendMsg() 1549// 1550int btSendMsg(int sock, void *data, int dataLen, int flags) 1551{ 1552 int bytesSent = 0; 1553 do 1554 { 1555 int bytes = btSend(sock, (char *) data + bytesSent, dataLen - bytesSent, flags); 1556 if (bytes == -1) 1557 return -1; 1558 1559 bytesSent += bytes; 1560 } while (bytesSent < dataLen); 1561 1562 return bytesSent; 1563} 1564 1565// btSend() 1566// 1567int btSend(int sock, void *data, int dataLen, int flags) 1568{ 1569 int bytes; 1570 1571 for (;;) 1572 { 1573 bytes = send(sock, (char *) data, dataLen, flags); 1574 if (bytes == -1) 1575 if (errno == EINTR) 1576 continue; 1577 else 1578 return -1; 1579 else 1580 break; 1581 } 1582 1583 return bytes; 1584} 1585 1586uint32 btSwapInt32(uint32 num) 1587{ 1588 uint8 byte; 1589 union 1590 { 1591 uint32 value; 1592 uint8 bytes[4]; 1593 } convert; 1594 1595 convert.value = num; 1596 byte = convert.bytes[0]; 1597 convert.bytes[0] = convert.bytes[3]; 1598 convert.bytes[3] = byte; 1599 byte = convert.bytes[1]; 1600 convert.bytes[1] = convert.bytes[2]; 1601 convert.bytes[2] = byte; 1602 return convert.value; 1603} 1604 1605uint64 btSwapInt64(uint64 num) 1606{ 1607 uint8 byte; 1608 union 1609 { 1610 uint64 value; 1611 uint8 bytes[8]; 1612 } convert; 1613 1614 convert.value = num; 1615 byte = convert.bytes[0]; 1616 convert.bytes[0] = convert.bytes[7]; 1617 convert.bytes[7] = byte; 1618 byte = convert.bytes[1]; 1619 convert.bytes[1] = convert.bytes[6]; 1620 convert.bytes[6] = byte; 1621 byte = convert.bytes[2]; 1622 convert.bytes[2] = convert.bytes[5]; 1623 convert.bytes[5] = byte; 1624 byte = convert.bytes[3]; 1625 convert.bytes[3] = convert.bytes[4]; 1626 convert.bytes[4] = byte; 1627 return convert.value; 1628} 1629 1630void btRPCCreateAck(bt_outPacket *packet, unsigned int xid, int error) 1631{ 1632 packet->size = BT_RPC_MIN_PACKET_SIZE; 1633 packet->buffer = (char *) malloc(packet->size); 1634 packet->length = 0; 1635 1636 if (!packet->buffer) 1637 return; 1638 1639 strcpy(packet->buffer, BT_RPC_SIGNATURE); 1640 packet->length += strlen(BT_RPC_SIGNATURE); 1641 btRPCPutInt32(packet, xid); 1642 btRPCPutInt32(packet, 0); 1643 btRPCPutInt32(packet, error); 1644} 1645 1646void btRPCSendAck(int client, bt_outPacket *packet) 1647{ 1648 if (packet) 1649 if (packet->buffer) 1650 { 1651 *(int32 *)(&packet->buffer[9]) = B_HOST_TO_LENDIAN_INT32(packet->length - 13); 1652 btSendMsg(client, packet->buffer, packet->length, 0); 1653 free(packet->buffer); 1654 } 1655} 1656 1657unsigned char btRPCGetChar(bt_inPacket *packet) 1658{ 1659 unsigned char value; 1660 1661 if (packet->offset < packet->length) 1662 value = (unsigned char) packet->buffer[packet->offset]; 1663 else 1664 value = 0; 1665 1666 packet->offset += sizeof(value); 1667 return value; 1668} 1669 1670unsigned int btRPCGetInt32(bt_inPacket *packet) 1671{ 1672 int32 value; 1673 1674 if (packet->offset < packet->length) 1675 value = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); 1676 else 1677 value = 0; 1678 1679 packet->offset += sizeof(value); 1680 return value; 1681} 1682 1683int64 btRPCGetInt64(bt_inPacket *packet) 1684{ 1685 int64 value; 1686 1687 if (packet->offset < packet->length) 1688 value = B_LENDIAN_TO_HOST_INT64(*((int64 *) &packet->buffer[packet->offset])); 1689 else 1690 value = 0; 1691 1692 packet->offset += sizeof(value); 1693 return value; 1694} 1695 1696char *btRPCGetNewString(bt_inPacket *packet) 1697{ 1698 char *str; 1699 unsigned int bytes; 1700 1701 if (packet->offset >= packet->length) 1702 return NULL; 1703 1704 bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); 1705 packet->offset += sizeof(bytes); 1706 if (bytes < 0 || bytes > BT_MAX_IO_BUFFER) 1707 return NULL; 1708 1709 str = (char *) malloc(bytes + 1); 1710 if (!str) 1711 return NULL; 1712 1713 if (bytes > 0) 1714 memcpy(str, &packet->buffer[packet->offset], bytes); 1715 1716 str[bytes] = 0; 1717 packet->offset += bytes; 1718 1719 return str; 1720} 1721 1722int btRPCGetString(bt_inPacket *packet, char *buffer, int length) 1723{ 1724 unsigned int bytes; 1725 1726 if (packet->offset >= packet->length) 1727 return ERANGE; 1728 1729 bytes = B_LENDIAN_TO_HOST_INT32(*((int32 *) &packet->buffer[packet->offset])); 1730 packet->offset += sizeof(bytes); 1731 if (bytes < 0 || bytes > BT_MAX_IO_BUFFER) 1732 return ERANGE; 1733 1734 if (length < bytes) 1735 return ERANGE; 1736 1737 if (bytes > 0) 1738 memcpy(buffer, &packet->buffer[packet->offset], bytes); 1739 1740 packet->offset += bytes; 1741 return bytes; 1742} 1743 1744void btRPCGrowPacket(bt_outPacket *packet, int bytes) 1745{ 1746 if (packet->length + bytes > packet->size) 1747 { 1748 int growth = ((bytes / BT_RPC_MIN_PACKET_SIZE) + 1) * BT_RPC_MIN_PACKET_SIZE; 1749 packet->buffer = (char *) realloc(packet->buffer, packet->size + growth); 1750 packet->size += growth; 1751 } 1752} 1753 1754void btRPCPutChar(bt_outPacket *packet, char value) 1755{ 1756 btRPCGrowPacket(packet, sizeof(value)); 1757 packet->buffer[packet->length] = value; 1758 packet->length += sizeof(value); 1759} 1760 1761void btRPCPutInt32(bt_outPacket *packet, int32 value) 1762{ 1763 btRPCGrowPacket(packet, sizeof(value)); 1764 *(int32 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT32(value); 1765 packet->length += sizeof(value); 1766} 1767 1768void btRPCPutInt64(bt_outPacket *packet, int64 value) 1769{ 1770 btRPCGrowPacket(packet, sizeof(value)); 1771 *(int64 *)(&packet->buffer[packet->length]) = B_HOST_TO_LENDIAN_INT64(value); 1772 packet->length += sizeof(value); 1773} 1774 1775void btRPCPutString(bt_outPacket *packet, char *buffer, int length) 1776{ 1777 if (packet && buffer) 1778 { 1779 btRPCGrowPacket(packet, sizeof(length) + length); 1780 btRPCPutInt32(packet, length); 1781 memcpy(&packet->buffer[packet->length], buffer, length); 1782 packet->length += length; 1783 } 1784} 1785 1786void btRPCPutBinary(bt_outPacket *packet, void *buffer, int length) 1787{ 1788 if (packet && buffer) 1789 { 1790 btRPCGrowPacket(packet, length); 1791 memcpy(&packet->buffer[packet->length], buffer, length); 1792 packet->length += length; 1793 } 1794} 1795 1796void btRPCGetStat(bt_inPacket *packet, beos_stat *st) 1797{ 1798 st->st_dev = 0; 1799 st->st_nlink = btRPCGetInt32(packet); 1800 st->st_uid = btRPCGetInt32(packet); 1801 st->st_gid = btRPCGetInt32(packet); 1802 st->st_size = (int32) btRPCGetInt64(packet); 1803 st->st_blksize = btRPCGetInt32(packet); 1804 st->st_rdev = btRPCGetInt32(packet); 1805 st->st_ino = (int32) btRPCGetInt64(packet); 1806 st->st_mode = btRPCGetInt32(packet); 1807 st->st_atime = btRPCGetInt32(packet); 1808 st->st_mtime = btRPCGetInt32(packet); 1809 st->st_ctime = btRPCGetInt32(packet); 1810} 1811 1812void btRPCPutStat(bt_outPacket *packet, beos_stat *st) 1813{ 1814 if (packet && st) 1815 { 1816 int64 size = (int64) st->st_size; 1817 int64 inode = (int64) st->st_ino; 1818 1819 btRPCPutInt32(packet, (int) st->st_nlink); 1820 btRPCPutInt32(packet, (int) st->st_uid); 1821 btRPCPutInt32(packet, (int) st->st_gid); 1822 btRPCPutInt64(packet, size); 1823 btRPCPutInt32(packet, (int) 1024); 1824 btRPCPutInt32(packet, (int) st->st_rdev); 1825 btRPCPutInt64(packet, inode); 1826 btRPCPutInt32(packet, (int) st->st_mode); 1827 btRPCPutInt32(packet, (int) st->st_atime); 1828 btRPCPutInt32(packet, (int) st->st_mtime); 1829 btRPCPutInt32(packet, (int) st->st_ctime); 1830 } 1831} 1832 1833//////////////////////////////////////////////////////////////////// 1834 1835bt_node *btGetNodeFromVnid(vnode_id vnid) 1836{ 1837 return (bt_node *) ubi_trFind(&vnidTree, &vnid); 1838} 1839 1840// btAddHandle() 1841// 1842void btAddHandle(vnode_id dir_vnid, vnode_id file_vnid, char *name) 1843{ 1844 bt_node *vnidNode, *nameNode, *dirNode; 1845 1846 // We don't store the references to the current and the parent directory. 1847 if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) 1848 return; 1849 1850 beginWriting(&handleData); 1851 1852 // Obtain the parent node. If no parent vnid is provided, then this must be 1853 // the root node. The parent of the root node is NULL, but it should be the 1854 // only node for which this is true. 1855 if (dir_vnid) 1856 dirNode = btGetNodeFromVnid(dir_vnid); 1857 else 1858 dirNode = NULL; 1859 1860 // If a node already exists with the given vnid, then it is either a symbolic 1861 // link or an attempt to add the same node again, such as when mounting or 1862 // walking a directory tree. If we find a matching vnid whose parent directory 1863 // and name also match, this is a duplicate and can be ignored. 1864 if (btGetNodeFromVnid(file_vnid)) 1865 { 1866 endWriting(&handleData); 1867 return; 1868 } 1869 1870 // Allocate a new node for the vnid and name-based trees. A separate node must exist for 1871 // each tree or the tree structure will go haywire. 1872 vnidNode = (bt_node *) malloc(sizeof(bt_node)); 1873 if (vnidNode == NULL) 1874 { 1875 endWriting(&handleData); 1876 return; 1877 } 1878 1879 nameNode = (bt_node *) malloc(sizeof(bt_node)); 1880 if (nameNode == NULL) 1881 { 1882 free(vnidNode); 1883 endWriting(&handleData); 1884 return; 1885 } 1886 1887 // Allocate memory for the file name itself. This prevents huge memory consumption used by 1888 // a static buffer that assumes the worst case file name length. 1889 vnidNode->name = (char *) malloc(strlen(name) + 1); 1890 if (vnidNode->name == NULL) 1891 { 1892 free(nameNode); 1893 free(vnidNode); 1894 endWriting(&handleData); 1895 return; 1896 } 1897 1898 // Copy the name into the allocated buffer. 1899 strcpy(vnidNode->name, name); 1900 1901 nameNode->name = strdup(vnidNode->name); 1902 if (nameNode->name == NULL) 1903 { 1904 free(vnidNode->name); 1905 free(nameNode); 1906 free(vnidNode); 1907 endWriting(&handleData); 1908 return; 1909 } 1910 1911 // Copy over the vnid, and parent node. 1912 vnidNode->invalid = nameNode->invalid = false; 1913 vnidNode->vnid = nameNode->vnid = file_vnid; 1914 vnidNode->parent = nameNode->parent = dirNode; 1915 1916 // Now insert the new nodes into the tree. 1917 ubi_trInsert(&vnidTree, vnidNode, &vnidNode->vnid, NULL); 1918 ubi_trInsert(&nameTree, nameNode, nameNode, NULL); 1919 1920 endWriting(&handleData); 1921} 1922 1923// btRemoveHandle() 1924// 1925void btRemoveHandle(vnode_id vnid) 1926{ 1927 bt_node *deadVnidNode, *deadNameNode; 1928 1929 beginWriting(&handleData); 1930 1931 deadVnidNode = (bt_node *) ubi_trFind(&vnidTree, &vnid); 1932 if (deadVnidNode) 1933 { 1934 ubi_trRemove(&vnidTree, deadVnidNode); 1935 1936 deadNameNode = (bt_node *) ubi_trFind(&nameTree, deadVnidNode); 1937 if (deadNameNode) 1938 ubi_trRemove(&nameTree, deadNameNode); 1939 } 1940 1941 endWriting(&handleData); 1942} 1943 1944// btPurgeNodes() 1945// 1946void btPurgeNodes(vnode_id vnid) 1947{ 1948 bt_node *curNode; 1949 ubi_trNodePtr cur, next; 1950 ubi_trRootPtr tree; 1951 ubi_trRootPtr trees[] = { &vnidTree, &nameTree, NULL }; 1952 int i; 1953 1954 beginWriting(&handleData); 1955 1956 // First loop through, marking this node and all its children as invalid. 1957 for (i = 0, tree = trees[i]; trees[i]; i++) 1958 { 1959 cur = ubi_trFirst(tree->root); 1960 while (cur) 1961 { 1962 next = ubi_trNext(cur); 1963 1964 curNode = (bt_node *) cur; 1965 if (curNode->vnid == vnid || btIsAncestorNode(vnid, curNode)) 1966 curNode->invalid = true; 1967 1968 cur = next; 1969 } 1970 1971 // Now loop through again, removing all invalid nodes. This prevents removing 1972 // a parent node and all its children being orphaned (with invalid pointers 1973 // back to the destroyed parent). 1974 cur = ubi_trFirst(tree->root); 1975 while (cur) 1976 { 1977 next = ubi_trNext(cur); 1978 1979 curNode = (bt_node *) cur; 1980 if (curNode->invalid) 1981 { 1982 ubi_trRemove(&vnidTree, curNode); 1983 free(curNode); 1984 } 1985 1986 cur = next; 1987 } 1988 } 1989 1990 endWriting(&handleData); 1991} 1992 1993// btIsAncestorNode() 1994// 1995bool btIsAncestorNode(vnode_id vnid, bt_node *node) 1996{ 1997 bt_node *curNode = node->parent; 1998 1999 while (curNode) 2000 { 2001 if (curNode->vnid == vnid) 2002 return true; 2003 2004 curNode = curNode->parent; 2005 } 2006 2007 return false; 2008} 2009 2010// btGetLocalFileName() 2011// 2012char *btGetLocalFileName(char *path, vnode_id vnid) 2013{ 2014 bt_node *node, *nodeStack[100]; 2015 int stackSize; 2016 2017 path[0] = 0; 2018 stackSize = 1; 2019 2020 beginReading(&handleData); 2021 2022 node = btGetNodeFromVnid(vnid); 2023 if (node == NULL) 2024 { 2025 endReading(&handleData); 2026 return NULL; 2027 } 2028 2029 nodeStack[0] = node; 2030 while ((node = node->parent) != NULL) 2031 nodeStack[stackSize++] = node; 2032 2033 while (--stackSize >= 0) 2034 { 2035 strcat(path, nodeStack[stackSize]->name); 2036 if (stackSize) 2037 { 2038 int length = strlen(path); 2039 if (length > 0 && path[length - 1] != '\\') 2040 strcat(path, "\\"); 2041 } 2042 } 2043 2044 endReading(&handleData); 2045 return path; 2046} 2047 2048bt_node *btFindNode(bt_node *parent, char *fileName) 2049{ 2050 bt_node search, *node; 2051 2052 // Initialize the node for tree searching purposes. 2053 search.parent = parent; 2054 search.name = strdup(fileName); 2055 if (search.name == NULL) 2056 return NULL; 2057 2058 beginReading(&handleData); 2059 node = (bt_node *) ubi_trFind(&nameTree, &search); 2060 endReading(&handleData); 2061 2062 free(search.name); 2063 return node; 2064} 2065 2066char *btGetSharePath(char *shareName) 2067{ 2068 int i; 2069 2070 for (i = 0; i < BT_MAX_FILE_SHARES; i++) 2071 if (fileShares[i].used) 2072 if (stricmp(fileShares[i].name, shareName) == 0) 2073 return fileShares[i].path; 2074 2075 return NULL; 2076} 2077 2078int btGetShareId(char *shareName) 2079{ 2080 int i; 2081 2082 for (i = 0; i < BT_MAX_FILE_SHARES; i++) 2083 if (fileShares[i].used) 2084 if (stricmp(fileShares[i].name, shareName) == 0) 2085 return i; 2086 2087 return -1; 2088} 2089 2090int btGetShareIdByPath(char *path) 2091{ 2092 int i; 2093 2094 for (i = 0; i < BT_MAX_FILE_SHARES; i++) 2095 if (fileShares[i].used) 2096 if (stricmp(fileShares[i].path, path) == 0) 2097 return i; 2098 2099 return -1; 2100} 2101 2102// btFindPrinter() 2103// 2104bt_printer *btFindPrinter(char *printerName) 2105{ 2106 int i; 2107 2108 for (i = 0; i < BT_MAX_PRINTER_SHARES; i++) 2109 if (sharedPrinters[i].used) 2110 if (stricmp(printerName, sharedPrinters[i].printerName) == 0) 2111 return &sharedPrinters[i]; 2112 2113 return NULL; 2114} 2115 2116void btGetRootPath(vnode_id vnid, char *path) 2117{ 2118 bt_node *curNode; 2119 2120 beginReading(&handleData); 2121 2122 curNode = btGetNodeFromVnid(vnid); 2123 while (curNode && curNode->parent) 2124 curNode = curNode->parent; 2125 2126 if (curNode) 2127 strcpy(path, curNode->name); 2128 else 2129 path[0] = 0; 2130 2131 endReading(&handleData); 2132} 2133 2134uint32 btGetWinInode(const char *path) 2135{ 2136 const int MAX_FOLDER_NESTING = 100; 2137 char *folders[MAX_FOLDER_NESTING + 1]; 2138 char newPath[B_PATH_NAME_LENGTH + 1]; 2139 int i, level, len, charSum; 2140 2141 // Subdivide the path into its components. 2142 char *p, *s = strdup(path); 2143 level = 0; 2144 folders[level++] = s; 2145 for (p = s; *p; p++) 2146 if (*p == '\\') 2147 { 2148 folders[level++] = p + 1; 2149 *p = 0; 2150 } 2151 2152 folders[level] = 0; 2153 2154 // Now look through the folders, to see if any are . and .. references. 2155 for (i = 0; i < level; i++) 2156 if (*folders[i]) 2157 if (strcmp(folders[i], ".") == 0) 2158 folders[i] = NULL; 2159 else if (strcmp(folders[i], "..") == 0) 2160 { 2161 int j = i; 2162 folders[i] = 0; 2163 while (j > 0 && folders[j] == NULL) 2164 j--; 2165 2166 if (j >= 0) 2167 folders[j] = 0; 2168 } 2169 2170 // Now reconstruct the path without the folders eliminated above. 2171 newPath[0] = 0; 2172 for (i = 0; i < level; i++) 2173 if (folders[i]) 2174 { 2175 strcat(newPath, folders[i]); 2176 if (i < level - 1) 2177 strcat(newPath, "\\"); 2178 } 2179 2180 // If we eliminated folders at the end of the path, the level will have 2181 // resulted in a trailing backslash. 2182 len = strlen(newPath); 2183 if (newPath[len - 1] == '\\') 2184 newPath[--len] = 0; 2185 2186 // Now compute the checksum, i.e., inode number, using the revised path. 2187 free(s); 2188 p = newPath; 2189 for (charSum = len = 0; *p; p++, len++) 2190 charSum += (*p * len); 2191 2192 return ((len << 24) + charSum); 2193} 2194 2195int btGetBeosStat(char *fileName, beos_stat *st) 2196{ 2197 struct _stat _st; 2198 2199 if (_stat(fileName, &_st) != 0) 2200 return BEOS_ENOENT; 2201 2202 st->st_atime = _st.st_atime; 2203 st->st_blksize = 1024; 2204 st->st_ctime = _st.st_ctime; 2205 st->st_dev = 0; 2206 st->st_gid = 0; 2207 st->st_uid = 0; 2208 st->st_ino = btGetWinInode(fileName); 2209 st->st_mode = _st.st_mode; 2210 st->st_mtime = _st.st_mtime; 2211 st->st_nlink = 0; 2212 st->st_rdev = 0; 2213 st->st_size = _st.st_size; 2214 2215 return B_OK; 2216} 2217 2218void btMakePath(char *path, char *dir, char *file) 2219{ 2220 int length; 2221 2222 strcpy(path, dir); 2223 length = strlen(path); 2224 if (length > 0) 2225 if (path[length - 1] != '\\') 2226 strcat(path, "\\"); 2227 2228 strcat(path, file); 2229} 2230 2231//////////////////////////////////////////////////////////////////// 2232 2233int btPreMount(bt_session_t *session, char *shareName) 2234{ 2235 // Look for the specified share name. If it can't be found, check to see if it's 2236 // a printer. If not, then there is no such resource available on this host. 2237 int shareId = btGetShareId(shareName); 2238 if (shareId < 0) 2239 { 2240 bt_printer *printer = btFindPrinter(shareName); 2241 if (!printer) 2242 return BEOS_ENOENT; 2243 2244 return printer->security; 2245 } 2246 2247 return fileShares[shareId].security; 2248} 2249 2250int btMount(bt_session_t *session, char *shareName, char *user, char *password, vnode_id *vnid) 2251{ 2252 bt_user_rights *ur; 2253 struct stat st; 2254 char *path, *groups[MAX_GROUPS_PER_USER]; 2255 int i, shareId; 2256 bool authenticated = false; 2257 2258 // Initialize the groups array. We may need to release the memory later. 2259 for (i = 0; i < MAX_GROUPS_PER_USER; i++) 2260 groups[i] = NULL; 2261 2262 // Look for the specified share name. If it can't be found, it must no longer be 2263 // shared on this host. 2264 shareId = btGetShareId(shareName); 2265 if (shareId < 0) 2266 return BEOS_ENOENT; 2267 2268 if (fileShares[shareId].security != BT_AUTH_NONE) 2269 { 2270 // Authenticate the user with name/password. 2271 authenticated = authenticateUser(user, password); 2272 if (!authenticated) 2273 return BEOS_EACCES; 2274 2275 // Does the authenticated user have any rights on this file share? 2276 session->rights = 0; 2277 for (ur = fileShares[shareId].rights; ur; ur = ur->next) 2278 if (!ur->isGroup && stricmp(ur->user, user) == 0) 2279 session->rights |= ur->rights; 2280 2281 getUserGroups(user, groups); 2282 for (ur = fileShares[shareId].rights; ur; ur = ur->next) 2283 if (ur->isGroup) 2284 for (i = 0; i < MAX_GROUPS_PER_USER; i++) 2285 if (groups[i] && stricmp(ur->user, groups[i]) == 0) 2286 { 2287 session->rights |= ur->rights; 2288 break; 2289 } 2290 2291 // Free the memory occupied by the group list. 2292 for (i = 0; i < MAX_GROUPS_PER_USER; i++) 2293 if (groups[i]) 2294 free(groups[i]); 2295 2296 // If no rights have been granted, deny access. 2297 if (session->rights == 0) 2298 return BEOS_EACCES; 2299 2300 // If write access has been globally disabled, this user's rights must be 2301 // correspondingly synchronized. 2302 if (fileShares[shareId].readOnly) 2303 session->rights = BT_RIGHTS_READ; 2304 } 2305 else 2306 session->rights = fileShares[shareId].readOnly 2307 ? BT_RIGHTS_READ 2308 : BT_RIGHTS_READ | BT_RIGHTS_WRITE; 2309 2310 // Make sure the folder we want to share still exists. 2311 path = fileShares[shareId].path; 2312 if (stat(path, &st) != 0) 2313 return BEOS_ENOENT; 2314 2315 if (!S_ISDIR(st.st_mode)) 2316 return BEOS_EACCES; 2317 2318 // Mark this session as owned by this user. 2319 strcpy(session->user, user); 2320 return B_OK; 2321} 2322 2323int btGetFSInfo(fs_info *fsInfo, char *path) 2324{ 2325 DWORD secsPerClstr, bytesPerSec, freeClstrs, totalClstrs; 2326 char rootDir[5]; 2327 2328 // We only want the root directory specification, not the entire path. 2329 strncpy(rootDir, path, 3); 2330 rootDir[3] = 0; 2331 2332 if (GetDiskFreeSpace(rootDir, &secsPerClstr, &bytesPerSec, &freeClstrs, &totalClstrs)) 2333 { 2334 fsInfo->block_size = bytesPerSec; 2335 fsInfo->total_blocks = secsPerClstr * totalClstrs; 2336 fsInfo->free_blocks = secsPerClstr * freeClstrs; 2337 return B_OK; 2338 } 2339 2340 return ENOTSUP; 2341} 2342 2343int btLookup(char *pathBuf, vnode_id dir_vnid, char *fileName, vnode_id *file_vnid) 2344{ 2345 struct _stat st; 2346 if (_stat(fileName, &st) != 0) 2347 return BEOS_ENOENT; 2348 2349 return B_OK; 2350} 2351 2352int btStat(char *pathBuf, vnode_id vnid, beos_stat *st) 2353{ 2354 char *fileName; 2355 int error; 2356 2357 fileName = btGetLocalFileName(pathBuf, vnid); 2358 if (fileName) 2359 { 2360 error = btGetBeosStat(fileName, st); 2361 return error; 2362 } 2363 2364 return BEOS_ENOENT; 2365} 2366 2367int btReadDir(char *pathBuf, vnode_id dir_vnid, long **dir, vnode_id *file_vnid, char *filename, beos_stat *st) 2368{ 2369 struct _finddata_t fileInfo; 2370 char *folder, path[B_PATH_NAME_LENGTH]; 2371 long result = -1; 2372 2373 if (dir_vnid == 0 || !file_vnid || !filename) 2374 return EINVAL; 2375 2376 if (!*dir) 2377 { 2378 folder = btGetLocalFileName(pathBuf, dir_vnid); 2379 if (folder) 2380 { 2381 char search[B_PATH_NAME_LENGTH]; 2382 btMakePath(search, folder, "*.*"); 2383 result = _findfirst(search, &fileInfo); 2384 *dir = (long *) malloc(sizeof(long *)); 2385 memcpy(*dir, &result, sizeof(result)); 2386 } 2387 } 2388 else 2389 result = _findnext((long) **dir, &fileInfo); 2390 2391 if (result != -1) 2392 { 2393 folder = btGetLocalFileName(pathBuf, dir_vnid); 2394 if (folder) 2395 { 2396 btMakePath(path, folder, fileInfo.name); 2397 if (btGetBeosStat(path, st) != 0) 2398 return BEOS_ENOENT; 2399 2400 strcpy(filename, fileInfo.name); 2401 *file_vnid = (vnode_id) st->st_ino; 2402 btAddHandle(dir_vnid, *file_vnid, filename); 2403 return B_OK; 2404 } 2405 } 2406 else if (*dir) 2407 { 2408 _findclose((long) **dir); 2409 return BEOS_ENOENT; 2410 } 2411 2412 return EINVAL; 2413} 2414 2415int32 btRead(char *pathBuf, vnode_id vnid, beos_off_t pos, int32 len, char *buffer) 2416{ 2417 char *path; 2418 int bytes; 2419 2420 path = btGetLocalFileName(pathBuf, vnid); 2421 if (path) 2422 { 2423 FILE *fp = fopen(path, "rb"); 2424 if (!fp) 2425 return EACCES; 2426 2427 fseek(fp, (int) pos, SEEK_SET); 2428 bytes = fread(buffer, 1, len, fp); 2429 fclose(fp); 2430 2431 buffer[bytes] = 0; 2432 return bytes; 2433 } 2434 2435 return 0; 2436} 2437 2438int32 btWrite(bt_session_t *session, vnode_id vnid, beos_off_t pos, int32 len, int32 totalLen, char *buffer) 2439{ 2440 bt_block *block; 2441 2442 // If we've been given a total length, then we have a new buffered write 2443 // session coming. A block will need to be allocated. 2444 if (totalLen > 0) 2445 { 2446 // Make sure we don't have a wildly inaccurate total length to allocate. 2447 if (totalLen > 10 * 1024 * 1024) 2448 return 0; 2449 2450 // Allocate a new buffered I/O block. 2451 block = (bt_block *) malloc(sizeof(bt_block)); 2452 if (block) 2453 { 2454 block->vnid = vnid; 2455 block->pos = pos; 2456 block->len = totalLen; 2457 block->count = 0; 2458 2459 block->buffer = (char *) malloc(totalLen + 1); 2460 if (!block->buffer) 2461 { 2462 free(block); 2463 return 0; 2464 } 2465 2466 btInsertWriteBlock(session, block); 2467 } 2468 else 2469 return 0; 2470 } 2471 else 2472 { 2473 block = btGetWriteBlock(session, vnid); 2474 if (!block) 2475 return 0; 2476 } 2477 2478 memcpy(block->buffer + block->count, buffer, len); 2479 block->count += len; 2480 return len; 2481} 2482 2483// btGetWriteBlock() 2484// 2485bt_block *btGetWriteBlock(bt_session_t *session, vnode_id vnid) 2486{ 2487 bt_block *block; 2488 2489 WaitForSingleObject(session->blockSem, INFINITE); 2490 2491 block = session->rootBlock; 2492 while (block && block->vnid != vnid) 2493 block = block->next; 2494 2495 ReleaseSemaphore(session->blockSem, 1, NULL); 2496 return block; 2497} 2498 2499// btInsertWriteBlock() 2500// 2501void btInsertWriteBlock(bt_session_t *session, bt_block *block) 2502{ 2503 WaitForSingleObject(session->blockSem, INFINITE); 2504 2505 block->next = session->rootBlock; 2506 block->prev = NULL; 2507 if (session->rootBlock) 2508 session->rootBlock->prev = block; 2509 2510 session->rootBlock = block; 2511 2512 ReleaseSemaphore(session->blockSem, 1, NULL); 2513} 2514 2515int btCommit(bt_session_t *session, vnode_id vnid) 2516{ 2517 bt_block *block; 2518 char *path; 2519 int file; 2520 2521 // Get the full path for the specified file. 2522 path = btGetLocalFileName(session->pathBuffer, vnid); 2523 if (!path) 2524 return BEOS_ENOENT; 2525 2526 // Obtain the buffered I/O block. If one can't be found, no buffered I/O 2527 // session was started for this vnode. 2528 block = btGetWriteBlock(session, vnid); 2529 if (!block) 2530 return BEOS_ENOENT; 2531 2532 // Open the file for writing. 2533 file = _open(path, _O_WRONLY | _O_CREAT | _O_BINARY); 2534 if (file < 0) 2535 return errno; 2536 2537 WaitForSingleObject(session->blockSem, INFINITE); 2538 2539 // Write the data. 2540 _lseek(file, (int32) block->pos, SEEK_SET); 2541 _write(file, block->buffer, block->len); 2542 2543 btRemoveWriteBlock(session, block); 2544 ReleaseSemaphore(session->blockSem, 1, NULL); 2545 2546 _close(file); 2547 return B_OK; 2548} 2549 2550void btRemoveWriteBlock(bt_session_t *session, bt_block *block) 2551{ 2552 // If we're removing the root, then adjust the root block pointer. 2553 if (session->rootBlock == block) 2554 session->rootBlock = block->next; 2555 2556 // If there's a previous block, it should now point beyond this block. 2557 if (block->prev) 2558 block->prev->next = block->next; 2559 2560 // If there's a next block, it hsould now point to the current predecessor. 2561 if (block->next) 2562 block->next->prev = block->prev; 2563 2564 // Release the memory used by this block. 2565 free(block->buffer); 2566 free(block); 2567} 2568 2569int btCreate(char *pathBuf, vnode_id dir_vnid, char *name, int omode, int perms, vnode_id *file_vnid) 2570{ 2571 beos_stat st; 2572 char path[B_PATH_NAME_LENGTH], *folder; 2573 int fh; 2574 2575 folder = btGetLocalFileName(pathBuf, dir_vnid); 2576 if (folder) 2577 { 2578 btMakePath(path, folder, name); 2579 fh = open(path, O_WRONLY | O_CREAT | O_TRUNC, _S_IREAD | _S_IWRITE); 2580 if (fh == -1) 2581 return errno; 2582 else 2583 { 2584 close(fh); 2585 if (btGetBeosStat(path, &st) == 0) 2586 { 2587 *file_vnid = (vnode_id) st.st_ino; 2588 btAddHandle(dir_vnid, *file_vnid, name); 2589 } 2590 else 2591 return BEOS_EACCES; 2592 } 2593 } 2594 2595 return B_OK; 2596} 2597 2598int btTruncate(char *pathBuf, vnode_id vnid, int64 len) 2599{ 2600 char *path; 2601 2602 path = btGetLocalFileName(pathBuf, vnid); 2603 if (path) 2604 { 2605 FILE *fp = fopen(path, "w"); 2606 fclose(fp); 2607 return B_OK; 2608 } 2609 2610 return BEOS_EACCES; 2611} 2612 2613// btCreateDir() 2614// 2615int btCreateDir(char *pathBuf, vnode_id dir_vnid, char *name, int perms, vnode_id *file_vnid, beos_stat *st) 2616{ 2617 char path[B_PATH_NAME_LENGTH], *folder; 2618 2619 folder = btGetLocalFileName(pathBuf, dir_vnid); 2620 if (folder) 2621 { 2622 btMakePath(path, folder, name); 2623 if (_mkdir(path) == -1) 2624 return errno; 2625 2626 if (btGetBeosStat(path, st) != 0) 2627 return BEOS_ENOENT; 2628 2629 *file_vnid = (vnode_id) st->st_ino; 2630 btAddHandle(dir_vnid, *file_vnid, name); 2631 return B_OK; 2632 } 2633 2634 return BEOS_ENOENT; 2635} 2636 2637// btDeleteDir() 2638// 2639int btDeleteDir(char *pathBuf, vnode_id vnid, char *name) 2640{ 2641 struct _stat st; 2642 char path[B_PATH_NAME_LENGTH], *folder; 2643 2644 folder = btGetLocalFileName(pathBuf, vnid); 2645 if (folder) 2646 { 2647 btMakePath(path, folder, name); 2648 if (_stat(path, &st) != 0) 2649 return errno; 2650 2651 if (_rmdir(path) == -1) 2652 return errno; 2653 2654 btPurgeNodes(btGetWinInode(path)); 2655 return B_OK; 2656 } 2657 2658 return BEOS_ENOENT; 2659} 2660 2661// btRename() 2662// 2663int btRename(char *pathBuf, vnode_id old_vnid, char *oldName, vnode_id new_vnid, char *newName) 2664{ 2665 struct _stat st; 2666 char oldPath[B_PATH_NAME_LENGTH], newPath[B_PATH_NAME_LENGTH], *oldFolder, *newFolder; 2667 2668 oldFolder = btGetLocalFileName(pathBuf, old_vnid); 2669 if (oldFolder) 2670 { 2671 btMakePath(oldPath, oldFolder, oldName); 2672 2673 newFolder = btGetLocalFileName(pathBuf, new_vnid); 2674 if (newFolder) 2675 { 2676 btMakePath(newPath, newFolder, newName); 2677 2678 if (_stat(oldPath, &st) != 0) 2679 return errno; 2680 2681 btPurgeNodes(btGetWinInode(oldPath)); 2682 2683 if (rename(oldPath, newPath) == -1) 2684 return errno; 2685 2686 return B_OK; 2687 } 2688 } 2689 2690 return BEOS_ENOENT; 2691} 2692 2693// btUnlink() 2694// 2695int btUnlink(char *pathBuf, vnode_id vnid, char *name) 2696{ 2697 struct _stat st; 2698 char path[B_PATH_NAME_LENGTH], *folder; 2699 int error; 2700 2701 folder = btGetLocalFileName(pathBuf, vnid); 2702 if (folder) 2703 { 2704 btMakePath(path, folder, name); 2705 2706 // Obtain the inode (vnid) of the specified file through stat(). 2707 if (_stat(path, &st) != 0) 2708 return errno; 2709 2710 // Construct a dummy file descriptor and cause it to be removed from 2711 // the list. 2712 btRemoveHandle(btGetWinInode(path)); 2713 2714 error = unlink(path); 2715 return (error == -1 ? errno : B_OK); 2716 } 2717 2718 return BEOS_EACCES; 2719} 2720 2721int btReadLink(char *pathBuf, vnode_id vnid, char *buffer, int length) 2722{ 2723 return BEOS_ENOENT; 2724} 2725 2726int btSymLink(char *pathBuf, vnode_id vnid, char *name, char *dest) 2727{ 2728 return BEOS_ENOENT; 2729} 2730 2731int btWStat(char *pathBuf, vnode_id vnid, long mask, int32 mode, int32 uid, int32 gid, int64 size, int32 atime, int32 mtime) 2732{ 2733 struct _utimbuf ftimes; 2734 struct _stat st; 2735 char *path; 2736 2737 path = btGetLocalFileName(pathBuf, vnid); 2738 if (path) 2739 { 2740// if (mask & WSTAT_MODE) 2741// chmod(path, mode); 2742 2743// if (mask & WSTAT_UID) 2744// chown(path, uid, -1); 2745 2746// if (mask & WSTAT_GID) 2747// chown(path, -1, gid); 2748 2749// if (mask & WSTAT_SIZE) 2750// truncate(path, size); 2751 2752 if (_stat(path, &st) == 0) 2753 if (mask & WSTAT_ATIME || mask & WSTAT_MTIME) 2754 { 2755 ftimes.actime = mask & WSTAT_ATIME ? atime : st.st_atime; 2756 ftimes.modtime = mask & WSTAT_MTIME ? mtime : st.st_mtime; 2757 _utime(path, &ftimes); 2758 } 2759 2760 return B_OK; 2761 } 2762 2763 return BEOS_ENOENT; 2764} 2765 2766int btReadAttrib(char *pathBuf, vnode_id vnid, char *name, char *buffer) 2767{ 2768 bt_mime_mapping *map; 2769 char *path; 2770 2771 path = btGetLocalFileName(pathBuf, vnid); 2772 if (path) 2773 { 2774 char *ext = strrchr(path, '.'); 2775 if (ext) 2776 { 2777 ext++; 2778 for (map = mimeMap; map; map = map->next) 2779 if (stricmp(ext, map->extension) == 0) 2780 { 2781 strcpy(buffer, map->mimeType); 2782 return (strlen(buffer)); 2783 } 2784 } 2785 } 2786 2787 return 0; 2788} 2789 2790int btAuthenticate(char *resource, char *user, char *password) 2791{ 2792 bt_user_rights *ur, *rootUr; 2793 bt_printer *printer; 2794 char *groups[MAX_GROUPS_PER_USER]; 2795 int i, rights, share; 2796 bool authenticated = false; 2797 2798 // Determine if the resource is a file share or a printer. 2799 share = btGetShareId(resource); 2800 if (share >= 0) 2801 { 2802 if (fileShares[share].security == BT_AUTH_NONE) 2803 return B_OK; 2804 2805 rootUr = fileShares[share].rights; 2806 } 2807 else 2808 { 2809 printer = btFindPrinter(resource); 2810 if (printer) 2811 if (printer->security == BT_AUTH_NONE) 2812 return B_OK; 2813 2814 rootUr = printer->rights; 2815 } 2816 2817 // Authenticate the user with name/password. 2818 authenticated = authenticateUser(user, password); 2819 if (!authenticated) 2820 return BEOS_EACCES; 2821 2822 // Does the authenticated user have any rights on this file share? 2823 rights = 0; 2824 for (ur = rootUr; ur; ur = ur->next) 2825 if (!ur->isGroup && stricmp(ur->user, user) == 0) 2826 rights |= ur->rights; 2827 2828 // Does the authenticated user belong to any groups that have any rights on this 2829 // file share? 2830 for (i = 0; i < MAX_GROUPS_PER_USER; i++) 2831 groups[i] = NULL; 2832 2833 getUserGroups(user, groups); 2834 for (ur = rootUr; ur; ur = ur->next) 2835 if (ur->isGroup) 2836 for (i = 0; i < MAX_GROUPS_PER_USER; i++) 2837 if (groups[i] && stricmp(ur->user, groups[i]) == 0) 2838 { 2839 rights |= ur->rights; 2840 break; 2841 } 2842 2843 // Free the memory occupied by the group list. 2844 for (i = 0; i < MAX_GROUPS_PER_USER; i++) 2845 if (groups[i]) 2846 free(groups[i]); 2847 2848 // If no rights have been granted, deny access. 2849 if (!rights) 2850 return BEOS_EACCES; 2851 2852 return B_OK; 2853} 2854 2855//////////////////////////////////////////////////////////////////// 2856 2857void netbtPreMount(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 2858{ 2859 bt_outPacket packet; 2860 int client, security; 2861 2862 client = session->socket; 2863 security = btPreMount(session, argv[0].data); 2864 btRPCCreateAck(&packet, xid, security); 2865 btRPCSendAck(session->socket, &packet); 2866} 2867 2868void netbtMount(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 2869{ 2870 bt_outPacket packet; 2871 vnode_id vnid; 2872 int client, error; 2873 char *shareName = argv[0].data; 2874 char *user = argv[1].data; 2875 char *password = argv[2].data; 2876 2877 client = session->socket; 2878 2879 error = btMount(session, shareName, user, password, &vnid); 2880 if (error == B_OK) 2881 { 2882 // Record this session having logged in to a specific share. 2883 session->share = btGetShareId(shareName); 2884 session->logon = time(NULL); 2885 2886 // Now send the client a response with the root vnid; 2887 btRPCCreateAck(&packet, xid, error); 2888 btRPCPutInt64(&packet, vnid); 2889 } 2890 else 2891 btRPCCreateAck(&packet, xid, error); 2892 2893 btRPCSendAck(client, &packet); 2894} 2895 2896void netbtFSInfo(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 2897{ 2898 bt_outPacket packet; 2899 int client, error; 2900 fs_info info; 2901 2902 client = session->socket; 2903 2904 error = btGetFSInfo(&info, fileShares[session->share].path); 2905 if (error == B_OK) 2906 { 2907 btRPCCreateAck(&packet, xid, error); 2908 btRPCPutInt32(&packet, info.block_size); 2909 btRPCPutInt32(&packet, info.total_blocks); 2910 btRPCPutInt32(&packet, info.free_blocks); 2911 } 2912 else 2913 btRPCCreateAck(&packet, xid, error); 2914 2915 btRPCSendAck(client, &packet); 2916} 2917 2918void netbtLookup(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 2919{ 2920 bt_outPacket packet; 2921 beos_stat st; 2922 int client, error; 2923 vnode_id dir_vnid = *((vnode_id *) argv[0].data); 2924 vnode_id file_vnid; 2925 2926 client = session->socket; 2927 2928 error = btLookup(session->pathBuffer, dir_vnid, argv[1].data, &file_vnid); 2929 if (error == B_OK) 2930 error = btStat(session->pathBuffer, file_vnid, &st); 2931 2932 if (error == B_OK) 2933 { 2934 btRPCCreateAck(&packet, xid, B_OK); 2935 btRPCPutInt64(&packet, file_vnid); 2936 btRPCPutStat(&packet, &st); 2937 } 2938 else 2939 btRPCCreateAck(&packet, xid, error); 2940 2941 btRPCSendAck(client, &packet); 2942} 2943 2944void netbtReadDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 2945{ 2946 const int MAX_FOLDER_ENTRIES = 128; 2947 bt_outPacket packet; 2948 beos_stat st; 2949 int client, error; 2950 vnode_id dir_vnid = *((vnode_id *) argv[0].data); 2951 vnode_id file_vnid; 2952 long *dir; 2953 char filename[B_PATH_NAME_LENGTH]; 2954 int entries = 0; 2955 2956 client = session->socket; 2957 2958 dir = (long *)(*((int32 *) argv[1].data)); 2959 error = btReadDir(session->pathBuffer, dir_vnid, &dir, &file_vnid, filename, &st); 2960 2961 if (error != B_OK) 2962 { 2963 btRPCCreateAck(&packet, xid, error); 2964 btRPCSendAck(client, &packet); 2965 return; 2966 } 2967 2968 btRPCCreateAck(&packet, xid, B_OK); 2969 while (error == B_OK) 2970 { 2971 btRPCPutInt64(&packet, file_vnid); 2972 btRPCPutString(&packet, filename, strlen(filename)); 2973 btRPCPutInt32(&packet, (int32) dir); 2974 btRPCPutStat(&packet, &st); 2975 2976 if (++entries >= MAX_FOLDER_ENTRIES) 2977 break; 2978 2979 error = btReadDir(session->pathBuffer, dir_vnid, &dir, &file_vnid, filename, &st); 2980 btRPCPutInt32(&packet, error); 2981 } 2982 2983 // If we exhausted the list of directory entries without filling 2984 // the buffer, add an error message that will prevent the client 2985 // from requesting further entries. 2986 if (entries < MAX_FOLDER_ENTRIES) 2987 btRPCPutInt32(&packet, BEOS_ENOENT); 2988 2989 btRPCSendAck(client, &packet); 2990} 2991 2992void netbtStat(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 2993{ 2994 bt_outPacket packet; 2995 int client, error; 2996 beos_stat info; 2997 vnode_id vnid = *((vnode_id *) argv[0].data); 2998 2999 client = session->socket; 3000 3001 error = btStat(session->pathBuffer, vnid, &info); 3002 3003 if (error == B_OK) 3004 { 3005 btRPCCreateAck(&packet, xid, error); 3006 btRPCPutStat(&packet, &info); 3007 } 3008 else 3009 btRPCCreateAck(&packet, xid, error); 3010 3011 btRPCSendAck(client, &packet); 3012} 3013 3014void netbtRead(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3015{ 3016 bt_outPacket packet; 3017 int client; 3018 vnode_id vnid = *((vnode_id *) argv[0].data); 3019 beos_off_t pos = *((beos_off_t *) argv[1].data); 3020 int32 len = *((int32 *) argv[2].data); 3021 int32 bytes = 0; 3022 3023 client = session->socket; 3024 3025 session->ioBuffer[len] = 0; 3026 bytes = btRead(session->pathBuffer, vnid, pos, len, session->ioBuffer); 3027 3028 btRPCCreateAck(&packet, xid, B_OK); 3029 btRPCPutString(&packet, session->ioBuffer, bytes); 3030 btRPCSendAck(client, &packet); 3031} 3032 3033void netbtWrite(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3034{ 3035 int client; 3036 vnode_id vnid = *((vnode_id *) argv[0].data); 3037 beos_off_t pos = *((beos_off_t *) argv[1].data); 3038 int32 len = *((int32 *) argv[2].data); 3039 int32 totalLen = *((int32 *) argv[3].data); 3040 3041 client = session->socket; 3042 3043 // If the file share this user is connected to is read-only, the command 3044 // cannot be honored. 3045 if (session->rights & BT_RIGHTS_WRITE) 3046 btWrite(session, vnid, pos, len, totalLen, argv[4].data); 3047} 3048 3049void netbtCreate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3050{ 3051 bt_outPacket packet; 3052 beos_stat st; 3053 int client, error; 3054 vnode_id dir_vnid = *((vnode_id *) argv[0].data); 3055 vnode_id file_vnid; 3056 int omode = *((int *) argv[2].data); 3057 int perms = *((int *) argv[3].data); 3058 3059 client = session->socket; 3060 3061 // If the file share this user is connected to is read-only, the command 3062 // cannot be honored. 3063 if (!(session->rights & BT_RIGHTS_WRITE)) 3064 { 3065 btRPCCreateAck(&packet, xid, BEOS_EACCES); 3066 btRPCSendAck(client, &packet); 3067 return; 3068 } 3069 3070 error = btCreate(session->pathBuffer, dir_vnid, argv[1].data, omode, perms, &file_vnid); 3071 if (error == B_OK) 3072 error = btStat(session->pathBuffer, file_vnid, &st); 3073 3074 if (error == B_OK) 3075 { 3076 btRPCCreateAck(&packet, xid, B_OK); 3077 btRPCPutInt64(&packet, file_vnid); 3078 btRPCPutStat(&packet, &st); 3079 } 3080 else 3081 btRPCCreateAck(&packet, xid, error); 3082 3083 btRPCSendAck(client, &packet); 3084} 3085 3086void netbtTruncate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3087{ 3088 bt_outPacket packet; 3089 int client, error; 3090 vnode_id vnid = *((vnode_id *) argv[0].data); 3091 3092 client = session->socket; 3093 3094 // If the file share this user is connected to is read-only, the command 3095 // cannot be honored. 3096 if (!(session->rights & BT_RIGHTS_WRITE)) 3097 { 3098 btRPCCreateAck(&packet, xid, BEOS_EACCES); 3099 btRPCSendAck(client, &packet); 3100 return; 3101 } 3102 3103 error = btTruncate(session->pathBuffer, vnid, *((int64 *) argv[1].data)); 3104 btRPCCreateAck(&packet, xid, error); 3105 btRPCSendAck(client, &packet); 3106} 3107 3108void netbtUnlink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3109{ 3110 bt_outPacket packet; 3111 int client, error; 3112 vnode_id vnid = *((vnode_id *) argv[0].data); 3113 3114 client = session->socket; 3115 3116 // If the file share this user is connected to is read-only, the command 3117 // cannot be honored. 3118 if (!(session->rights & BT_RIGHTS_WRITE)) 3119 { 3120 btRPCCreateAck(&packet, xid, BEOS_EACCES); 3121 btRPCSendAck(client, &packet); 3122 return; 3123 } 3124 3125 error = btUnlink(session->pathBuffer, vnid, argv[1].data); 3126 btRPCCreateAck(&packet, xid, error); 3127 btRPCSendAck(client, &packet); 3128} 3129 3130void netbtRename(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3131{ 3132 bt_outPacket packet; 3133 int client, error; 3134 vnode_id old_vnid = *((vnode_id *) argv[0].data); 3135 vnode_id new_vnid = *((vnode_id *) argv[2].data); 3136 3137 client = session->socket; 3138 3139 // If the file share this user is connected to is read-only, the command 3140 // cannot be honored. 3141 if (!(session->rights & BT_RIGHTS_WRITE)) 3142 { 3143 btRPCCreateAck(&packet, xid, BEOS_EACCES); 3144 btRPCSendAck(client, &packet); 3145 return; 3146 } 3147 3148 error = btRename(session->pathBuffer, old_vnid, argv[1].data, new_vnid, argv[3].data); 3149 btRPCCreateAck(&packet, xid, error); 3150 btRPCSendAck(client, &packet); 3151} 3152 3153void netbtCreateDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3154{ 3155 bt_outPacket packet; 3156 int client, error; 3157 vnode_id dir_vnid = *((vnode_id *) argv[0].data); 3158 vnode_id file_vnid; 3159 beos_stat st; 3160 3161 client = session->socket; 3162 3163 // If the file share this user is connected to is read-only, the command 3164 // cannot be honored. 3165 if (!(session->rights & BT_RIGHTS_WRITE)) 3166 { 3167 btRPCCreateAck(&packet, xid, BEOS_EACCES); 3168 btRPCSendAck(client, &packet); 3169 return; 3170 } 3171 3172 error = btCreateDir(session->pathBuffer, dir_vnid, argv[1].data, *((int *) argv[2].data), &file_vnid, &st); 3173 if (error == B_OK) 3174 { 3175 btRPCCreateAck(&packet, xid, B_OK); 3176 btRPCPutInt64(&packet, file_vnid); 3177 btRPCPutStat(&packet, &st); 3178 } 3179 else 3180 btRPCCreateAck(&packet, xid, error); 3181 3182 btRPCSendAck(client, &packet); 3183} 3184 3185void netbtDeleteDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3186{ 3187 bt_outPacket packet; 3188 int client, error; 3189 vnode_id vnid = *((vnode_id *) argv[0].data); 3190 3191 client = session->socket; 3192 3193 // If the file share this user is connected to is read-only, the command 3194 // cannot be honored. 3195 if (!(session->rights & BT_RIGHTS_WRITE)) 3196 { 3197 btRPCCreateAck(&packet, xid, BEOS_EACCES); 3198 btRPCSendAck(client, &packet); 3199 return; 3200 } 3201 3202 error = btDeleteDir(session->pathBuffer, vnid, argv[1].data); 3203 btRPCCreateAck(&packet, xid, error); 3204 btRPCSendAck(client, &packet); 3205} 3206 3207void netbtReadLink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3208{ 3209 bt_outPacket packet; 3210 int client; 3211 3212 client = session->socket; 3213 btRPCCreateAck(&packet, xid, ENOTSUP); 3214 btRPCSendAck(client, &packet); 3215} 3216 3217void netbtSymLink(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3218{ 3219 bt_outPacket packet; 3220 int client; 3221 3222 client = session->socket; 3223 btRPCCreateAck(&packet, xid, ENOTSUP); 3224 btRPCSendAck(client, &packet); 3225} 3226 3227void netbtWStat(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3228{ 3229 bt_outPacket packet; 3230 int client, error; 3231 vnode_id vnid = *((vnode_id *) argv[0].data); 3232 int32 mask = *((int32 *) argv[1].data); 3233 int32 mode = *((int32 *) argv[2].data); 3234 int32 uid = *((int32 *) argv[3].data); 3235 int32 gid = *((int32 *) argv[4].data); 3236 int64 size = (int64) *((int32 *) argv[5].data); 3237 int32 atime = *((int32 *) argv[6].data); 3238 int32 mtime = *((int32 *) argv[7].data); 3239 3240 client = session->socket; 3241 3242 // If the file share this user is connected to is read-only, the command 3243 // cannot be honored. 3244 if (!(session->rights & BT_RIGHTS_WRITE)) 3245 { 3246 btRPCCreateAck(&packet, xid, BEOS_EACCES); 3247 btRPCSendAck(client, &packet); 3248 return; 3249 } 3250 3251 error = btWStat(session->pathBuffer, vnid, mask, mode, uid, gid, size, atime, mtime); 3252 btRPCCreateAck(&packet, xid, error); 3253 btRPCSendAck(client, &packet); 3254} 3255 3256void netbtReadAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3257{ 3258 bt_outPacket packet; 3259 int client, bytesRead; 3260 3261 client = session->socket; 3262 3263 if (stricmp(argv[1].data, "BEOS:TYPE") == 0) 3264 { 3265 vnode_id vnid = *((vnode_id *) argv[0].data); 3266 bytesRead = btReadAttrib(session->pathBuffer, vnid, argv[1].data, session->attrBuffer); 3267 if (bytesRead > 0) 3268 { 3269 btRPCCreateAck(&packet, xid, B_OK); 3270 btRPCPutInt32(&packet, (int32) bytesRead + 1); 3271 btRPCPutString(&packet, session->attrBuffer, bytesRead + 1); 3272 btRPCSendAck(client, &packet); 3273 return; 3274 } 3275 } 3276 3277 btRPCCreateAck(&packet, xid, ENOTSUP); 3278 btRPCSendAck(client, &packet); 3279} 3280 3281void netbtWriteAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3282{ 3283 bt_outPacket packet; 3284 int client; 3285 3286 client = session->socket; 3287 btRPCCreateAck(&packet, xid, ENOTSUP); 3288 btRPCSendAck(client, &packet); 3289} 3290 3291void netbtReadAttribDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3292{ 3293 bt_outPacket packet; 3294 int client; 3295 3296 client = session->socket; 3297 btRPCCreateAck(&packet, xid, ENOTSUP); 3298 btRPCSendAck(client, &packet); 3299} 3300 3301void netbtRemoveAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3302{ 3303 bt_outPacket packet; 3304 int client; 3305 3306 client = session->socket; 3307 btRPCCreateAck(&packet, xid, ENOTSUP); 3308 btRPCSendAck(client, &packet); 3309} 3310 3311void netbtStatAttrib(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3312{ 3313 bt_outPacket packet; 3314 int client, bytesRead; 3315 3316 client = session->socket; 3317 if (strcmp(argv[1].data, "BEOS:TYPE") == 0) 3318 { 3319 vnode_id vnid = *((vnode_id *) argv[0].data); 3320 bytesRead = btReadAttrib(session->pathBuffer, vnid, argv[1].data, session->attrBuffer); 3321 btRPCCreateAck(&packet, xid, B_OK); 3322 btRPCPutInt32(&packet, B_STRING_TYPE); 3323 btRPCPutInt64(&packet, bytesRead + 1); 3324 btRPCSendAck(client, &packet); 3325 return; 3326 } 3327 3328 btRPCCreateAck(&packet, xid, ENOTSUP); 3329 btRPCSendAck(client, &packet); 3330} 3331 3332void netbtReadIndexDir(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3333{ 3334 bt_outPacket packet; 3335 int client; 3336 3337 client = session->socket; 3338 btRPCCreateAck(&packet, xid, ENOTSUP); 3339 btRPCSendAck(client, &packet); 3340} 3341 3342void netbtCreateIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3343{ 3344 bt_outPacket packet; 3345 int client; 3346 3347 client = session->socket; 3348 btRPCCreateAck(&packet, xid, ENOTSUP); 3349 btRPCSendAck(client, &packet); 3350} 3351 3352void netbtRemoveIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3353{ 3354 bt_outPacket packet; 3355 int client; 3356 3357 client = session->socket; 3358 btRPCCreateAck(&packet, xid, ENOTSUP); 3359 btRPCSendAck(client, &packet); 3360} 3361 3362void netbtStatIndex(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3363{ 3364 bt_outPacket packet; 3365 int client; 3366 3367 client = session->socket; 3368 btRPCCreateAck(&packet, xid, ENOTSUP); 3369 btRPCSendAck(client, &packet); 3370} 3371 3372void netbtReadQuery(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3373{ 3374 bt_outPacket packet; 3375 int client; 3376 3377 client = session->socket; 3378 btRPCCreateAck(&packet, xid, ENOTSUP); 3379 btRPCSendAck(client, &packet); 3380} 3381 3382void netbtCommit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3383{ 3384 bt_outPacket packet; 3385 int client, error; 3386 vnode_id vnid = *((vnode_id *) argv[0].data); 3387 3388 client = session->socket; 3389 3390 // If the file share this user is connected to is read-only, the command 3391 // cannot be honored. 3392 if (!(session->rights & BT_RIGHTS_WRITE)) 3393 { 3394 btRPCCreateAck(&packet, xid, BEOS_EACCES); 3395 btRPCSendAck(client, &packet); 3396 return; 3397 } 3398 3399 error = btCommit(session, vnid); 3400 btRPCCreateAck(&packet, xid, error); 3401 btRPCSendAck(client, &packet); 3402} 3403 3404void netbtPrintJobNew(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3405{ 3406 bt_outPacket packet; 3407 int client, error; 3408 char jobId[MAX_NAME_LENGTH]; 3409 char *printerName = argv[0].data; 3410 char *user = argv[1].data; 3411 char *password = argv[2].data; 3412 char *jobName = argv[3].data; 3413 3414 client = session->socket; 3415 3416 error = btPrintJobNew(printerName, user, password, session->client_s_addr, jobName, jobId); 3417 btRPCCreateAck(&packet, xid, error); 3418 if (error == B_OK) 3419 btRPCPutString(&packet, jobId, strlen(jobId)); 3420 3421 btRPCSendAck(client, &packet); 3422} 3423 3424void netbtPrintJobData(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3425{ 3426 bt_outPacket packet; 3427 int client, error; 3428 char *printerName = argv[0].data; 3429 char *jobId = argv[1].data; 3430 char *jobData = argv[2].data; 3431 int32 dataLen = *((int32 *) argv[3].data); 3432 3433 client = session->socket; 3434 3435 error = btPrintJobData(printerName, jobId, jobData, dataLen); 3436 btRPCCreateAck(&packet, xid, error); 3437 btRPCSendAck(client, &packet); 3438} 3439 3440void netbtPrintJobCommit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3441{ 3442 bt_outPacket packet; 3443 int client, error; 3444 char *printerName = argv[0].data; 3445 char *jobId = argv[1].data; 3446 3447 client = session->socket; 3448 3449 error = btPrintJobCommit(printerName, jobId); 3450 btRPCCreateAck(&packet, xid, error); 3451 btRPCSendAck(client, &packet); 3452} 3453 3454void netbtAuthenticate(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3455{ 3456 bt_outPacket packet; 3457 int client, error; 3458 char *resource = argv[0].data; 3459 char *user = argv[1].data; 3460 char *password = argv[2].data; 3461 3462 client = session->socket; 3463 3464 error = btAuthenticate(resource, user, password); 3465 btRPCCreateAck(&packet, xid, error); 3466 btRPCSendAck(client, &packet); 3467} 3468 3469void netbtQuit(bt_session_t *session, unsigned int xid, int argc, bt_arg_t argv[]) 3470{ 3471 bt_outPacket packet; 3472 int client; 3473 3474 client = session->socket; 3475 btRPCCreateAck(&packet, xid, B_OK); 3476 btRPCSendAck(client, &packet); 3477} 3478 3479/* 3480bool IsValidUser(char *user, char *domain, char *password) 3481{ 3482 HANDLE hUser, hTok; 3483 OSVERSIONINFO osInfo; 3484 bool authenticated; 3485 3486 authenticated = false; 3487 3488 osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 3489 if (GetVersionEx(&osInfo)) 3490 if (osInfo.dwPlatformId != VER_PLATFORM_WIN32_NT) 3491 return true; 3492 3493 hTok = 0; 3494 if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hTok)) 3495 { 3496 TOKEN_PRIVILEGES tp; 3497 tp.PrivilegeCount = 1; 3498 tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 3499 if (LookupPrivilegeValue(0, SE_TCB_NAME, &tp.Privileges[0].Luid)) 3500 if (AdjustTokenPrivileges(hTok, FALSE, &tp, 0, NULL, NULL)) 3501 if (LogonUser(user, domain, password, LOGON32_LOGON_BATCH, LOGON32_PROVIDER_DEFAULT, &hUser)) 3502 { 3503 CloseHandle(hUser); 3504 authenticated = true; 3505 } 3506 3507 CloseHandle(hTok); 3508 } 3509 3510 return authenticated; 3511} 3512*/ 3513 3514void loadFolder(const char *path) 3515{ 3516 struct _finddata_t fileInfo; 3517 struct _stat st; 3518 char *search; 3519 long dir, result; 3520 uint32 dir_vnid; 3521 3522 search = (char *) malloc(MAX_PATH); 3523 if (search == NULL) 3524 return; 3525 3526 dir_vnid = btGetWinInode(path); 3527 sprintf(search, "%s\\*.*", path); 3528 3529 dir = result = _findfirst(search, &fileInfo); 3530 while (result != -1) 3531 { 3532 btMakePath(search, (char *) path, fileInfo.name); 3533 btAddHandle(dir_vnid, btGetWinInode(search), fileInfo.name); 3534 3535 _stat(search, &st); 3536 if (st.st_mode & _S_IFDIR) 3537 if (strcmp(fileInfo.name, ".") && strcmp(fileInfo.name, "..")) 3538 loadFolder(search); 3539 3540 result = _findnext(dir, &fileInfo); 3541 } 3542 3543 _findclose(dir); 3544 free(search); 3545} 3546 3547 3548 3549//////// 3550 3551void KillNode(ubi_trNodePtr node) 3552{ 3553 bt_node *bn = (bt_node *) node; 3554 free(bn->name); 3555 free(node); 3556} 3557 3558int CompareVnidNodes(ubi_trItemPtr item, ubi_trNodePtr node) 3559{ 3560 vnode_id vnid1 = *((vnode_id *) item); 3561 vnode_id vnid2 = ((bt_node *) node)->vnid; 3562 if (vnid1 < vnid2) 3563 return -1; 3564 else if (vnid1 > vnid2) 3565 return 1; 3566 else 3567 return 0; 3568} 3569 3570int CompareNameNodes(ubi_trItemPtr item, ubi_trNodePtr node) 3571{ 3572 bt_node *node1 = (bt_node *) item; 3573 bt_node *node2 = (bt_node *) node; 3574 3575 if (node1->parent < node2->parent) 3576 return -1; 3577 else if (node1->parent > node2->parent) 3578 return 1; 3579 else 3580 return strcmp(node1->name, node2->name); 3581} 3582