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         result = ncp_request(server, 66);
 221         ncp_unlock_server(server);
 222         return result;
 223 }
 224 
 225 static void
 226 ncp_add_handle_path(struct ncp_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 227                     __u8 vol_num,
 228                     __u32 dir_base, int have_dir_base,
 229                     char *path)
 230 {
 231         ncp_add_byte(server, vol_num);
 232         ncp_add_dword(server, dir_base);
 233         if (have_dir_base != 0)
 234         {
 235                 ncp_add_byte(server, 1); /* dir_base */
 236         }
 237         else
 238         {
 239                 ncp_add_byte(server, 0xff); /* no handle */
 240         }
 241         if (path != NULL)
 242         {
 243                 ncp_add_byte(server, 1); /* 1 component */
 244                 ncp_add_pstring(server, path);
 245         }
 246         else
 247         {
 248                 ncp_add_byte(server, 0);
 249         }
 250 }
 251 
 252 static void
 253 ncp_extract_file_info(void *structure, struct nw_info_struct *target)
     /* [previous][next][first][last][top][bottom][index][help] */
 254 {
 255         __u8 *name_len;
 256         const int info_struct_size = sizeof(struct nw_info_struct) - 257;
 257 
 258         memcpy(target, structure, info_struct_size);
 259         name_len = structure + info_struct_size;
 260         target->nameLen = *name_len;
 261         strncpy(target->entryName, name_len+1, *name_len);
 262         target->entryName[*name_len] = '\0';
 263         return;
 264 }
 265 
 266 int
 267 ncp_obtain_info(struct ncp_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 268                 __u8 vol_num, __u32 dir_base,
 269                 char *path, /* At most 1 component */
 270                 struct nw_info_struct *target)
 271 {
 272         int result;
 273 
 274         if (target == NULL)
 275         {
 276                 return -EINVAL;
 277         }
 278 
 279         ncp_init_request(server);
 280         ncp_add_byte(server, 6); /* subfunction */
 281         ncp_add_byte(server, 0); /* dos name space */
 282         ncp_add_byte(server, 0); /* dos name space as dest */
 283         ncp_add_word(server, 0xff); /* get all */
 284         ncp_add_dword(server, RIM_ALL);
 285         ncp_add_handle_path(server, vol_num, dir_base, 1, path);
 286 
 287         if ((result = ncp_request(server, 87)) != 0)
 288         {
 289                 ncp_unlock_server(server);
 290                 return result;
 291         }
 292 
 293         ncp_extract_file_info(ncp_reply_data(server, 0), target);
 294         ncp_unlock_server(server);
 295         return 0;
 296 }
 297 
 298 int
 299 ncp_lookup_volume(struct ncp_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 300                   char *volname,
 301                   struct nw_info_struct *target)
 302 {
 303         int result;
 304         __u8  vol_num;
 305         __u32 dir_base;
 306 
 307         DPRINTK("ncp_lookup_volume: looking up vol %s\n", volname);
 308 
 309         ncp_init_request(server);
 310         ncp_add_byte(server, 22); /* Subfunction: Generate dir handle */
 311         ncp_add_byte(server, 0); /* DOS name space */
 312         ncp_add_byte(server, 0); /* reserved */
 313         ncp_add_byte(server, 0); /* reserved */
 314         ncp_add_byte(server, 0); /* reserved */
 315 
 316         ncp_add_byte(server, 0); /* faked volume number */
 317         ncp_add_dword(server, 0); /* faked dir_base */
 318         ncp_add_byte(server, 0xff); /* Don't have a dir_base */
 319         ncp_add_byte(server, 1); /* 1 path component */
 320         ncp_add_pstring(server, volname);
 321 
 322         if ((result = ncp_request(server, 87)) != 0)
 323         {
 324                 ncp_unlock_server(server);
 325                 return result;
 326         }
 327 
 328         dir_base = ncp_reply_dword(server, 4);
 329         vol_num  = ncp_reply_byte(server, 8);
 330         ncp_unlock_server(server);
 331 
 332         if ((result = ncp_obtain_info(server, vol_num, dir_base, NULL,
 333                                       target)) != 0)
 334         {
 335                 return result;
 336         }
 337 
 338         DPRINTK("ncp_lookup_volume: attribs = %X\n", target->attributes);
 339 
 340         target->nameLen = strlen(volname);
 341         strcpy(target->entryName, volname);
 342         return 0;
 343 }
 344 
 345 int
 346 ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 347                                    struct nw_info_struct *file,
 348                                    __u32 info_mask,
 349                                    struct nw_modify_dos_info *info)
 350 {
 351         int result;
 352 
 353         ncp_init_request(server);
 354         ncp_add_byte(server, 7); /* subfunction */
 355         ncp_add_byte(server, 0); /* dos name space */
 356         ncp_add_byte(server, 0); /* reserved */
 357         ncp_add_word(server, 0x8006); /* search attribs: all */
 358 
 359         ncp_add_dword(server, info_mask);
 360         ncp_add_mem(server, info, sizeof(*info));
 361         ncp_add_handle_path(server, file->volNumber,
 362                             file->DosDirNum, 1, NULL);
 363 
 364         result = ncp_request(server, 87);
 365         ncp_unlock_server(server);
 366         return result;
 367 }
 368 
 369 int
 370 ncp_del_file_or_subdir(struct ncp_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 371                        struct nw_info_struct *dir, char *name)
 372 {
 373         int result;
 374 
 375         ncp_init_request(server);
 376         ncp_add_byte(server, 8); /* subfunction */
 377         ncp_add_byte(server, 0); /* dos name space */
 378         ncp_add_byte(server, 0); /* reserved */
 379         ncp_add_word(server, 0x8006); /* search attribs: all */
 380         ncp_add_handle_path(server, dir->volNumber,
 381                             dir->DosDirNum, 1, name);
 382         
 383         result = ncp_request(server, 87);
 384         ncp_unlock_server(server);
 385         return result;
 386 }
 387 
 388 static inline void
 389 ConvertToNWfromDWORD ( __u32 sfd , __u8 ret[6] )
     /* [previous][next][first][last][top][bottom][index][help] */
 390 {
 391     __u16 *dest = (__u16 *) ret;
 392     memcpy(&(dest[1]), &sfd, 4);
 393     dest[0] = dest[1] + 1;
 394     return;
 395 }
 396 
 397 /* If both dir and name are NULL, then in target there's already a
 398    looked-up entry that wants to be opened. */
 399 int
 400 ncp_open_create_file_or_subdir(struct ncp_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 401                                struct nw_info_struct *dir, char *name,
 402                                int open_create_mode,
 403                                __u32 create_attributes,
 404                                int desired_acc_rights,
 405                                struct nw_file_info *target)
 406 {
 407         int result;
 408         __u16 search_attribs = 0x0006;
 409 
 410         if ((create_attributes & aDIR) != 0)
 411         {
 412                 search_attribs |= 0x8000;
 413         }
 414 
 415         ncp_init_request(server);
 416         ncp_add_byte(server, 1); /* subfunction */
 417         ncp_add_byte(server, 0); /* dos name space */
 418         ncp_add_byte(server, open_create_mode);
 419         ncp_add_word(server, search_attribs);
 420         ncp_add_dword(server, RIM_ALL);
 421         ncp_add_dword(server, create_attributes);
 422         /* The desired acc rights seem to be the inherited rights mask
 423            for directories */
 424         ncp_add_word(server, desired_acc_rights);
 425 
 426         if (dir != NULL)
 427         {
 428                 ncp_add_handle_path(server, dir->volNumber,
 429                                     dir->DosDirNum, 1, name);
 430         }
 431         else
 432         {
 433                 ncp_add_handle_path(server,
 434                                     target->i.volNumber, target->i.DosDirNum,
 435                                     1, NULL);
 436         }       
 437 
 438         if ((result = ncp_request(server, 87)) != 0)
 439         {
 440                 ncp_unlock_server(server);
 441                 return result;
 442         }
 443 
 444         target->opened = 1;
 445         target->server_file_handle = ncp_reply_dword(server, 0);
 446         target->open_create_action = ncp_reply_byte(server, 4);
 447 
 448         if (dir != NULL)
 449         {
 450                 /* in target there's a new finfo to fill */
 451                 ncp_extract_file_info(ncp_reply_data(server, 5), &(target->i));
 452         }
 453 
 454         ConvertToNWfromDWORD(target->server_file_handle, target->file_handle);
 455 
 456         ncp_unlock_server(server);
 457         return 0;
 458 }
 459         
 460 
 461 int
 462 ncp_initialize_search(struct ncp_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 463                       struct nw_info_struct *dir,
 464                       struct nw_search_sequence *target)
 465 {
 466         int result;
 467 
 468         ncp_init_request(server);
 469         ncp_add_byte(server, 2); /* subfunction */
 470         ncp_add_byte(server, 0); /* dos name space */
 471         ncp_add_byte(server, 0); /* reserved */
 472         ncp_add_handle_path(server, dir->volNumber, dir->DosDirNum, 1, NULL);
 473         
 474         if ((result = ncp_request(server, 87)) != 0)
 475         {
 476                 ncp_unlock_server(server);
 477                 return result;
 478         }
 479 
 480         memcpy(target, ncp_reply_data(server, 0), sizeof(*target));
 481 
 482         ncp_unlock_server(server);
 483         return 0;
 484 }
 485         
 486 /* Search for everything */
 487 int
 488 ncp_search_for_file_or_subdir(struct ncp_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 489                               struct nw_search_sequence *seq,
 490                               struct nw_info_struct *target)
 491 {
 492         int result;
 493 
 494         ncp_init_request(server);
 495         ncp_add_byte(server, 3); /* subfunction */
 496         ncp_add_byte(server, 0); /* dos name space */
 497         ncp_add_byte(server, 0); /* data stream (???) */
 498         ncp_add_word(server, 0xffff); /* Search attribs */
 499         ncp_add_dword(server, RIM_ALL); /* return info mask */
 500         ncp_add_mem(server, seq, 9);
 501         ncp_add_byte(server, 2); /* 2 byte pattern */
 502         ncp_add_byte(server, 0xff); /* following is a wildcard */
 503         ncp_add_byte(server, '*');
 504         
 505         if ((result = ncp_request(server, 87)) != 0)
 506         {
 507                 ncp_unlock_server(server);
 508                 return result;
 509         }
 510 
 511         memcpy(seq, ncp_reply_data(server, 0), sizeof(*seq));
 512         ncp_extract_file_info(ncp_reply_data(server, 10), target);
 513 
 514         ncp_unlock_server(server);
 515         return 0;
 516 }
 517 
 518 int
 519 ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 520                               struct nw_info_struct *old_dir, char *old_name,
 521                               struct nw_info_struct *new_dir, char *new_name)
 522 {
 523         int result;
 524 
 525         if (   (old_dir == NULL) || (old_name == NULL)
 526             || (new_dir == NULL) || (new_name == NULL))
 527                 return -EINVAL;
 528         
 529         ncp_init_request(server);
 530         ncp_add_byte(server, 4); /* subfunction */
 531         ncp_add_byte(server, 0); /* dos name space */
 532         ncp_add_byte(server, 1); /* rename flag */
 533         ncp_add_word(server, 0x8006); /* search attributes */
 534 
 535         /* source Handle Path */
 536         ncp_add_byte(server, old_dir->volNumber);
 537         ncp_add_dword(server, old_dir->DosDirNum);
 538         ncp_add_byte(server, 1);
 539         ncp_add_byte(server, 1); /* 1 source component */
 540 
 541         /* dest Handle Path */
 542         ncp_add_byte(server, new_dir->volNumber);
 543         ncp_add_dword(server, new_dir->DosDirNum);
 544         ncp_add_byte(server, 1);
 545         ncp_add_byte(server, 1); /* 1 destination component */
 546 
 547         /* source path string */
 548         ncp_add_pstring(server, old_name);
 549         /* dest path string */
 550         ncp_add_pstring(server, new_name);
 551 
 552         result = ncp_request(server, 87);
 553         ncp_unlock_server(server);
 554         return result;
 555 }
 556         
 557 
 558 /* We have to transfer to/from user space */
 559 int
 560 ncp_read(struct ncp_server *server, const char *file_id,
     /* [previous][next][first][last][top][bottom][index][help] */
 561          __u32 offset, __u16 to_read,
 562          char *target, int *bytes_read)
 563 {
 564         int result;
 565 
 566         ncp_init_request(server);
 567         ncp_add_byte(server, 0);
 568         ncp_add_mem(server, file_id, 6);
 569         ncp_add_dword(server, htonl(offset));
 570         ncp_add_word(server, htons(to_read));
 571 
 572         if ((result = ncp_request(server, 72)) != 0)
 573         {
 574                 ncp_unlock_server(server);
 575                 return result;
 576         }
 577 
 578         *bytes_read = ntohs(ncp_reply_word(server, 0));
 579 
 580         memcpy_tofs(target, ncp_reply_data(server, 2+(offset&1)), *bytes_read);
 581 
 582         ncp_unlock_server(server);
 583         return 0;
 584 }
 585 
 586 int
 587 ncp_write(struct ncp_server *server, const char *file_id,
     /* [previous][next][first][last][top][bottom][index][help] */
 588           __u32 offset, __u16 to_write,
 589           const char *source, int *bytes_written)
 590 {
 591         int result;
 592 
 593         ncp_init_request(server);
 594         ncp_add_byte(server, 0);
 595         ncp_add_mem(server, file_id, 6);
 596         ncp_add_dword(server, htonl(offset));
 597         ncp_add_word(server, htons(to_write));
 598         ncp_add_mem_fromfs(server, source, to_write);
 599 
 600         if ((result = ncp_request(server, 73)) != 0)
 601         {
 602                 ncp_unlock_server(server);
 603                 return result;
 604         }
 605 
 606         *bytes_written = to_write;
 607 
 608         ncp_unlock_server(server);
 609         return 0;
 610 }
 611 

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