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