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

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