root/fs/ncpfs/ncplib_kernel.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. min
  2. assert_server_locked
  3. ncp_add_byte
  4. ncp_add_word
  5. ncp_add_dword
  6. ncp_add_mem
  7. ncp_add_mem_fromfs
  8. ncp_add_pstring
  9. ncp_init_request
  10. ncp_init_request_s
  11. ncp_reply_data
  12. ncp_reply_byte
  13. ncp_reply_word
  14. ncp_reply_dword
  15. ncp_negotiate_buffersize
  16. ncp_get_volume_info_with_number
  17. ncp_get_volume_number
  18. ncp_close_file
  19. ncp_add_handle_path
  20. ncp_extract_file_info
  21. ncp_obtain_info
  22. ncp_lookup_volume
  23. ncp_modify_file_or_subdir_dos_info
  24. ncp_del_file_or_subdir
  25. ConvertToNWfromDWORD
  26. ncp_open_create_file_or_subdir
  27. ncp_initialize_search
  28. ncp_search_for_file_or_subdir
  29. ncp_ren_or_mov_file_or_subdir
  30. ncp_read
  31. ncp_write

   1 /*
   2  *  ncplib_kernel.c
   3  *
   4  *  Copyright (C) 1995, 1996 by Volker Lendecke
   5  *
   6  */
   7 
   8 #include "ncplib_kernel.h"
   9 
  10 typedef __u8  byte;
  11 typedef __u16 word;
  12 typedef __u32 dword;
  13 
  14 static inline int min(int a, int b)
     /* [previous][next][first][last][top][bottom][index][help] */
  15 {
  16         return a<b ? a : b;
  17 }
  18 
  19 static void
  20 assert_server_locked(struct ncp_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
  21 {
  22         if (server->lock == 0)
  23         {
  24                 DPRINTK("ncpfs: server not locked!\n");
  25         }
  26 }
  27 
  28 static void
  29 ncp_add_byte(struct ncp_server *server, byte x)
     /* [previous][next][first][last][top][bottom][index][help] */
  30 {
  31         assert_server_locked(server);
  32         *(byte *)(&(server->packet[server->current_size])) = x;
  33         server->current_size += 1;
  34         return;
  35 }
  36 
  37 static void
  38 ncp_add_word(struct ncp_server *server, word x)
     /* [previous][next][first][last][top][bottom][index][help] */
  39 {
  40         assert_server_locked(server);
  41         *(word *)(&(server->packet[server->current_size])) = x;
  42         server->current_size += 2;
  43         return;
  44 }
  45 
  46 static void
  47 ncp_add_dword(struct ncp_server *server, dword x)
     /* [previous][next][first][last][top][bottom][index][help] */
  48 {
  49         assert_server_locked(server);
  50         *(dword *)(&(server->packet[server->current_size])) = x;
  51         server->current_size += 4;
  52         return;
  53 }
  54 
  55 static void
  56 ncp_add_mem(struct ncp_server *server, const void *source, int size)
     /* [previous][next][first][last][top][bottom][index][help] */
  57 {
  58         assert_server_locked(server);
  59         memcpy(&(server->packet[server->current_size]), source, size);
  60         server->current_size += size;
  61         return;
  62 }
  63 
  64 static void
  65 ncp_add_mem_fromfs(struct ncp_server *server, const char *source, int size)
     /* [previous][next][first][last][top][bottom][index][help] */
  66 {
  67         assert_server_locked(server);
  68         memcpy_fromfs(&(server->packet[server->current_size]), source, size);
  69         server->current_size += size;
  70         return;
  71 }
  72 
  73 static void
  74 ncp_add_pstring(struct ncp_server *server, const char *s)
     /* [previous][next][first][last][top][bottom][index][help] */
  75 {
  76         int len = strlen(s);
  77         assert_server_locked(server);
  78         if (len > 255)
  79         {
  80                 DPRINTK("ncpfs: string too long: %s\n", s);
  81                 len = 255;
  82         }
  83         ncp_add_byte(server, len);
  84         ncp_add_mem(server, s, len);
  85         return;
  86 }
  87 
  88 static void
  89 ncp_init_request(struct ncp_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
  90 {
  91         ncp_lock_server(server);
  92 
  93         server->current_size = sizeof(struct ncp_request_header);
  94         server->has_subfunction = 0;
  95 }
  96 
  97 static void
  98 ncp_init_request_s(struct ncp_server *server, int subfunction)
     /* [previous][next][first][last][top][bottom][index][help] */
  99 {
 100         ncp_init_request(server);
 101         ncp_add_word(server, 0); /* preliminary size */
 102 
 103         ncp_add_byte(server, subfunction);
 104 
 105         server->has_subfunction = 1;
 106 }
 107 
 108 static char *
 109 ncp_reply_data(struct ncp_server *server, int offset)
     /* [previous][next][first][last][top][bottom][index][help] */
 110 {
 111         return &(server->packet[sizeof(struct ncp_reply_header) + offset]);
 112 }
 113 
 114 static byte
 115 ncp_reply_byte(struct ncp_server *server, int offset)
     /* [previous][next][first][last][top][bottom][index][help] */
 116 {
 117         return *(byte *)(ncp_reply_data(server, offset));
 118 }
 119 
 120 static word
 121 ncp_reply_word(struct ncp_server *server, int offset)
     /* [previous][next][first][last][top][bottom][index][help] */
 122 {
 123         return *(word *)(ncp_reply_data(server, offset));
 124 }
 125 
 126 static dword
 127 ncp_reply_dword(struct ncp_server *server, int offset)
     /* [previous][next][first][last][top][bottom][index][help] */
 128 {
 129         return *(dword *)(ncp_reply_data(server, offset));
 130 }
 131 
 132 int
 133 ncp_negotiate_buffersize(struct ncp_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 134                          int size, int *target)
 135 {
 136         int result;
 137 
 138         ncp_init_request(server);
 139         ncp_add_word(server, htons(size));
 140         
 141         if ((result = ncp_request(server, 33)) != 0)
 142         {
 143                 ncp_unlock_server(server);
 144                 return result;
 145         }
 146 
 147         *target =min(ntohs(ncp_reply_word(server, 0)), size);
 148 
 149         ncp_unlock_server(server);
 150         return 0;
 151 }
 152 
 153 int
 154 ncp_get_volume_info_with_number(struct ncp_server *server, int n,
     /* [previous][next][first][last][top][bottom][index][help] */
 155                                 struct ncp_volume_info *target)
 156 {
 157         int result;
 158         int len;
 159 
 160         ncp_init_request_s(server, 44);
 161         ncp_add_byte(server, n);
 162 
 163         if ((result = ncp_request(server, 22)) != 0)
 164         {
 165                 ncp_unlock_server(server);
 166                 return result;
 167         }
 168 
 169         target->total_blocks = ncp_reply_dword(server, 0);
 170         target->free_blocks  = ncp_reply_dword(server, 4);
 171         target->purgeable_blocks = ncp_reply_dword(server, 8);
 172         target->not_yet_purgeable_blocks = ncp_reply_dword(server, 12);
 173         target->total_dir_entries = ncp_reply_dword(server, 16);
 174         target->available_dir_entries = ncp_reply_dword(server, 20);
 175         target->sectors_per_block = ncp_reply_byte(server, 28);
 176 
 177         memset(&(target->volume_name), 0, sizeof(target->volume_name));
 178 
 179         len = ncp_reply_byte(server, 29);
 180         if (len > NCP_VOLNAME_LEN)
 181         {
 182                 DPRINTK("ncpfs: volume name too long: %d\n", len);
 183                 ncp_unlock_server(server);
 184                 return -EIO;
 185         }
 186 
 187         memcpy(&(target->volume_name), ncp_reply_data(server, 30), len);
 188         ncp_unlock_server(server);
 189         return 0;
 190 }
 191 
 192 int
 193 ncp_get_volume_number(struct ncp_server *server, const char *name, int *target)
     /* [previous][next][first][last][top][bottom][index][help] */
 194 {
 195         int result;
 196 
 197         ncp_init_request_s(server, 5);
 198         ncp_add_pstring(server, name);
 199 
 200         if ((result = ncp_request(server, 22)) != 0)
 201         {
 202                 ncp_unlock_server(server);
 203                 return result;
 204         }
 205 
 206         *target = ncp_reply_byte(server, 0);
 207         ncp_unlock_server(server);
 208         return 0;
 209 }
 210 
 211 int
 212 ncp_close_file(struct ncp_server *server, const char *file_id)
     /* [previous][next][first][last][top][bottom][index][help] */
 213 {
 214         int result;
 215 
 216         ncp_init_request(server);
 217         ncp_add_byte(server, 0);
 218         ncp_add_mem(server, file_id, 6);
 219 
 220         if ((result = ncp_request(server, 66)) != 0)
 221         {
 222                 ncp_unlock_server(server);
 223                 return result;
 224         }
 225 
 226         ncp_unlock_server(server);
 227         return 0;
 228 }
 229 
 230 static void
 231 ncp_add_handle_path(struct ncp_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 232                     __u8 vol_num,
 233                     __u32 dir_base, int have_dir_base,
 234                     char *path)
 235 {
 236         ncp_add_byte(server, vol_num);
 237         ncp_add_dword(server, dir_base);
 238         if (have_dir_base != 0)
 239         {
 240                 ncp_add_byte(server, 1); /* dir_base */
 241         }
 242         else
 243         {
 244                 ncp_add_byte(server, 0xff); /* no handle */
 245         }
 246         if (path != NULL)
 247         {
 248                 ncp_add_byte(server, 1); /* 1 component */
 249                 ncp_add_pstring(server, path);
 250         }
 251         else
 252         {
 253                 ncp_add_byte(server, 0);
 254         }
 255 }
 256 
 257 static void
 258 ncp_extract_file_info(void *structure, struct nw_info_struct *target)
     /* [previous][next][first][last][top][bottom][index][help] */
 259 {
 260         __u8 *name_len;
 261         const int info_struct_size = sizeof(struct nw_info_struct) - 257;
 262 
 263         memcpy(target, structure, info_struct_size);
 264         name_len = structure + info_struct_size;
 265         target->nameLen = *name_len;
 266         strncpy(target->entryName, name_len+1, *name_len);
 267         target->entryName[*name_len] = '\0';
 268         return;
 269 }
 270 
 271 int
 272 ncp_obtain_info(struct ncp_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 273                 __u8 vol_num, __u32 dir_base,
 274                 char *path, /* At most 1 component */
 275                 struct nw_info_struct *target)
 276 {
 277         int result;
 278 
 279         if (target == NULL)
 280         {
 281                 return -EINVAL;
 282         }
 283 
 284         ncp_init_request(server);
 285         ncp_add_byte(server, 6); /* subfunction */
 286         ncp_add_byte(server, 0); /* dos name space */
 287         ncp_add_byte(server, 0); /* dos name space as dest */
 288         ncp_add_word(server, 0xff); /* get all */
 289         ncp_add_dword(server, RIM_ALL);
 290         ncp_add_handle_path(server, vol_num, dir_base, 1, path);
 291 
 292         if ((result = ncp_request(server, 87)) != 0)
 293         {
 294                 ncp_unlock_server(server);
 295                 return result;
 296         }
 297 
 298         ncp_extract_file_info(ncp_reply_data(server, 0), target);
 299         ncp_unlock_server(server);
 300         return 0;
 301 }
 302 
 303 int
 304 ncp_lookup_volume(struct ncp_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 305                   char *volname,
 306                   struct nw_info_struct *target)
 307 {
 308         int result;
 309         __u8  vol_num;
 310         __u32 dir_base;
 311 
 312         DPRINTK("ncp_lookup_volume: looking up vol %s\n", volname);
 313 
 314         ncp_init_request(server);
 315         ncp_add_byte(server, 22); /* Subfunction: Generate dir handle */
 316         ncp_add_byte(server, 0); /* DOS name space */
 317         ncp_add_byte(server, 0); /* reserved */
 318         ncp_add_byte(server, 0); /* reserved */
 319         ncp_add_byte(server, 0); /* reserved */
 320 
 321         ncp_add_byte(server, 0); /* faked volume number */
 322         ncp_add_dword(server, 0); /* faked dir_base */
 323         ncp_add_byte(server, 0xff); /* Don't have a dir_base */
 324         ncp_add_byte(server, 1); /* 1 path component */
 325         ncp_add_pstring(server, volname);
 326 
 327         if ((result = ncp_request(server, 87)) != 0)
 328         {
 329                 ncp_unlock_server(server);
 330                 return result;
 331         }
 332 
 333         dir_base = ncp_reply_dword(server, 4);
 334         vol_num  = ncp_reply_byte(server, 8);
 335         ncp_unlock_server(server);
 336 
 337         if ((result = ncp_obtain_info(server, vol_num, dir_base, NULL,
 338                                       target)) != 0)
 339         {
 340                 return result;
 341         }
 342 
 343         DPRINTK("ncp_lookup_volume: attribs = %X\n", target->attributes);
 344 
 345         target->nameLen = strlen(volname);
 346         strcpy(target->entryName, volname);
 347         return 0;
 348 }
 349 
 350 int
 351 ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 352                                    struct nw_info_struct *file,
 353                                    __u32 info_mask,
 354                                    struct nw_modify_dos_info *info)
 355 {
 356         int result;
 357 
 358         ncp_init_request(server);
 359         ncp_add_byte(server, 7); /* subfunction */
 360         ncp_add_byte(server, 0); /* dos name space */
 361         ncp_add_byte(server, 0); /* reserved */
 362         ncp_add_word(server, 0x8006); /* search attribs: all */
 363 
 364         ncp_add_dword(server, info_mask);
 365         ncp_add_mem(server, info, sizeof(*info));
 366         ncp_add_handle_path(server, file->volNumber,
 367                             file->DosDirNum, 1, NULL);
 368 
 369         if ((result = ncp_request(server, 87)) != 0)
 370         {
 371                 ncp_unlock_server(server);
 372                 return result;
 373         }
 374 
 375         ncp_unlock_server(server);
 376         return 0;
 377 }
 378 
 379 int
 380 ncp_del_file_or_subdir(struct ncp_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 381                        struct nw_info_struct *dir, char *name)
 382 {
 383         int result;
 384 
 385         ncp_init_request(server);
 386         ncp_add_byte(server, 8); /* subfunction */
 387         ncp_add_byte(server, 0); /* dos name space */
 388         ncp_add_byte(server, 0); /* reserved */
 389         ncp_add_word(server, 0x8006); /* search attribs: all */
 390         ncp_add_handle_path(server, dir->volNumber,
 391                             dir->DosDirNum, 1, name);
 392         
 393         if ((result = ncp_request(server, 87)) != 0)
 394         {
 395                 ncp_unlock_server(server);
 396                 return result;
 397         }
 398 
 399         ncp_unlock_server(server);
 400         return 0;
 401 }
 402 
 403 static inline void
 404 ConvertToNWfromDWORD ( __u32 sfd , __u8 ret[6] )
     /* [previous][next][first][last][top][bottom][index][help] */
 405 {
 406     __u16 *dest = (__u16 *) ret;
 407     memcpy(&(dest[1]), &sfd, 4);
 408     dest[0] = dest[1] + 1;
 409     return;
 410 }
 411 
 412 /* If both dir and name are NULL, then in target there's already a
 413    looked-up entry that wants to be opened. */
 414 int
 415 ncp_open_create_file_or_subdir(struct ncp_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 416                                struct nw_info_struct *dir, char *name,
 417                                int open_create_mode,
 418                                __u32 create_attributes,
 419                                int desired_acc_rights,
 420                                struct nw_file_info *target)
 421 {
 422         int result;
 423         __u16 search_attribs = 0x0006;
 424 
 425         if ((create_attributes & aDIR) != 0)
 426         {
 427                 search_attribs |= 0x8000;
 428         }
 429 
 430         ncp_init_request(server);
 431         ncp_add_byte(server, 1); /* subfunction */
 432         ncp_add_byte(server, 0); /* dos name space */
 433         ncp_add_byte(server, open_create_mode);
 434         ncp_add_word(server, search_attribs);
 435         ncp_add_dword(server, RIM_ALL);
 436         ncp_add_dword(server, create_attributes);
 437         /* The desired acc rights seem to be the inherited rights mask
 438            for directories */
 439         ncp_add_word(server, desired_acc_rights);
 440 
 441         if (dir != NULL)
 442         {
 443                 ncp_add_handle_path(server, dir->volNumber,
 444                                     dir->DosDirNum, 1, name);
 445         }
 446         else
 447         {
 448                 ncp_add_handle_path(server,
 449                                     target->i.volNumber, target->i.DosDirNum,
 450                                     1, NULL);
 451         }       
 452 
 453         if ((result = ncp_request(server, 87)) != 0)
 454         {
 455                 ncp_unlock_server(server);
 456                 return result;
 457         }
 458 
 459         target->opened = 1;
 460         target->server_file_handle = ncp_reply_dword(server, 0);
 461         target->open_create_action = ncp_reply_byte(server, 4);
 462 
 463         if (dir != NULL)
 464         {
 465                 /* in target there's a new finfo to fill */
 466                 ncp_extract_file_info(ncp_reply_data(server, 5), &(target->i));
 467         }
 468 
 469         ConvertToNWfromDWORD(target->server_file_handle, target->file_handle);
 470 
 471         ncp_unlock_server(server);
 472         return 0;
 473 }
 474         
 475 
 476 int
 477 ncp_initialize_search(struct ncp_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 478                       struct nw_info_struct *dir,
 479                       struct nw_search_sequence *target)
 480 {
 481         int result;
 482 
 483         ncp_init_request(server);
 484         ncp_add_byte(server, 2); /* subfunction */
 485         ncp_add_byte(server, 0); /* dos name space */
 486         ncp_add_byte(server, 0); /* reserved */
 487         ncp_add_handle_path(server, dir->volNumber, dir->DosDirNum, 1, NULL);
 488         
 489         if ((result = ncp_request(server, 87)) != 0)
 490         {
 491                 ncp_unlock_server(server);
 492                 return result;
 493         }
 494 
 495         memcpy(target, ncp_reply_data(server, 0), sizeof(*target));
 496 
 497         ncp_unlock_server(server);
 498         return 0;
 499 }
 500         
 501 /* Search for everything */
 502 int
 503 ncp_search_for_file_or_subdir(struct ncp_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 504                               struct nw_search_sequence *seq,
 505                               struct nw_info_struct *target)
 506 {
 507         int result;
 508 
 509         ncp_init_request(server);
 510         ncp_add_byte(server, 3); /* subfunction */
 511         ncp_add_byte(server, 0); /* dos name space */
 512         ncp_add_byte(server, 0); /* data stream (???) */
 513         ncp_add_word(server, 0xffff); /* Search attribs */
 514         ncp_add_dword(server, RIM_ALL); /* return info mask */
 515         ncp_add_mem(server, seq, 9);
 516         ncp_add_byte(server, 2); /* 2 byte pattern */
 517         ncp_add_byte(server, 0xff); /* following is a wildcard */
 518         ncp_add_byte(server, '*');
 519         
 520         if ((result = ncp_request(server, 87)) != 0)
 521         {
 522                 ncp_unlock_server(server);
 523                 return result;
 524         }
 525 
 526         memcpy(seq, ncp_reply_data(server, 0), sizeof(*seq));
 527         ncp_extract_file_info(ncp_reply_data(server, 10), target);
 528 
 529         ncp_unlock_server(server);
 530         return 0;
 531 }
 532 
 533 int
 534 ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 535                               struct nw_info_struct *old_dir, char *old_name,
 536                               struct nw_info_struct *new_dir, char *new_name)
 537 {
 538         int result;
 539 
 540         if (   (old_dir == NULL) || (old_name == NULL)
 541             || (new_dir == NULL) || (new_name == NULL))
 542                 return -EINVAL;
 543         
 544         ncp_init_request(server);
 545         ncp_add_byte(server, 4); /* subfunction */
 546         ncp_add_byte(server, 0); /* dos name space */
 547         ncp_add_byte(server, 1); /* rename flag */
 548         ncp_add_word(server, 0x8006); /* search attributes */
 549 
 550         /* source Handle Path */
 551         ncp_add_byte(server, old_dir->volNumber);
 552         ncp_add_dword(server, old_dir->DosDirNum);
 553         ncp_add_byte(server, 1);
 554         ncp_add_byte(server, 1); /* 1 source component */
 555 
 556         /* dest Handle Path */
 557         ncp_add_byte(server, new_dir->volNumber);
 558         ncp_add_dword(server, new_dir->DosDirNum);
 559         ncp_add_byte(server, 1);
 560         ncp_add_byte(server, 1); /* 1 destination component */
 561 
 562         /* source path string */
 563         ncp_add_pstring(server, old_name);
 564         /* dest path string */
 565         ncp_add_pstring(server, new_name);
 566 
 567         result = ncp_request(server, 87);
 568         ncp_unlock_server(server);
 569         return result;
 570 }
 571         
 572 
 573 /* We have to transfer to/from user space */
 574 int
 575 ncp_read(struct ncp_server *server, const char *file_id,
     /* [previous][next][first][last][top][bottom][index][help] */
 576          __u32 offset, __u16 to_read,
 577          char *target, int *bytes_read)
 578 {
 579         int result;
 580 
 581         ncp_init_request(server);
 582         ncp_add_byte(server, 0);
 583         ncp_add_mem(server, file_id, 6);
 584         ncp_add_dword(server, htonl(offset));
 585         ncp_add_word(server, htons(to_read));
 586 
 587         if ((result = ncp_request(server, 72)) != 0)
 588         {
 589                 ncp_unlock_server(server);
 590                 return result;
 591         }
 592 
 593         *bytes_read = ntohs(ncp_reply_word(server, 0));
 594 
 595         memcpy_tofs(target, ncp_reply_data(server, 2+(offset&1)), *bytes_read);
 596 
 597         ncp_unlock_server(server);
 598         return 0;
 599 }
 600 
 601 int
 602 ncp_write(struct ncp_server *server, const char *file_id,
     /* [previous][next][first][last][top][bottom][index][help] */
 603           __u32 offset, __u16 to_write,
 604           const char *source, int *bytes_written)
 605 {
 606         int result;
 607 
 608         ncp_init_request(server);
 609         ncp_add_byte(server, 0);
 610         ncp_add_mem(server, file_id, 6);
 611         ncp_add_dword(server, htonl(offset));
 612         ncp_add_word(server, htons(to_write));
 613         ncp_add_mem_fromfs(server, source, to_write);
 614 
 615         if ((result = ncp_request(server, 73)) != 0)
 616         {
 617                 ncp_unlock_server(server);
 618                 return result;
 619         }
 620 
 621         *bytes_written = to_write;
 622 
 623         ncp_unlock_server(server);
 624         return 0;
 625 }
 626 

/* [previous][next][first][last][top][bottom][index][help] */