root/fs/smbfs/proc.c

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

DEFINITIONS

This source file includes following definitions.
  1. smb_encode_word
  2. smb_decode_word
  3. smb_encode_smb_length
  4. smb_encode_dialect
  5. smb_encode_ascii
  6. smb_encode_vblock
  7. smb_decode_data
  8. smb_name_mangle
  9. utc2local
  10. local2utc
  11. date_dos2unix
  12. date_unix2dos
  13. smb_len
  14. smb_bcc
  15. smb_valid_packet
  16. smb_verify
  17. smb_errno
  18. print_char
  19. smb_dump_packet
  20. smb_lock_server
  21. smb_unlock_server
  22. smb_request_ok
  23. smb_retry
  24. smb_request_ok_unlock
  25. smb_setup_header
  26. smb_setup_header_exclusive
  27. smb_proc_open
  28. smb_proc_close
  29. smb_proc_read
  30. smb_proc_read_raw
  31. smb_proc_write
  32. smb_proc_write_raw
  33. smb_proc_do_create
  34. smb_proc_create
  35. smb_proc_mknew
  36. smb_proc_mv
  37. smb_proc_mkdir
  38. smb_proc_rmdir
  39. smb_proc_unlink
  40. smb_proc_trunc
  41. smb_decode_dirent
  42. smb_proc_readdir_short
  43. smb_decode_long_dirent
  44. smb_proc_readdir_long
  45. smb_proc_readdir
  46. smb_proc_getattr_core
  47. smb_proc_getattrE
  48. smb_proc_getattr
  49. smb_proc_setattr_core
  50. smb_proc_setattrE
  51. smb_proc_setattr
  52. smb_proc_dskattr
  53. smb_proc_reconnect
  54. smb_proc_connect
  55. smb_proc_disconnect
  56. smb_printerr

   1 /*
   2  *  proc.c
   3  *
   4  *  Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke
   5  *
   6  */
   7 
   8 #include <linux/config.h>
   9 #ifdef MODULE
  10 #include <linux/module.h>
  11 #include <linux/version.h>
  12 #endif
  13 
  14 
  15 #include <linux/fs.h>
  16 #include <linux/smbno.h>
  17 #include <linux/smb_fs.h>
  18 #include <linux/types.h>
  19 #include <linux/errno.h>
  20 #include <linux/malloc.h>
  21 #include <linux/stat.h>
  22 #include <linux/fcntl.h>
  23 #include <asm/segment.h>
  24 #include <asm/string.h>
  25 
  26 #define ARCH i386
  27 #define SMB_VWV(packet)  ((packet) + SMB_HEADER_LEN)
  28 #define SMB_CMD(packet)  ((packet)[8])
  29 #define SMB_WCT(packet)  ((packet)[SMB_HEADER_LEN - 1])
  30 #define SMB_BCC(packet)  smb_bcc(packet)
  31 #define SMB_BUF(packet)  ((packet) + SMB_HEADER_LEN + SMB_WCT(packet) * 2 + 2)
  32 
  33 #define SMB_DIRINFO_SIZE 43
  34 #define SMB_STATUS_SIZE  21
  35 
  36 #define HI_WORD(l) ((word)(l >> 16))
  37 #define LO_WORD(l) ((word)(l % 0xFFFF))
  38 
  39 void smb_printerr(int class, int num);
  40 static int smb_request_ok(struct smb_server *s, int command, int wct, int bcc);
  41 
  42 /*****************************************************************************/
  43 /*                                                                           */
  44 /*  Encoding/Decoding section                                                */
  45 /*                                                                           */
  46 /*****************************************************************************/
  47 
  48 static byte *
  49 smb_encode_word(byte *p, word data)
     /* [previous][next][first][last][top][bottom][index][help] */
  50 {
  51 #if (ARCH == i386)
  52         *((word *)p) = data;
  53 #else
  54         p[0] = data & 0x00ffU;
  55         p[1] = (data & 0xff00U) >> 8;
  56 #error "Non-Intel"
  57 #endif
  58         return &p[2];
  59 }
  60 
  61 static byte *
  62 smb_decode_word(byte *p, word *data)
     /* [previous][next][first][last][top][bottom][index][help] */
  63 {
  64 #if (ARCH == i386)
  65         *data = *(word *)p;
  66 #else
  67         *data = (word) p[0] | p[1] << 8;
  68 #endif 
  69         return &p[2];
  70 }
  71 
  72 byte *
  73 smb_encode_smb_length(byte *p, dword len)
     /* [previous][next][first][last][top][bottom][index][help] */
  74 {
  75         p[0] = p[1] = 0;
  76         p[2] = (len & 0xFF00) >> 8;
  77         p[3] = (len & 0xFF);
  78         if (len > 0xFFFF)
  79                 p[1] |= 0x01;
  80         return &p[4];
  81 }
  82 
  83 static byte *
  84 smb_encode_dialect(byte *p, const byte *name, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
  85 {
  86         *p ++ = 2;
  87         strcpy(p, name);
  88         return p + len + 1;
  89 }
  90 
  91 static byte *
  92 smb_encode_ascii(byte *p, const byte *name, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
  93 {
  94         *p ++ = 4;
  95         strcpy(p, name);
  96         return p + len + 1;
  97 }
  98 
  99 static byte *
 100 smb_encode_vblock(byte *p, const byte *data, word len, int fs)
     /* [previous][next][first][last][top][bottom][index][help] */
 101 {
 102         *p ++ = 5;
 103         p = smb_encode_word(p, len);
 104         if (fs)
 105                 memcpy_fromfs(p, data, len);
 106         else
 107                 memcpy(p, data, len);
 108         return p + len;
 109 }
 110 
 111 static byte *
 112 smb_decode_data(byte *p, byte *data, word *data_len, int fs)
     /* [previous][next][first][last][top][bottom][index][help] */
 113 {
 114         word len;
 115 
 116         if (!(*p == 1 || *p == 5)) {
 117                 printk("smb_decode_data: Warning! Data block not starting "
 118                        "with 1 or 5\n");
 119         }
 120 
 121         len = WVAL(p, 1);
 122         p += 3;
 123 
 124         if (fs)
 125                 memcpy_tofs(data, p, len);
 126         else
 127                 memcpy(data, p, len);
 128 
 129         *data_len = len;
 130 
 131         return p + len;
 132 }
 133 
 134 static byte *
 135 smb_name_mangle(byte *p, const byte *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 136 {
 137         int len, pad = 0;
 138 
 139         len = strlen(name);
 140 
 141         if (len < 16)
 142                 pad = 16 - len;
 143 
 144         *p ++ = 2 * (len + pad);
 145 
 146         while (*name) {
 147                 *p ++ = (*name >> 4) + 'A';
 148                 *p ++ = (*name & 0x0F) + 'A';
 149                 name ++;
 150         }
 151         while (pad --) {
 152                 *p ++ = 'C';
 153                 *p ++ = 'A';
 154         }
 155         *p++ = '\0';
 156         
 157         return p;
 158 }
 159 
 160 /* The following are taken directly from msdos-fs */
 161 
 162 /* Linear day numbers of the respective 1sts in non-leap years. */
 163 
 164 static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 };
 165                   /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */
 166 
 167 
 168 extern struct timezone sys_tz;
 169 
 170 static int
 171 utc2local(int time)
     /* [previous][next][first][last][top][bottom][index][help] */
 172 {
 173         return time - sys_tz.tz_minuteswest*60;
 174 }
 175 
 176 static int
 177 local2utc(int time)
     /* [previous][next][first][last][top][bottom][index][help] */
 178 {
 179         return time + sys_tz.tz_minuteswest*60;
 180 }
 181 
 182 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
 183 
 184 static int
 185 date_dos2unix(unsigned short time,unsigned short date)
     /* [previous][next][first][last][top][bottom][index][help] */
 186 {
 187         int month,year,secs;
 188 
 189         month = ((date >> 5) & 15)-1;
 190         year = date >> 9;
 191         secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400*
 192             ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
 193             month < 2 ? 1 : 0)+3653);
 194                         /* days since 1.1.70 plus 80's leap day */
 195         return local2utc(secs);
 196 }
 197 
 198 
 199 /* Convert linear UNIX date to a MS-DOS time/date pair. */
 200 
 201 static void
 202 date_unix2dos(int unix_date,unsigned short *time, unsigned short *date)
     /* [previous][next][first][last][top][bottom][index][help] */
 203 {
 204         int day,year,nl_day,month;
 205 
 206         unix_date = utc2local(unix_date);
 207         *time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+
 208             (((unix_date/3600) % 24) << 11);
 209         day = unix_date/86400-3652;
 210         year = day/365;
 211         if ((year+3)/4+365*year > day) year--;
 212         day -= (year+3)/4+365*year;
 213         if (day == 59 && !(year & 3)) {
 214                 nl_day = day;
 215                 month = 2;
 216         }
 217         else {
 218                 nl_day = (year & 3) || day <= 59 ? day : day-1;
 219                 for (month = 0; month < 12; month++)
 220                         if (day_n[month] > nl_day) break;
 221         }
 222         *date = nl_day-day_n[month-1]+1+(month << 5)+(year << 9);
 223 }
 224 
 225 
 226 
 227 /*****************************************************************************/
 228 /*                                                                           */
 229 /*  Support section.                                                         */
 230 /*                                                                           */
 231 /*****************************************************************************/
 232 
 233 dword
 234 smb_len(byte *packet) 
     /* [previous][next][first][last][top][bottom][index][help] */
 235 {
 236         return ((packet[1] & 0x1) << 16L) | (packet[2] << 8L) | (packet[3]);
 237 }
 238 
 239 static word
 240 smb_bcc(byte *packet)
     /* [previous][next][first][last][top][bottom][index][help] */
 241 {
 242         int pos = SMB_HEADER_LEN + SMB_WCT(packet) * sizeof(word);
 243 #if (ARCH == i386)
 244         return *((word *)((byte *)packet + pos));
 245 #else
 246         return packet[pos] | packet[pos+1] << 8;
 247 #endif
 248 }
 249 
 250 /* smb_valid_packet: We check if packet fulfills the basic
 251    requirements of a smb packet */
 252 
 253 static int
 254 smb_valid_packet(byte *packet)
     /* [previous][next][first][last][top][bottom][index][help] */
 255 {
 256         DDPRINTK("len: %ld, wct: %d, bcc: %d\n",
 257                  smb_len(packet), SMB_WCT(packet), SMB_BCC(packet));
 258         return (   packet[4] == 0xff
 259                 && packet[5] == 'S'
 260                 && packet[6] == 'M'
 261                 && packet[7] == 'B'
 262                 && (smb_len(packet) + 4 == SMB_HEADER_LEN
 263                     + SMB_WCT(packet) * 2 + SMB_BCC(packet)));
 264 }
 265 
 266 /* smb_verify: We check if we got the answer we expected, and if we
 267    got enough data. If bcc == -1, we don't care. */
 268 
 269 static int
 270 smb_verify(byte *packet, int command, int wct, int bcc)
     /* [previous][next][first][last][top][bottom][index][help] */
 271 {
 272         return (SMB_CMD(packet) == command &&
 273                 SMB_WCT(packet) >= wct &&
 274                 (bcc == -1 || SMB_BCC(packet) == bcc)) ? 0 : -EIO;
 275 }
 276 
 277 static int
 278 smb_errno(int errcls, int error)
     /* [previous][next][first][last][top][bottom][index][help] */
 279 {
 280 
 281 #if DEBUG_SMB > 1
 282         if (errcls) {
 283                 printk("smb_errno: ");
 284                 smb_printerr(errcls, error);
 285                 printk("\n");
 286         }
 287 #endif
 288 
 289         if (errcls == ERRDOS) 
 290                 switch (error) {
 291                         case ERRbadfunc:    return EINVAL;
 292                         case ERRbadfile:    return ENOENT;
 293                         case ERRbadpath:    return ENOENT;
 294                         case ERRnofids:     return EMFILE;
 295                         case ERRnoaccess:   return EACCES;
 296                         case ERRbadfid:     return EBADF;
 297                         case ERRbadmcb:     return EREMOTEIO;
 298                         case ERRnomem:      return ENOMEM;
 299                         case ERRbadmem:     return EFAULT;
 300                         case ERRbadenv:     return EREMOTEIO;
 301                         case ERRbadformat:  return EREMOTEIO;
 302                         case ERRbadaccess:  return EACCES;
 303                         case ERRbaddata:    return E2BIG;
 304                         case ERRbaddrive:   return ENXIO;
 305                         case ERRremcd:      return EREMOTEIO;
 306                         case ERRdiffdevice: return EXDEV;
 307                         case ERRnofiles:    return 0;
 308                         case ERRbadshare:   return ETXTBSY;
 309                         case ERRlock:       return EDEADLOCK;
 310                         case ERRfilexists:  return EEXIST;
 311                         case 87:            return 0; /* Unknown error!! */
 312                         /* This next error seems to occur on an mv when
 313                          * the destination exists */
 314                         case 183:           return EEXIST;
 315                         default:            return EIO;
 316                 }
 317         else if (errcls == ERRSRV) 
 318                 switch (error) {
 319                         case ERRerror: return ENFILE;
 320                         case ERRbadpw: return EINVAL;
 321                         case ERRbadtype: return EIO;
 322                         case ERRaccess: return EACCES;
 323                         default: return EIO;
 324                 }
 325         else if (errcls == ERRHRD) 
 326                 switch (error) {
 327                         case ERRnowrite: return EROFS; 
 328                         case ERRbadunit: return ENODEV;
 329                         case ERRnotready: return EUCLEAN;
 330                         case ERRbadcmd: return EIO;
 331                         case ERRdata: return EIO;
 332                         case ERRbadreq: return ERANGE;
 333                         case ERRbadshare: return ETXTBSY;
 334                         case ERRlock: return EDEADLOCK;
 335                         default: return EIO;
 336                 }
 337         else if (errcls == ERRCMD) 
 338                 return EIO;
 339         return 0;
 340 }
 341 
 342 #if DEBUG_SMB > 0
 343 static char
 344 print_char(char c)
     /* [previous][next][first][last][top][bottom][index][help] */
 345 {
 346         if ((c < ' ') || (c > '~'))
 347                 return '.';
 348         return c;
 349 }
 350 
 351 static void
 352 smb_dump_packet(byte *packet) {
     /* [previous][next][first][last][top][bottom][index][help] */
 353         int i, j, len;
 354         int errcls, error;
 355 
 356         errcls = (int)packet[9];
 357         error  = (int)(int)(packet[11]|packet[12]<<8);
 358 
 359         printk("smb_len = %d  valid = %d    \n", 
 360                len = smb_len(packet), smb_valid_packet(packet));
 361         printk("smb_cmd = %d  smb_wct = %d  smb_bcc = %d\n", 
 362                packet[8], SMB_WCT(packet), SMB_BCC(packet)); 
 363         printk("smb_rcls = %d smb_err = %d\n", errcls, error);
 364 
 365         if (errcls) {
 366                 smb_printerr(errcls, error);
 367                 printk("\n");
 368         }
 369 
 370         if (len > 100)
 371                 len = 100;
 372         
 373         for (i = 0; i < len; i += 10) {
 374                 printk("%03d:", i);
 375                 for (j = i; j < i+10; j++)
 376                         if (j < len)
 377                                 printk("%02x ", packet[j]);
 378                         else
 379                                 printk("   ");
 380                 printk(": ");
 381                 for (j = i; j < i+10; j++)
 382                         if (j < len)
 383                                 printk("%c", print_char(packet[j]));
 384                 printk("\n");
 385         }
 386 }
 387 #endif
 388 
 389 static void
 390 smb_lock_server(struct smb_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
 391 {
 392         while (server->lock)
 393                 sleep_on(&server->wait);
 394         server->lock = 1;
 395 }
 396 
 397 static void
 398 smb_unlock_server(struct smb_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
 399 {
 400         if (server->lock != 1) {
 401                 printk("smb_unlock_server: was not locked!\n");
 402         }
 403 
 404         server->lock = 0;
 405         wake_up(&server->wait);
 406 }
 407         
 408 /* smb_request_ok: We expect the server to be locked. Then we do the
 409    request and check the answer completely. When smb_request_ok
 410    returns 0, you can be quite sure that everything went well. When
 411    the answer is <=0, the returned number is a valid unix errno. */
 412 
 413 static int
 414 smb_request_ok(struct smb_server *s, int command, int wct, int bcc)
     /* [previous][next][first][last][top][bottom][index][help] */
 415 {
 416         int result = 0;
 417         s->rcls = 0;
 418         s->err  = 0;
 419 
 420         if (smb_request(s) < 0) {
 421                 DPRINTK("smb_request failed\n");
 422                 result = -EIO;
 423         }
 424         else if (smb_valid_packet(s->packet) != 0) {
 425                 DPRINTK("not a valid packet!\n");
 426                 result = -EIO;
 427         }
 428         else if (s->rcls != 0) {
 429                 result =  -smb_errno(s->rcls, s->err);
 430         }
 431         else if (smb_verify(s->packet, command, wct, bcc) != 0) {
 432                 DPRINTK("smb_verify failed\n");
 433                 result = -EIO;
 434         }
 435 
 436         return result;
 437 }
 438 
 439 /* smb_retry: This function should be called when smb_request_ok has
 440    indicated an error. If the error was indicated because the
 441    connection was killed, we try to reconnect. If smb_retry returns 0,
 442    the error was indicated for another reason, so a retry would not be
 443    of any use. */
 444 
 445 static int
 446 smb_retry(struct smb_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
 447 {
 448         if (server->state != CONN_INVALID) {
 449                 return 0;
 450         }
 451         
 452         if (smb_release(server) < 0) {
 453                 DPRINTK("smb_retry: smb_release failed\n");
 454                 server->state = CONN_RETRIED;
 455                 return 0;
 456         }
 457         if(smb_proc_reconnect(server) < 0) {
 458                 DPRINTK("smb_proc_reconnect failed\n");
 459                 server->state = CONN_RETRIED;
 460                 return 0;
 461         }
 462 
 463         server->state = CONN_VALID;
 464         return 1;
 465 }
 466 
 467 static int
 468 smb_request_ok_unlock(struct smb_server *s, int command, int wct, int bcc)
     /* [previous][next][first][last][top][bottom][index][help] */
 469 {
 470         int result = smb_request_ok(s, command, wct, bcc);
 471 
 472         smb_unlock_server(s);
 473 
 474         return result;
 475 }
 476         
 477 /* smb_setup_header: We completely set up the packet. You only have to
 478    insert the command-specific fields */
 479 
 480 static byte *
 481 smb_setup_header(struct smb_server *server, byte command, word wct, word bcc)
     /* [previous][next][first][last][top][bottom][index][help] */
 482 {
 483         dword xmit_len = SMB_HEADER_LEN + wct * sizeof(word) + bcc + 2;
 484         byte *p = server->packet;
 485         byte *buf = server->packet;
 486 
 487         p = smb_encode_smb_length(p, xmit_len);
 488 
 489         BSET(p,0,0xff);
 490         BSET(p,1,'S');
 491         BSET(p,2,'M');
 492         BSET(p,3,'B');
 493         BSET(p,4,command);
 494 
 495         p += 5;
 496         memset(p, '\0', 19);
 497         p += 19;
 498         p += 8;
 499 
 500         WSET(buf, smb_tid, server->tid);
 501         WSET(buf, smb_pid, server->pid);
 502         WSET(buf, smb_uid, server->server_uid);
 503         WSET(buf, smb_mid, server->mid);
 504 
 505         if (server->protocol > PROTOCOL_CORE) {
 506                 BSET(buf, smb_flg, 0x8);
 507                 WSET(buf, smb_flg2, 0x3);
 508         }
 509         
 510         *p++ = wct;             /* wct */
 511         p += 2*wct;
 512         WSET(p, 0, bcc);
 513         return p+2;
 514 }
 515 
 516 /* smb_setup_header_exclusive waits on server->lock and locks the
 517    server, when it's free. You have to unlock it manually when you're
 518    finished with server->packet! */
 519 
 520 static byte *
 521 smb_setup_header_exclusive(struct smb_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 522                            byte command, word wct, word bcc)
 523 {
 524         smb_lock_server(server);
 525         return smb_setup_header(server, command, wct, bcc);
 526 }
 527 
 528 
 529 /*****************************************************************************/
 530 /*                                                                           */
 531 /*  File operation section.                                                  */
 532 /*                                                                           */
 533 /*****************************************************************************/
 534 
 535 int
 536 smb_proc_open(struct smb_server *server, const char *pathname, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 537               struct smb_dirent *entry)
 538 {
 539         int error;
 540         char* p;
 541         char* buf = server->packet;
 542         const word o_attr = aSYSTEM | aHIDDEN | aDIR;
 543 
 544         DPRINTK("smb_proc_open: path=%s\n", pathname);
 545 
 546         smb_lock_server(server);
 547 
 548  retry:
 549         p = smb_setup_header(server, SMBopen, 2, 2 + len);
 550         WSET(buf, smb_vwv0, 0x42); /* read/write */
 551         WSET(buf, smb_vwv1, o_attr);
 552         smb_encode_ascii(p, pathname, len);
 553 
 554         if ((error = smb_request_ok(server, SMBopen, 7, 0)) != 0) {
 555 
 556                 if (smb_retry(server)) {
 557                         goto retry;
 558                 }
 559                 
 560                 if (error != -EACCES) {
 561                         smb_unlock_server(server);
 562                         return error;
 563                 }
 564 
 565                 p = smb_setup_header(server, SMBopen, 2, 2 + len);
 566                 WSET(buf, smb_vwv0, 0x40); /* read only */
 567                 WSET(buf, smb_vwv1, o_attr);
 568                 smb_encode_ascii(p, pathname, len);
 569 
 570                 if ((error = smb_request_ok(server, SMBopen, 7, 0)) != 0) {
 571                         if (smb_retry(server)) {
 572                                 goto retry;
 573                         }
 574                         smb_unlock_server(server);
 575                         return error;
 576                 }
 577         }
 578 
 579         /* We should now have data in vwv[0..6]. */
 580 
 581         entry->fileid = WVAL(buf, smb_vwv0);
 582         entry->attr   = WVAL(buf, smb_vwv1);
 583         entry->ctime = entry->atime =
 584                 entry->mtime = local2utc(DVAL(buf, smb_vwv2));
 585         entry->size   = DVAL(buf, smb_vwv4);
 586         entry->access = WVAL(buf, smb_vwv6);
 587 
 588         smb_unlock_server(server);
 589 
 590         entry->access &= 3;
 591         DPRINTK("smb_proc_open: entry->access = %d\n", entry->access);
 592         return 0;
 593 }
 594 
 595 /* smb_proc_close: in finfo->mtime we can send a modification time to
 596    the server */
 597 int
 598 smb_proc_close(struct smb_server *server, struct smb_dirent *finfo)
     /* [previous][next][first][last][top][bottom][index][help] */
 599 {
 600         char *buf = server->packet;
 601 
 602         smb_setup_header_exclusive(server, SMBclose, 3, 0);
 603         WSET(buf, smb_vwv0, finfo->fileid);
 604         DSET(buf, smb_vwv1, utc2local(finfo->mtime));
 605 
 606         return smb_request_ok_unlock(server, SMBclose, 0, 0);
 607 }
 608 
 609 /* In smb_proc_read and smb_proc_write we do not retry, because the
 610    file-id would not be valid after a reconnection. */
 611 
 612 /* smb_proc_read: fs indicates if it should be copied with
 613    memcpy_tofs. */
 614 
 615 int
 616 smb_proc_read(struct smb_server *server, struct smb_dirent *finfo, 
     /* [previous][next][first][last][top][bottom][index][help] */
 617               off_t offset, long count, char *data, int fs)
 618 {
 619         word returned_count, data_len;
 620         char *buf = server->packet;
 621         int error;
 622 
 623         smb_setup_header_exclusive(server, SMBread, 5, 0);
 624 
 625         WSET(buf, smb_vwv0, finfo->fileid);
 626         WSET(buf, smb_vwv1, count);
 627         DSET(buf, smb_vwv2, offset);
 628         WSET(buf, smb_vwv4, 0);
 629         
 630         if ((error = smb_request_ok(server, SMBread, 5, -1)) < 0) {
 631                 smb_unlock_server(server);
 632                 return error;
 633         }
 634 
 635         returned_count = WVAL(buf, smb_vwv0);
 636         
 637         smb_decode_data(SMB_BUF(server->packet), data, &data_len, fs);
 638 
 639         smb_unlock_server(server);
 640 
 641         if (returned_count != data_len) {
 642                 printk("smb_proc_read: Warning, returned_count != data_len\n");
 643                 printk("smb_proc_read: ret_c=%d, data_len=%d\n",
 644                        returned_count, data_len);
 645         }
 646 
 647         return data_len;
 648 }
 649 
 650 /* count must be <= 65535. No error number is returned.  A result of 0
 651    indicates an error, which has to be investigated by a normal read
 652    call. */
 653 int
 654 smb_proc_read_raw(struct smb_server *server, struct smb_dirent *finfo, 
     /* [previous][next][first][last][top][bottom][index][help] */
 655                   off_t offset, long count, char *data)
 656 {
 657         char *buf = server->packet;
 658         int result;
 659 
 660         if ((count <= 0) || (count > 65535)) {
 661                 return -EINVAL;
 662         }
 663 
 664         smb_setup_header_exclusive(server, SMBreadbraw, 8, 0);
 665 
 666         WSET(buf, smb_vwv0, finfo->fileid);
 667         DSET(buf, smb_vwv1, offset);
 668         WSET(buf, smb_vwv3, count);
 669         WSET(buf, smb_vwv4, 0);
 670         DSET(buf, smb_vwv5, 0);
 671 
 672         result = smb_request_read_raw(server, data, count);
 673         smb_unlock_server(server);
 674         return result;
 675 }
 676 
 677 int
 678 smb_proc_write(struct smb_server *server, struct smb_dirent *finfo,
     /* [previous][next][first][last][top][bottom][index][help] */
 679                off_t offset, int count, const char *data)
 680 {
 681         int res = 0;
 682         char *buf = server->packet;
 683         byte *p;
 684 
 685         p = smb_setup_header_exclusive(server, SMBwrite, 5, count + 3);
 686         WSET(buf, smb_vwv0, finfo->fileid);
 687         WSET(buf, smb_vwv1, count);
 688         DSET(buf, smb_vwv2, offset);
 689         WSET(buf, smb_vwv4, 0);
 690 
 691         *p++ = 1;
 692         WSET(p, 0, count);
 693         memcpy_fromfs(p+2, data, count);
 694 
 695         if ((res = smb_request_ok(server, SMBwrite, 1, 0)) >= 0) {
 696                 res = WVAL(buf, smb_vwv0);
 697         }
 698 
 699         smb_unlock_server(server);
 700 
 701         return res;
 702 }
 703 
 704 /* count must be <= 65535 */
 705 int
 706 smb_proc_write_raw(struct smb_server *server, struct smb_dirent *finfo, 
     /* [previous][next][first][last][top][bottom][index][help] */
 707                    off_t offset, long count, const char *data)
 708 {
 709         char *buf = server->packet;
 710         int result;
 711 
 712         if ((count <= 0) || (count > 65535)) {
 713                 return -EINVAL;
 714         }
 715 
 716         smb_setup_header_exclusive(server, SMBwritebraw, 11, 0);
 717 
 718         WSET(buf, smb_vwv0, finfo->fileid);
 719         WSET(buf, smb_vwv1, count);
 720         WSET(buf, smb_vwv2, 0); /* reserved */
 721         DSET(buf, smb_vwv3, offset);
 722         DSET(buf, smb_vwv5, 0); /* timeout */
 723         WSET(buf, smb_vwv7, 1); /* send final result response */
 724         DSET(buf, smb_vwv8, 0); /* reserved */
 725         WSET(buf, smb_vwv10, 0); /* no data in this buf */
 726         WSET(buf, smb_vwv11, 0); /* no data in this buf */
 727 
 728         result = smb_request_ok(server, SMBwritebraw, 1, 0);
 729 
 730         DPRINTK("smb_proc_write_raw: first request returned %d\n", result);
 731         
 732         if (result < 0) {
 733                 smb_unlock_server(server);
 734                 return result;
 735         }
 736         
 737         result = smb_request_write_raw(server, data, count);
 738 
 739         DPRINTK("smb_proc_write_raw: raw request returned %d\n", result);
 740         
 741         if (result > 0) {
 742                 /* We have to do the checks of smb_request_ok here as well */
 743                 if (smb_valid_packet(server->packet) != 0) {
 744                         DPRINTK("not a valid packet!\n");
 745                         result = -EIO;
 746                 } else if (server->rcls != 0) {
 747                         result = -smb_errno(server->rcls, server->err);
 748                 } else if (smb_verify(server->packet, SMBwritec,1,0) != 0) {
 749                         DPRINTK("smb_verify failed\n");
 750                         result = -EIO;
 751                 }
 752         }
 753 
 754         smb_unlock_server(server);
 755         return result;
 756 }
 757 
 758 
 759 /* smb_proc_do_create: We expect entry->attry & entry->ctime to be set. */
 760 
 761 static int
 762 smb_proc_do_create(struct smb_server *server, const char *path, int len, 
     /* [previous][next][first][last][top][bottom][index][help] */
 763                    struct smb_dirent *entry, word command)
 764 {
 765         int error;
 766         char *p;
 767         char *buf = server->packet;
 768 
 769         smb_lock_server(server);
 770  retry:
 771         p = smb_setup_header(server, command, 3, len + 2);
 772         WSET(buf, smb_vwv0, entry->attr);
 773         DSET(buf, smb_vwv1, utc2local(entry->ctime));
 774         smb_encode_ascii(p, path, len);
 775 
 776         if ((error = smb_request_ok(server, command, 1, 0)) < 0) {
 777                 if (smb_retry(server)) {
 778                         goto retry;
 779                 }
 780                 smb_unlock_server(server);
 781                 return error;
 782         }
 783 
 784         entry->opened = 1;
 785         entry->fileid = WVAL(buf, smb_vwv0);
 786         smb_unlock_server(server);
 787 
 788         smb_proc_close(server, entry);
 789 
 790         return 0;
 791 }
 792         
 793 int
 794 smb_proc_create(struct smb_server *server, const char *path, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 795                 struct smb_dirent *entry)
 796 {
 797         return smb_proc_do_create(server, path, len, entry, SMBcreate);
 798 }
 799 
 800 int
 801 smb_proc_mknew(struct smb_server *server, const char *path, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 802                struct smb_dirent *entry)
 803 {
 804         return smb_proc_do_create(server, path, len, entry, SMBmknew);
 805 }
 806 
 807 int
 808 smb_proc_mv(struct smb_server *server, 
     /* [previous][next][first][last][top][bottom][index][help] */
 809             const char *opath, const int olen,
 810             const char *npath, const int nlen)
 811 {
 812         char *p;
 813         char *buf = server->packet;
 814         int result;
 815 
 816         smb_lock_server(server);
 817 
 818  retry:
 819         p = smb_setup_header(server, SMBmv, 1, olen + nlen + 4);
 820         WSET(buf, smb_vwv0, 0);
 821         p = smb_encode_ascii(p, opath, olen);
 822         smb_encode_ascii(p, npath, olen);
 823 
 824         if ((result = smb_request_ok(server, SMBmv, 0, 0)) < 0) {
 825                 if (smb_retry(server)) {
 826                         goto retry;
 827                 }
 828         }
 829         smb_unlock_server(server);
 830         return result;
 831 }
 832 
 833 int
 834 smb_proc_mkdir(struct smb_server *server, const char *path, const int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 835 {
 836         char *p;
 837         int result;
 838 
 839         smb_lock_server(server);
 840 
 841  retry:
 842         p = smb_setup_header(server, SMBmkdir, 0, 2 + len);
 843         smb_encode_ascii(p, path, len);
 844 
 845         if ((result = smb_request_ok(server, SMBmkdir, 0, 0)) < 0) {
 846                 if (smb_retry(server)) {
 847                         goto retry;
 848                 }
 849         }
 850         smb_unlock_server(server);
 851         return result;
 852 }
 853 
 854 int
 855 smb_proc_rmdir(struct smb_server *server, const char *path, const int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 856 {
 857         char *p;
 858         int result;
 859 
 860         smb_lock_server(server);
 861 
 862  retry:
 863         p = smb_setup_header(server, SMBrmdir, 0, 2 + len);
 864         smb_encode_ascii(p, path, len);
 865 
 866         if ((result = smb_request_ok(server, SMBrmdir, 0, 0)) < 0) {
 867                 if (smb_retry(server)) {
 868                         goto retry;
 869                 }
 870         }
 871         smb_unlock_server(server);
 872         return result;
 873 }
 874 
 875 int
 876 smb_proc_unlink(struct smb_server *server, const char *path, const int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 877 {
 878         char *p;
 879         char *buf = server->packet;
 880         int result;
 881 
 882         smb_lock_server(server);
 883 
 884  retry:
 885         p = smb_setup_header(server, SMBunlink, 1, 2 + len);
 886         WSET(buf, smb_vwv0, 0);
 887         smb_encode_ascii(p, path, len);
 888 
 889         if ((result = smb_request_ok(server, SMBunlink, 0, 0)) < 0) {
 890                 if (smb_retry(server)) {
 891                         goto retry;
 892                 }
 893         }
 894         smb_unlock_server(server);
 895         return result;
 896 }
 897 
 898 int
 899 smb_proc_trunc(struct smb_server *server, word fid, dword length)
     /* [previous][next][first][last][top][bottom][index][help] */
 900 {
 901         char *p;
 902         char *buf = server->packet;
 903         int result;
 904 
 905         smb_lock_server(server);
 906 
 907  retry:
 908         p = smb_setup_header(server, SMBwrite, 5, 3);
 909         WSET(buf, smb_vwv0, fid);
 910         WSET(buf, smb_vwv1, 0);
 911         DSET(buf, smb_vwv2, length);
 912         WSET(buf, smb_vwv4, 0);
 913         smb_encode_ascii(p, "", 0);
 914         
 915         if ((result = smb_request_ok(server, SMBwrite, 1, 0)) < 0) {
 916                 if (smb_retry(server)) {
 917                         goto retry;
 918                 }
 919         }
 920         smb_unlock_server(server);
 921         return result;
 922 }
 923 
 924 static char *
 925 smb_decode_dirent(char *p, struct smb_dirent *entry)
     /* [previous][next][first][last][top][bottom][index][help] */
 926 {
 927         p += SMB_STATUS_SIZE;                  /* reserved (search_status) */
 928         entry->attr = BVAL(p, 0);
 929         entry->mtime = entry->atime = entry->ctime =
 930                 date_dos2unix(WVAL(p, 1), WVAL(p, 3));
 931         entry->size = DVAL(p, 5);
 932         memcpy(entry->path, p+9, 13);
 933         DDPRINTK("smb_decode_dirent: path = %s\n", entry->path);
 934         return p + 22;
 935 }
 936 
 937 /* This routine is used to read in directory entries from the network.
 938    Note that it is for short directory name seeks, i.e.: protocol <
 939    PROTOCOL_LANMAN2 */
 940 
 941 static int
 942 smb_proc_readdir_short(struct smb_server *server, struct inode *dir, int fpos,
     /* [previous][next][first][last][top][bottom][index][help] */
 943                        int cache_size, struct smb_dirent *entry)
 944 {
 945         char *p;
 946         char *buf;
 947         int error;
 948         int result;
 949         int i;
 950         int first, total_count;
 951         struct smb_dirent *current_entry;
 952         word bcc;
 953         word count;
 954         char status[SMB_STATUS_SIZE];
 955         int entries_asked = (server->max_xmit - 100) / SMB_DIRINFO_SIZE;
 956         int dirlen = strlen(SMB_FINFO(dir)->path);
 957         char mask[dirlen + 5];
 958 
 959         strcpy(mask, SMB_FINFO(dir)->path);
 960         strcat(mask, "\\*.*");
 961 
 962         DPRINTK("SMB call  readdir %d @ %d\n", cache_size, fpos);        
 963         DPRINTK("          mask = %s\n", mask);
 964 
 965         buf = server->packet;
 966 
 967         smb_lock_server(server);
 968 
 969  retry:
 970         first = 1;
 971         total_count = 0;
 972         current_entry = entry;
 973         
 974         while (1) {
 975                 if (first == 1) {
 976                         p = smb_setup_header(server, SMBsearch, 2,
 977                                              5 + strlen(mask));
 978                         WSET(buf, smb_vwv0, entries_asked);
 979                         WSET(buf, smb_vwv1, aDIR);
 980                         p = smb_encode_ascii(p, mask, strlen(mask));
 981                         *p ++ = 5;
 982                         p = smb_encode_word(p, 0);
 983                 } else {
 984                         p = smb_setup_header(server, SMBsearch, 2,
 985                                              5 + SMB_STATUS_SIZE);
 986                         WSET(buf, smb_vwv0, entries_asked);
 987                         WSET(buf, smb_vwv1, aDIR);
 988                         p = smb_encode_ascii(p, "", 0);
 989                         p = smb_encode_vblock(p, status, SMB_STATUS_SIZE, 0);
 990                 }
 991                 
 992                 if ((error = smb_request_ok(server, SMBsearch, 1, -1)) < 0) {
 993                         if (   (server->rcls == ERRDOS)
 994                             && (server->err  == ERRnofiles)) {
 995                                 result = total_count - fpos;
 996                                 goto unlock_return;
 997                         }
 998                         else
 999                         {
1000                                 if (smb_retry(server)) {
1001                                         goto retry;
1002                                 }
1003                                 result = error;
1004                                 goto unlock_return;
1005                         }
1006                 }
1007 
1008                 p = SMB_VWV(server->packet);
1009                 p = smb_decode_word(p, &count); /* vwv[0] = count-returned */
1010                 p = smb_decode_word(p, &bcc);           
1011                 
1012                 first = 0;
1013                 
1014                 if (count <= 0) {
1015                         result = total_count - fpos;
1016                         goto unlock_return;
1017                 }
1018                 if (bcc != count * SMB_DIRINFO_SIZE + 3) {
1019                         result = -EIO;
1020                         goto unlock_return;
1021                 }
1022 
1023                 p += 3; /* Skipping VBLOCK header (5, length lo, length hi). */
1024 
1025                 /* Read the last entry into the status field. */
1026                 memcpy(status,
1027                        SMB_BUF(server->packet) + 3 +
1028                        (count - 1) * SMB_DIRINFO_SIZE, 
1029                        SMB_STATUS_SIZE);
1030 
1031                 /* Now we are ready to parse smb directory entries. */
1032                 
1033                 for (i = 0; i < count; i ++) {
1034                         if (total_count < fpos) {
1035                                 p += SMB_DIRINFO_SIZE;
1036                                 DDPRINTK("smb_proc_readdir: skipped entry.\n");
1037                                 DDPRINTK("                  total_count = %d\n"
1038                                          "                i = %d, fpos = %d\n",
1039                                          total_count, i, fpos);
1040                         }
1041                         else if (total_count >= fpos + cache_size) {
1042                                 result = total_count - fpos;
1043                                 goto unlock_return;
1044                         }
1045                         else {
1046                                 p = smb_decode_dirent(p, current_entry);
1047                                 current_entry->f_pos = total_count;
1048                                 DDPRINTK("smb_proc_readdir: entry->f_pos = "
1049                                          "%lu\n", entry->f_pos);        
1050                                 current_entry += 1;
1051                         }
1052                         total_count += 1;
1053                 }
1054         }
1055  unlock_return:
1056         smb_unlock_server(server);
1057         return result;
1058 }
1059 
1060 /* interpret a long filename structure - this is mostly guesses at the
1061    moment.  The length of the structure is returned.  The structure of
1062    a long filename depends on the info level. 260 is used by NT and 2
1063    is used by OS/2. */
1064 
1065 static char *
1066 smb_decode_long_dirent(char *p, struct smb_dirent *finfo, int level)
     /* [previous][next][first][last][top][bottom][index][help] */
1067 {
1068         char *result;
1069 
1070         if (finfo) {
1071                 /* I have to set times to 0 here, because I do not
1072                    have specs about this for all info levels. */
1073                 finfo->ctime = finfo->mtime = finfo->atime = 0;
1074         }
1075 
1076         switch (level)
1077         {
1078         case 1:                 /* OS/2 understands this */
1079                 if (finfo)
1080                 {
1081                         DPRINTK("received entry\n");
1082                         strcpy(finfo->path,p+27);
1083                         finfo->len  = strlen(finfo->path);
1084                         finfo->size = DVAL(p,16);
1085                         finfo->attr = BVAL(p,24);
1086 
1087                         finfo->ctime = date_dos2unix(WVAL(p, 6), WVAL(p, 4));
1088                         finfo->atime = date_dos2unix(WVAL(p, 10), WVAL(p, 8));
1089                         finfo->mtime = date_dos2unix(WVAL(p, 14), WVAL(p, 12));
1090                 }
1091                 result = p + 28 + BVAL(p,26);
1092                 break;
1093 
1094         case 2:                 /* this is what OS/2 uses */
1095                 if (finfo)
1096                 {
1097                         strcpy(finfo->path,p+31);
1098                         finfo->len  = strlen(finfo->path);
1099                         finfo->size = DVAL(p,16);
1100                         finfo->attr = BVAL(p,24);
1101 #if 0
1102                         finfo->atime = make_unix_date2(p+8);
1103                         finfo->mtime = make_unix_date2(p+12);
1104 #endif
1105                 }
1106                 result = p + 32 + BVAL(p,30);
1107                 break;
1108 
1109         case 260:               /* NT uses this, but also accepts 2 */
1110                 result = p + WVAL(p,0);
1111                 if (finfo)
1112                 {
1113                         int namelen;
1114                         p += 4; /* next entry offset */
1115                         p += 4; /* fileindex */
1116                         /* finfo->ctime = interpret_filetime(p);*/
1117                         p += 8;
1118                         /* finfo->atime = interpret_filetime(p);*/
1119                         p += 8;
1120                         p += 8; /* write time */
1121                         /* finfo->mtime = interpret_filetime(p);*/
1122                         p += 8;
1123                         finfo->size = DVAL(p,0);
1124                         p += 8;
1125                         p += 8; /* alloc size */
1126                         finfo->attr = BVAL(p,0);
1127                         p += 4;
1128                         namelen = min(DVAL(p,0), SMB_MAXNAMELEN);
1129                         p += 4;
1130                         p += 4; /* EA size */
1131                         p += 2; /* short name len? */
1132                         p += 24; /* short name? */        
1133                         strncpy(finfo->path,p,namelen);
1134                         finfo->len = namelen;
1135                 }
1136                 break;
1137 
1138         default:
1139                 DPRINTK("Unknown long filename format %d\n",level);
1140                 result = p + WVAL(p,0);
1141         }
1142         return result;
1143 }
1144 
1145 int
1146 smb_proc_readdir_long(struct smb_server *server, struct inode *dir, int fpos,
     /* [previous][next][first][last][top][bottom][index][help] */
1147                       int cache_size, struct smb_dirent *entry)
1148 {
1149         int max_matches = 512;
1150   
1151         /* NT uses 260, OS/2 uses 2. Both accept 1. */
1152         int info_level = 1;
1153 
1154         char *p;
1155         int i;
1156         int first, total_count;
1157         struct smb_dirent *current_entry;
1158 
1159         char *resp_data;
1160         char *resp_param;
1161         int resp_data_len = 0;
1162         int resp_param_len=0;
1163 
1164         int attribute = aSYSTEM | aHIDDEN | aDIR;
1165         int result;
1166 
1167         int ff_resume_key = 0;
1168         int ff_searchcount=0;
1169         int ff_eos=0;
1170         int ff_lastname=0;
1171         int ff_dir_handle=0;
1172         int loop_count = 0;
1173 
1174         int dirlen = strlen(SMB_FINFO(dir)->path);
1175         char mask[dirlen + 5];
1176 
1177         strcpy(mask, SMB_FINFO(dir)->path);
1178         strcat(mask, "\\*");
1179 
1180         DPRINTK("SMB call lreaddir %d @ %d\n", cache_size, fpos);        
1181         DPRINTK("          mask = %s\n", mask);
1182 
1183         resp_param = NULL;
1184         resp_data  = NULL;
1185 
1186         smb_lock_server(server);
1187 
1188  retry:
1189 
1190         first = 1;
1191         total_count = 0;
1192         current_entry = entry;
1193         
1194         while (ff_eos == 0)
1195         {
1196                 int masklen = strlen(mask);
1197                 unsigned char *outbuf = server->packet;
1198                 
1199                 loop_count += 1;
1200                 if (loop_count > 200)
1201                 {
1202                         printk("smb_proc_readdir_long: "
1203                                "Looping in FIND_NEXT??\n");
1204                         break;
1205                 }
1206 
1207                 smb_setup_header(server, SMBtrans2, 15,
1208                                  5 + 12 + masklen + 1);
1209 
1210                 WSET(outbuf,smb_tpscnt,12 + masklen +1);
1211                 WSET(outbuf,smb_tdscnt,0);
1212                 WSET(outbuf,smb_mprcnt,10); 
1213                 WSET(outbuf,smb_mdrcnt,TRANS2_MAX_TRANSFER);
1214                 WSET(outbuf,smb_msrcnt,0);
1215                 WSET(outbuf,smb_flags,0); 
1216                 DSET(outbuf,smb_timeout,0);
1217                 WSET(outbuf,smb_pscnt,WVAL(outbuf,smb_tpscnt));
1218                 WSET(outbuf,smb_psoff,((SMB_BUF(outbuf)+3) - outbuf)-4);
1219                 WSET(outbuf,smb_dscnt,0);
1220                 WSET(outbuf,smb_dsoff,0);
1221                 WSET(outbuf,smb_suwcnt,1);
1222                 WSET(outbuf,smb_setup0,
1223                      first == 1 ? TRANSACT2_FINDFIRST : TRANSACT2_FINDNEXT);
1224 
1225                 p = SMB_BUF(outbuf);
1226                 *p++=0;         /* put in a null smb_name */
1227                 *p++='D'; *p++ = ' '; /* this was added because OS/2 does it */
1228 
1229                 if (first != 0)
1230                 {
1231                         WSET(p,0,attribute); /* attribute */
1232                         WSET(p,2,max_matches); /* max count */
1233                         WSET(p,4,8+4+2); /* resume required + close on end +
1234                                             continue */
1235                         WSET(p,6,info_level); 
1236                         DSET(p,8,0);
1237                         p += 12;
1238                         strncpy(p, mask, masklen);
1239                         p += masklen;
1240                         *p++ = 0; *p++ = 0;
1241                 }
1242                 else
1243                 {
1244                         DPRINTK("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
1245                                 ff_dir_handle,ff_resume_key,ff_lastname,mask);
1246                         WSET(p,0,ff_dir_handle);
1247                         WSET(p,2,max_matches); /* max count */
1248                         WSET(p,4,info_level); 
1249                         DSET(p,6,ff_resume_key); /* ff_resume_key */
1250                         WSET(p,10,8+4+2); /* resume required + close on end +
1251                                              continue */
1252                         p += 12;
1253                         strncpy(p, mask, masklen);
1254                         p += masklen;
1255                         *p++ = 0; *p++ = 0;
1256                 }
1257 
1258                 result = smb_trans2_request(server,
1259                                             &resp_data_len,&resp_param_len,
1260                                             &resp_data,&resp_param);
1261 
1262                 if (result < 0) {
1263                         if (smb_retry(server)) {
1264                                 goto retry;
1265                         }
1266                         DPRINTK("smb_proc_readdir_long: "
1267                                 "got error from trans2_request\n");
1268                         break;
1269                 }
1270 
1271                 if (server->rcls != 0)
1272                 {
1273                         result = -EIO;
1274                         break;
1275                 }
1276 
1277                 /* parse out some important return info */
1278                 p = resp_param;
1279                 if (first != 0)
1280                 {
1281                         ff_dir_handle = WVAL(p,0);
1282                         ff_searchcount = WVAL(p,2);
1283                         ff_eos = WVAL(p,4);
1284                         ff_lastname = WVAL(p,8);
1285                 }
1286                 else
1287                 {
1288                         ff_searchcount = WVAL(p,0);
1289                         ff_eos = WVAL(p,2);
1290                         ff_lastname = WVAL(p,6);
1291                 }
1292 
1293                 if (ff_searchcount == 0) 
1294                         break;
1295 
1296                 /* point to the data bytes */
1297                 p = resp_data;
1298 
1299                 /* we might need the lastname for continuations */
1300                 if (ff_lastname > 0)
1301                 {
1302                         switch(info_level)
1303                         {
1304                         case 260:
1305                                 ff_resume_key =0;
1306                                 strcpy(mask,p+ff_lastname+94);
1307                                 break;
1308                         case 1:
1309                                 strcpy(mask,p + ff_lastname + 1);
1310                                 ff_resume_key = 0;
1311                                 break;
1312                         }
1313                 }
1314                 else
1315                         strcpy(mask,"");
1316   
1317                 /* Now we are ready to parse smb directory entries. */
1318                 
1319                 for (i = 0; i < ff_searchcount; i ++) {
1320                         if (total_count < fpos) {
1321                                 p = smb_decode_long_dirent(p, NULL,
1322                                                            info_level);
1323                                 DPRINTK("smb_proc_readdir: skipped entry.\n");
1324                                 DDPRINTK("                  total_count = %d\n"
1325                                          "                i = %d, fpos = %d\n",
1326                                          total_count, i, fpos);
1327                         }
1328                         else if (total_count >= fpos + cache_size) {
1329                                 goto finished;
1330                         }
1331                         else {
1332                                 p = smb_decode_long_dirent(p, current_entry,
1333                                                            info_level);
1334                                 current_entry->f_pos = total_count;
1335                                 DDPRINTK("smb_proc_readdir: entry->f_pos = "
1336                                          "%lu\n", entry->f_pos);        
1337                                 current_entry += 1;
1338                         }
1339                         total_count += 1;
1340                 }
1341 
1342                 if (resp_data != NULL) {
1343                         smb_kfree_s(resp_data,  0);
1344                         resp_data = NULL;
1345                 }
1346                 if (resp_param != NULL) {
1347                         smb_kfree_s(resp_param, 0);
1348                         resp_param = NULL;
1349                 }
1350 
1351                 DPRINTK("received %d entries (eos=%d resume=%d)\n",
1352                         ff_searchcount,ff_eos,ff_resume_key);
1353 
1354                 first = 0;
1355         }
1356 
1357  finished:
1358         if (resp_data != NULL) {
1359                 smb_kfree_s(resp_data,  0);
1360                 resp_data = NULL;
1361         }
1362         if (resp_param != NULL) {
1363                 smb_kfree_s(resp_param, 0);
1364                 resp_param = NULL;
1365         }
1366 
1367         smb_unlock_server(server);
1368 
1369         return total_count - fpos;
1370 }
1371 
1372 int
1373 smb_proc_readdir(struct smb_server *server, struct inode *dir, int fpos,
     /* [previous][next][first][last][top][bottom][index][help] */
1374                  int cache_size, struct smb_dirent *entry)
1375 {
1376         if (server->protocol >= PROTOCOL_LANMAN2)
1377                 return smb_proc_readdir_long(server, dir, fpos, cache_size,
1378                                              entry);
1379         else
1380                 return smb_proc_readdir_short(server, dir, fpos, cache_size,
1381                                               entry);
1382 }
1383                 
1384 static int
1385 smb_proc_getattr_core(struct smb_server *server, const char *path, int len, 
     /* [previous][next][first][last][top][bottom][index][help] */
1386                       struct smb_dirent *entry)
1387 {
1388         int result;
1389         char *p;
1390         char *buf = server->packet;
1391 
1392         smb_lock_server(server);
1393 
1394         DDPRINTK("smb_proc_getattr: %s\n", path);
1395 
1396  retry:
1397         p = smb_setup_header(server, SMBgetatr, 0, 2 + len);
1398         smb_encode_ascii(p, path, len);
1399         
1400         if ((result = smb_request_ok(server, SMBgetatr, 10, 0)) < 0) {
1401                 if (smb_retry(server)) {
1402                         goto retry;
1403                 }
1404                 smb_unlock_server(server);
1405                 return result;
1406         }
1407 
1408         entry->attr         = WVAL(buf, smb_vwv0);
1409         entry->ctime = entry->atime = /* The server only tells us 1 time */
1410                 entry->mtime = local2utc(DVAL(buf, smb_vwv1));
1411 
1412         entry->size         = DVAL(buf, smb_vwv3);
1413         smb_unlock_server(server);
1414         return 0;
1415 }
1416 
1417 /* smb_proc_getattrE: entry->fid must be valid */
1418 
1419 static int
1420 smb_proc_getattrE(struct smb_server *server, struct smb_dirent *entry)
     /* [previous][next][first][last][top][bottom][index][help] */
1421 {
1422         char* buf = server->packet;
1423         int result;
1424 
1425         smb_setup_header_exclusive(server, SMBgetattrE, 1, 0);
1426         WSET(buf, smb_vwv0, entry->fileid);
1427 
1428         if ((result = smb_request_ok(server, SMBgetattrE, 11, 0)) != 0) {
1429                 smb_unlock_server(server);
1430                 return result;
1431         }
1432 
1433         entry->ctime = date_dos2unix(WVAL(buf, smb_vwv1), WVAL(buf, smb_vwv0));
1434         entry->atime = date_dos2unix(WVAL(buf, smb_vwv3), WVAL(buf, smb_vwv2));
1435         entry->mtime = date_dos2unix(WVAL(buf, smb_vwv5), WVAL(buf, smb_vwv4));
1436         entry->size  = DVAL(buf, smb_vwv6);
1437         entry->attr  = WVAL(buf, smb_vwv10);
1438 
1439         smb_unlock_server(server);
1440         return 0;
1441 }
1442 
1443 int
1444 smb_proc_getattr(struct smb_server *server, const char *path, int len, 
     /* [previous][next][first][last][top][bottom][index][help] */
1445                  struct smb_dirent *entry)
1446 {
1447         if (server->protocol >= PROTOCOL_LANMAN1) {
1448 
1449                 int result = 0;
1450                 struct smb_dirent temp_entry;
1451 
1452                 if ((result=smb_proc_open(server,path,len,
1453                                           &temp_entry)) < 0) {
1454                         /* We cannot open directories, so we try to use the
1455                            core variant */
1456                         return smb_proc_getattr_core(server,path,len,entry);
1457                 }
1458 
1459                 if ((result=smb_proc_getattrE(server, &temp_entry)) >= 0) {
1460                         entry->attr  = temp_entry.attr;
1461                         entry->atime = temp_entry.atime;
1462                         entry->mtime = temp_entry.mtime;
1463                         entry->ctime = temp_entry.ctime;
1464                         entry->size  = temp_entry.size;
1465                 }
1466                 
1467                 smb_proc_close(server, &temp_entry);
1468                 return result;
1469 
1470         } else {
1471                 return smb_proc_getattr_core(server, path, len, entry);
1472         }
1473 }
1474 
1475 
1476 /* In core protocol, there is only 1 time to be set, we use
1477    entry->mtime, to make touch work. */
1478 static int
1479 smb_proc_setattr_core(struct smb_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
1480                       const char *path, int len,
1481                       struct smb_dirent *new_finfo)
1482 {
1483         char *p;
1484         char *buf = server->packet;
1485         int result;
1486 
1487         smb_lock_server(server);
1488 
1489  retry:
1490         p = smb_setup_header(server, SMBsetatr, 8, 4 + len);
1491         WSET(buf, smb_vwv0, new_finfo->attr);
1492         DSET(buf, smb_vwv1, utc2local(new_finfo->mtime));
1493         p = smb_encode_ascii(p, path, len);
1494         p = smb_encode_ascii(p, "", 0);
1495 
1496         if ((result = smb_request_ok(server, SMBsetatr, 0, 0)) < 0) {
1497                 if (smb_retry(server)) {
1498                         goto retry;
1499                 }
1500         }
1501         smb_unlock_server(server);
1502         return result;
1503 }
1504 
1505 /* smb_proc_setattrE: we do not retry here, because we rely on fid,
1506    which would not be valid after a retry. */
1507 static int
1508 smb_proc_setattrE(struct smb_server *server, word fid,
     /* [previous][next][first][last][top][bottom][index][help] */
1509                   struct smb_dirent *new_entry)
1510 {
1511         char *buf = server->packet;
1512         word date, time;
1513 
1514         smb_setup_header_exclusive(server, SMBsetattrE, 7, 0);
1515 
1516         WSET(buf, smb_vwv0, fid);
1517 
1518         date_unix2dos(new_entry->ctime, &time, &date);
1519         WSET(buf, smb_vwv1, date);
1520         WSET(buf, smb_vwv2, time);
1521         
1522         date_unix2dos(new_entry->atime, &time, &date);
1523         WSET(buf, smb_vwv3, date);
1524         WSET(buf, smb_vwv4, time);
1525         
1526         date_unix2dos(new_entry->mtime, &time, &date);
1527         WSET(buf, smb_vwv5, date);
1528         WSET(buf, smb_vwv6, time);
1529 
1530         return smb_request_ok_unlock(server, SMBsetattrE, 0, 0);
1531 }
1532 
1533 /* smb_proc_setattr: for protocol >= LANMAN1 we expect the file to be
1534    opened for writing. */
1535 int
1536 smb_proc_setattr(struct smb_server *server, struct inode *inode,
     /* [previous][next][first][last][top][bottom][index][help] */
1537                  struct smb_dirent *new_finfo)
1538 {
1539         struct smb_dirent *finfo = SMB_FINFO(inode);
1540         int result;
1541 
1542         if (server->protocol >= PROTOCOL_LANMAN1) {
1543                 if ((result = smb_make_open(inode, O_RDWR)) < 0)
1544                         return result;
1545                 return smb_proc_setattrE(server, finfo->fileid, new_finfo);
1546         } else {
1547                 return smb_proc_setattr_core(server, finfo->path, finfo->len,
1548                                              new_finfo);
1549         }
1550 }
1551 
1552 int
1553 smb_proc_dskattr(struct super_block *super, struct smb_dskattr *attr)
     /* [previous][next][first][last][top][bottom][index][help] */
1554 {
1555         int error;
1556         char *p;
1557         struct smb_server *server = &(SMB_SBP(super)->s_server);
1558 
1559         smb_lock_server(server);
1560 
1561  retry:
1562         smb_setup_header(server, SMBdskattr, 0, 0);
1563         
1564         if ((error = smb_request_ok(server, SMBdskattr, 5, 0)) < 0) {
1565                 if (smb_retry(server)) {
1566                         goto retry;
1567                 }
1568                 smb_unlock_server(server);
1569                 return error;
1570         }
1571         
1572         p = SMB_VWV(server->packet);
1573         p = smb_decode_word(p, &attr->total);
1574         p = smb_decode_word(p, &attr->allocblocks);
1575         p = smb_decode_word(p, &attr->blocksize);
1576         p = smb_decode_word(p, &attr->free);
1577         smb_unlock_server(server);
1578         return 0;
1579 }
1580 
1581 /*****************************************************************************/
1582 /*                                                                           */
1583 /*  Mount/umount operations.                                                 */
1584 /*                                                                           */
1585 /*****************************************************************************/
1586 
1587 struct smb_prots {
1588         enum smb_protocol prot;
1589         const char *name;
1590 };
1591 
1592 /* smb_proc_reconnect: We expect the server to be locked, so that you
1593    can call the routine from within smb_retry. The socket must be
1594    created, like after a user-level socket()-call. It may not be
1595    connected. */
1596 
1597 int
1598 smb_proc_reconnect(struct smb_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
1599 {
1600         struct smb_prots prots[] =
1601         { { PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
1602           { PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
1603 #ifdef LANMAN1
1604           { PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
1605           { PROTOCOL_LANMAN1,"LANMAN1.0"},
1606 #endif
1607 #ifdef LANMAN2
1608           { PROTOCOL_LANMAN2,"LM1.2X002"},
1609 #endif
1610           {-1, NULL} };
1611         char dev[] = "A:";
1612         int i, plength;
1613         int max_xmit = 1024;    /* Space needed for first request. */
1614         int given_max_xmit = server->m.max_xmit;
1615         int result;
1616         byte *p;
1617 
1618         if ((result = smb_connect(server)) < 0) {
1619                 DPRINTK("smb_proc_reconnect: could not smb_connect\n");
1620                 goto fail;
1621         }
1622 
1623         /* Here we assume that the connection is valid */
1624         server->state = CONN_VALID;
1625 
1626         if (server->packet != NULL) {
1627                 smb_kfree_s(server->packet, server->max_xmit);
1628         }
1629         
1630         server->packet = smb_kmalloc(max_xmit, GFP_KERNEL);
1631 
1632         if (server->packet == NULL) {
1633                 printk("smb_proc_connect: No memory! Bailing out.\n");
1634                 result = -ENOMEM;
1635                 goto fail;
1636         }
1637 
1638         server->max_xmit = max_xmit;
1639 
1640         /*
1641          * Start with an RFC1002 session request packet.
1642          */
1643         p = server->packet + 4;
1644 
1645         p = smb_name_mangle(p, server->m.server_name);
1646         p = smb_name_mangle(p, server->m.client_name);
1647         
1648         smb_encode_smb_length(server->packet,
1649                               (void *)p - (void *)(server->packet));
1650         
1651         server->packet[0] = 0x81; /* SESSION REQUEST */
1652 
1653         if (smb_catch_keepalive(server) < 0) {
1654                 printk("smb_proc_connect: could not catch_keepalives\n");
1655         }
1656         
1657         if ((result = smb_request(server)) < 0) {
1658                 printk("smb_proc_connect: Failed to send SESSION REQUEST.\n");
1659                 smb_dont_catch_keepalive(server);
1660                 goto fail;
1661         }
1662         
1663         if (server->packet[0] != 0x82) {
1664                 printk("smb_proc_connect: Did not recieve positive response "
1665                        "(err = %x)\n", 
1666                        server->packet[0]);
1667                 smb_dont_catch_keepalive(server);
1668 #if DEBUG_SMB > 0
1669                 smb_dump_packet(server->packet);
1670 #endif
1671                 result = -EIO;
1672                 goto fail;
1673         }
1674 
1675         DPRINTK("smb_proc_connect: Passed SESSION REQUEST.\n");
1676         
1677         /* Now we are ready to send a SMB Negotiate Protocol packet. */
1678         memset(server->packet, 0, SMB_HEADER_LEN);
1679 
1680         plength = 0;
1681         for (i = 0; prots[i].name != NULL; i++) {
1682                 plength += strlen(prots[i].name) + 2;
1683         }
1684 
1685         smb_setup_header(server, SMBnegprot, 0, plength);
1686 
1687         p = SMB_BUF(server->packet);
1688         
1689         for (i = 0; prots[i].name != NULL; i++) {
1690                 p = smb_encode_dialect(p,prots[i].name, strlen(prots[i].name));
1691         }
1692         
1693         if ((result = smb_request_ok(server, SMBnegprot, 1, -1)) < 0) {
1694                 printk("smb_proc_connect: Failure requesting SMBnegprot\n");
1695                 smb_dont_catch_keepalive(server);
1696                 goto fail;
1697         } else {
1698                 DDPRINTK("smb_proc_connect: Request SMBnegprot..");
1699         }
1700 
1701         DDPRINTK("Verified!\n");
1702 
1703         p = SMB_VWV(server->packet);
1704         p = smb_decode_word(p, (word *)&i);
1705         server->protocol = prots[i].prot;
1706 
1707         DPRINTK("smb_proc_connect: Server wants %s protocol.\n",
1708                 prots[i].name);
1709 
1710         if (server->protocol > PROTOCOL_LANMAN1) {
1711 
1712                 word passlen = strlen(server->m.password);
1713                 word userlen = strlen(server->m.username);
1714                 
1715                 DPRINTK("smb_proc_connect: password = %s\n",
1716                         server->m.password);
1717                 DPRINTK("smb_proc_connect: usernam = %s\n",
1718                         server->m.username);
1719                 DPRINTK("smb_proc_connect: blkmode = %d\n",
1720                         WVAL(server->packet, smb_vwv5));
1721 
1722                 server->maxxmt = WVAL(server->packet, smb_vwv2);
1723                 server->maxmux = WVAL(server->packet, smb_vwv3);
1724                 server->maxvcs = WVAL(server->packet, smb_vwv4);
1725                 server->blkmode= WVAL(server->packet, smb_vwv5);
1726                 server->sesskey= DVAL(server->packet, smb_vwv6);
1727 
1728                 smb_setup_header(server, SMBsesssetupX, 10,
1729                                  2 + userlen + passlen);
1730 
1731                 WSET(server->packet, smb_vwv0, 0x00ff);
1732                 WSET(server->packet, smb_vwv1, 0);
1733                 WSET(server->packet, smb_vwv2, given_max_xmit);
1734                 WSET(server->packet, smb_vwv3, 2);
1735                 WSET(server->packet, smb_vwv4, server->pid);
1736                 DSET(server->packet, smb_vwv5, server->sesskey);
1737                 WSET(server->packet, smb_vwv7, passlen + 1);
1738                 WSET(server->packet, smb_vwv8, 0);
1739                 WSET(server->packet, smb_vwv9, 0);
1740 
1741                 p = SMB_BUF(server->packet);
1742                 strcpy(p, server->m.password);
1743                 p += passlen + 1;
1744                 strcpy(p, server->m.username);
1745 
1746                 if ((result = smb_request_ok(server,SMBsesssetupX,3,0)) < 0) {
1747                         DPRINTK("smb_proc_connect: SMBsessetupX failed\n");
1748                         smb_dont_catch_keepalive(server);
1749                         goto fail;
1750                 }
1751                 smb_decode_word(server->packet+32, &(server->server_uid));
1752         }
1753         else
1754 
1755         {
1756                 server->maxxmt = 0;
1757                 server->maxmux = 0;
1758                 server->maxvcs = 0;
1759                 server->blkmode = 0;
1760                 server->sesskey = 0;
1761         }
1762 
1763         /* Fine! We have a connection, send a tcon message. */
1764 
1765         smb_setup_header(server, SMBtcon, 0,
1766                          6 + strlen(server->m.service) +
1767                          strlen(server->m.password) + strlen(dev));
1768         p = SMB_BUF(server->packet);
1769         p = smb_encode_ascii(p, server->m.service, strlen(server->m.service));
1770         p = smb_encode_ascii(p,server->m.password, strlen(server->m.password));
1771         p = smb_encode_ascii(p, dev, strlen(dev));
1772 
1773         if ((result = smb_request_ok(server, SMBtcon, 2, 0)) < 0) {
1774                 DPRINTK("smb_proc_connect: SMBtcon not verified.\n");
1775                 smb_dont_catch_keepalive(server);
1776                 goto fail;
1777         }
1778 
1779         DDPRINTK("OK! Managed to set up SMBtcon!\n");
1780    
1781         p = SMB_VWV(server->packet);
1782         p = smb_decode_word(p, &server->max_xmit);
1783 
1784         if (server->max_xmit > given_max_xmit)
1785                 server->max_xmit = given_max_xmit;
1786         
1787         p = smb_decode_word(p, &server->tid);
1788 
1789         /* Ok, everything is fine. max_xmit does not include */
1790         /* the TCP-SMB header of 4 bytes. */
1791         server->max_xmit += 4;
1792 
1793         DPRINTK("max_xmit = %d, tid = %d\n", server->max_xmit, server->tid);
1794 
1795         /* Now make a new packet with the correct size. */
1796         smb_kfree_s(server->packet, max_xmit); 
1797 
1798         server->packet = smb_kmalloc(server->max_xmit, GFP_KERNEL);
1799         if (server->packet == NULL) {
1800                 printk("smb_proc_connect: No memory left in end of "
1801                        "connection phase :-(\n");
1802                 smb_dont_catch_keepalive(server);
1803                 goto fail;
1804         }
1805 
1806         DPRINTK("smb_proc_connect: Normal exit\n");
1807         return 0;
1808 
1809  fail:
1810         server->state = CONN_INVALID;
1811         return result;
1812 }
1813 
1814 /* smb_proc_reconnect: server->packet is allocated with
1815    server->max_xmit bytes if and only if we return >= 0 */
1816 int
1817 smb_proc_connect(struct smb_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
1818 {
1819         int result;
1820         smb_lock_server(server);
1821         result = smb_proc_reconnect(server);
1822         if ((result < 0) && (server->packet != NULL)) {
1823                 smb_kfree_s(server->packet, server->max_xmit);
1824                 server->packet = NULL;
1825         }
1826         smb_unlock_server(server);
1827         return result;
1828 }
1829         
1830 int
1831 smb_proc_disconnect(struct smb_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
1832 {
1833         smb_setup_header_exclusive(server, SMBtdis, 0, 0);
1834         return smb_request_ok_unlock(server, SMBtdis, 0, 0);
1835 }
1836 
1837 /* error code stuff - put together by Merik Karman
1838    merik@blackadder.dsh.oz.au */
1839 
1840 #if DEBUG_SMB > 0
1841 
1842 typedef struct {
1843         char *name;
1844         int code;
1845         char *message;
1846 } err_code_struct;
1847 
1848 /* Dos Error Messages */
1849 err_code_struct dos_msgs[] = {
1850   { "ERRbadfunc",1,"Invalid function."},
1851   { "ERRbadfile",2,"File not found."},
1852   { "ERRbadpath",3,"Directory invalid."},
1853   { "ERRnofids",4,"No file descriptors available"},
1854   { "ERRnoaccess",5,"Access denied."},
1855   { "ERRbadfid",6,"Invalid file handle."},
1856   { "ERRbadmcb",7,"Memory control blocks destroyed."},
1857   { "ERRnomem",8,"Insufficient server memory to perform the requested function."},
1858   { "ERRbadmem",9,"Invalid memory block address."},
1859   { "ERRbadenv",10,"Invalid environment."},
1860   { "ERRbadformat",11,"Invalid format."},
1861   { "ERRbadaccess",12,"Invalid open mode."},
1862   { "ERRbaddata",13,"Invalid data."},
1863   { "ERR",14,"reserved."},
1864   { "ERRbaddrive",15,"Invalid drive specified."},
1865   { "ERRremcd",16,"A Delete Directory request attempted  to  remove  the  server's  current directory."},
1866   { "ERRdiffdevice",17,"Not same device."},
1867   { "ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."},
1868   { "ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing  FIDs  on the file."},
1869   { "ERRlock",33,"A Lock request conflicted with an existing lock or specified an  invalid mode,  or an Unlock requested attempted to remove a lock held by another process."},
1870   { "ERRfilexists",80,"The file named in a Create Directory, Make  New  File  or  Link  request already exists."},
1871   { "ERRbadpipe",230,"Pipe invalid."},
1872   { "ERRpipebusy",231,"All instances of the requested pipe are busy."},
1873   { "ERRpipeclosing",232,"Pipe close in progress."},
1874   { "ERRnotconnected",233,"No process on other end of pipe."},
1875   { "ERRmoredata",234,"There is more data to be returned."},
1876   { NULL,-1,NULL}};
1877 
1878 /* Server Error Messages */
1879 err_code_struct server_msgs[] = { 
1880   { "ERRerror",1,"Non-specific error code."},
1881   { "ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
1882   { "ERRbadtype",3,"reserved."},
1883   { "ERRaccess",4,"The requester does not have  the  necessary  access  rights  within  the specified  context for the requested function. The context is defined by the TID or the UID."},
1884   { "ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."},
1885   { "ERRinvnetname",6,"Invalid network name in tree connect."},
1886   { "ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or  non-printer request made to printer connection."},
1887   { "ERRqfull",49,"Print queue full (files) -- returned by open print file."},
1888   { "ERRqtoobig",50,"Print queue full -- no space."},
1889   { "ERRqeof",51,"EOF on print queue dump."},
1890   { "ERRinvpfid",52,"Invalid print file FID."},
1891   { "ERRsmbcmd",64,"The server did not recognize the command received."},
1892   { "ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."},
1893   { "ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid  combination of values."},
1894   { "ERRreserved",68,"reserved."},
1895   { "ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination.  The server cannot set the requested attribute."},
1896   { "ERRreserved",70,"reserved."},
1897   { "ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."},
1898   { "ERRpaused",81,"Server is paused."},
1899   { "ERRmsgoff",82,"Not receiving messages."},
1900   { "ERRnoroom",83,"No room to buffer message."},
1901   { "ERRrmuns",87,"Too many remote user names."},
1902   { "ERRtimeout",88,"Operation timed out."},
1903   { "ERRnoresource",89,"No resources currently available for request."},
1904   { "ERRtoomanyuids",90,"Too many UIDs active on this session."},
1905   { "ERRbaduid",91,"The UID is not known as a valid ID on this session."},
1906   { "ERRusempx",250,"Temp unable to support Raw, use MPX mode."},
1907   { "ERRusestd",251,"Temp unable to support Raw, use standard read/write."},
1908   { "ERRcontmpx",252,"Continue in MPX mode."},
1909   { "ERRreserved",253,"reserved."},
1910   { "ERRreserved",254,"reserved."},
1911   { "ERRnosupport",0xFFFF,"Function not supported."},
1912   { NULL,-1,NULL}};
1913 
1914 /* Hard Error Messages */
1915 err_code_struct hard_msgs[] = { 
1916   { "ERRnowrite",19,"Attempt to write on write-protected diskette."},
1917   { "ERRbadunit",20,"Unknown unit."},
1918   { "ERRnotready",21,"Drive not ready."},
1919   { "ERRbadcmd",22,"Unknown command."},
1920   { "ERRdata",23,"Data error (CRC)."},
1921   { "ERRbadreq",24,"Bad request structure length."},
1922   { "ERRseek",25 ,"Seek error."},
1923   { "ERRbadmedia",26,"Unknown media type."},
1924   { "ERRbadsector",27,"Sector not found."},
1925   { "ERRnopaper",28,"Printer out of paper."},
1926   { "ERRwrite",29,"Write fault."},
1927   { "ERRread",30,"Read fault."},
1928   { "ERRgeneral",31,"General failure."},
1929   { "ERRbadshare",32,"A open conflicts with an existing open."},
1930   { "ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
1931   { "ERRwrongdisk",34,"The wrong disk was found in a drive."},
1932   { "ERRFCBUnavail",35,"No FCBs are available to process request."},
1933   { "ERRsharebufexc",36,"A sharing buffer has been exceeded."},
1934   { NULL,-1,NULL}
1935 };
1936 
1937 
1938 struct { 
1939         int code;
1940         char *class;
1941         err_code_struct *err_msgs;
1942 } err_classes[] = {  
1943   { 0,"SUCCESS",NULL},
1944   { 0x01,"ERRDOS",dos_msgs},
1945   { 0x02,"ERRSRV",server_msgs},
1946   { 0x03,"ERRHRD",hard_msgs},
1947   { 0x04,"ERRXOS",NULL},
1948   { 0xE1,"ERRRMX1",NULL},
1949   { 0xE2,"ERRRMX2",NULL},
1950   { 0xE3,"ERRRMX3",NULL},
1951   { 0xFF,"ERRCMD",NULL},
1952   { -1,NULL,NULL}
1953 };
1954 
1955 void
1956 smb_printerr(int class, int num)
     /* [previous][next][first][last][top][bottom][index][help] */
1957 {
1958         int i,j;
1959         err_code_struct *err;
1960 
1961         for (i=0; err_classes[i].class; i++) {
1962                 if (err_classes[i].code != class)
1963                         continue;
1964                 if (!err_classes[i].err_msgs) {
1965                         printk("%s - %d", err_classes[i].class, num);
1966                         return;
1967                 }
1968 
1969                 err = err_classes[i].err_msgs;
1970                 for (j=0; err[j].name; j++) {
1971                         if (num != err[j].code)
1972                                 continue;
1973                         printk("%s - %s (%s)",
1974                                err_classes[i].class, err[j].name,
1975                                err[j].message);
1976                         return;
1977                 }
1978         }
1979         
1980         printk("Unknown error - (%d,%d)", class, num);
1981         return;
1982 }
1983 
1984 #endif /* DEBUG_SMB > 0 */
1985 
1986 /*
1987  * Overrides for Emacs so that we follow Linus's tabbing style.
1988  * Emacs will notice this stuff at the end of the file and automatically
1989  * adjust the settings for this buffer only.  This must remain at the end
1990  * of the file.
1991  * ---------------------------------------------------------------------------
1992  * Local variables:
1993  * c-indent-level: 8
1994  * c-brace-imaginary-offset: 0
1995  * c-brace-offset: -8
1996  * c-argdecl-indent: 8
1997  * c-label-offset: -8
1998  * c-continued-statement-offset: 8
1999  * c-continued-brace-offset: 0
2000  * End:
2001  */

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