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 = 64; /* this should actually be based on the 
1143                                  maxxmit */
1144   
1145         /* NT uses 260, OS/2 uses 2. Both accept 1. */
1146         int info_level = 1;
1147 
1148         char *p;
1149         int i;
1150         int first, total_count;
1151         struct smb_dirent *current_entry;
1152 
1153         char *resp_data;
1154         char *resp_param;
1155         int resp_data_len = 0;
1156         int resp_param_len=0;
1157 
1158         int attribute = aSYSTEM | aHIDDEN | aDIR;
1159         int result;
1160 
1161         int ff_resume_key = 0;
1162         int ff_searchcount=0;
1163         int ff_eos=0;
1164         int ff_lastname=0;
1165         int ff_dir_handle=0;
1166         int loop_count = 0;
1167 
1168         int dirlen = strlen(SMB_FINFO(dir)->path);
1169         char mask[dirlen + 5];
1170 
1171         strcpy(mask, SMB_FINFO(dir)->path);
1172         strcat(mask, "\\*");
1173 
1174         DPRINTK("SMB call lreaddir %d @ %d\n", cache_size, fpos);        
1175         DPRINTK("          mask = %s\n", mask);
1176 
1177         resp_param = NULL;
1178         resp_data  = NULL;
1179 
1180         smb_lock_server(server);
1181 
1182  retry:
1183 
1184         first = 1;
1185         total_count = 0;
1186         current_entry = entry;
1187         
1188         while (ff_eos == 0)
1189         {
1190                 int masklen = strlen(mask);
1191                 unsigned char *outbuf = server->packet;
1192                 
1193                 loop_count += 1;
1194                 if (loop_count > 200)
1195                 {
1196                         printk("smb_proc_readdir_long: "
1197                                "Looping in FIND_NEXT??\n");
1198                         break;
1199                 }
1200 
1201                 smb_setup_header(server, SMBtrans2, 15,
1202                                  5 + 12 + masklen + 1);
1203 
1204                 WSET(outbuf,smb_tpscnt,12 + masklen +1);
1205                 WSET(outbuf,smb_tdscnt,0);
1206                 WSET(outbuf,smb_mprcnt,10); 
1207                 WSET(outbuf,smb_mdrcnt,TRANS2_MAX_TRANSFER);
1208                 WSET(outbuf,smb_msrcnt,0);
1209                 WSET(outbuf,smb_flags,0); 
1210                 DSET(outbuf,smb_timeout,0);
1211                 WSET(outbuf,smb_pscnt,WVAL(outbuf,smb_tpscnt));
1212                 WSET(outbuf,smb_psoff,((SMB_BUF(outbuf)+3) - outbuf)-4);
1213                 WSET(outbuf,smb_dscnt,0);
1214                 WSET(outbuf,smb_dsoff,0);
1215                 WSET(outbuf,smb_suwcnt,1);
1216                 WSET(outbuf,smb_setup0,
1217                      first == 1 ? TRANSACT2_FINDFIRST : TRANSACT2_FINDNEXT);
1218 
1219                 p = SMB_BUF(outbuf);
1220                 *p++=0;         /* put in a null smb_name */
1221                 *p++='D'; *p++ = ' '; /* this was added because OS/2 does it */
1222 
1223                 if (first != 0)
1224                 {
1225                         WSET(p,0,attribute); /* attribute */
1226                         WSET(p,2,max_matches); /* max count */
1227                         WSET(p,4,8+4+2); /* resume required + close on end +
1228                                             continue */
1229                         WSET(p,6,info_level); 
1230                         DSET(p,8,0);
1231                         p += 12;
1232                         strncpy(p, mask, masklen);
1233                         p += masklen;
1234                         *p++ = 0; *p++ = 0;
1235                 }
1236                 else
1237                 {
1238                         DPRINTK("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
1239                                 ff_dir_handle,ff_resume_key,ff_lastname,mask);
1240                         WSET(p,0,ff_dir_handle);
1241                         WSET(p,2,max_matches); /* max count */
1242                         WSET(p,4,info_level); 
1243                         DSET(p,6,ff_resume_key); /* ff_resume_key */
1244                         WSET(p,10,8+4+2); /* resume required + close on end +
1245                                              continue */
1246                         p += 12;
1247                         strncpy(p, mask, masklen);
1248                         p += masklen;
1249                         *p++ = 0; *p++ = 0;
1250                 }
1251 
1252                 result = smb_trans2_request(server,
1253                                             &resp_data_len,&resp_param_len,
1254                                             &resp_data,&resp_param);
1255 
1256                 if (result < 0) {
1257                         if (smb_retry(server)) {
1258                                 goto retry;
1259                         }
1260                         DPRINTK("smb_proc_readdir_long: "
1261                                 "got error from trans2_request\n");
1262                         break;
1263                 }
1264 
1265                 if (server->rcls != 0)
1266                 {
1267                         result = -EIO;
1268                         break;
1269                 }
1270 
1271                 /* parse out some important return info */
1272                 p = resp_param;
1273                 if (first != 0)
1274                 {
1275                         ff_dir_handle = WVAL(p,0);
1276                         ff_searchcount = WVAL(p,2);
1277                         ff_eos = WVAL(p,4);
1278                         ff_lastname = WVAL(p,8);
1279                 }
1280                 else
1281                 {
1282                         ff_searchcount = WVAL(p,0);
1283                         ff_eos = WVAL(p,2);
1284                         ff_lastname = WVAL(p,6);
1285                 }
1286 
1287                 if (ff_searchcount == 0) 
1288                         break;
1289 
1290                 /* point to the data bytes */
1291                 p = resp_data;
1292 
1293                 /* we might need the lastname for continuations */
1294                 if (ff_lastname > 0)
1295                 {
1296                         switch(info_level)
1297                         {
1298                         case 260:
1299                                 ff_resume_key =0;
1300                                 strcpy(mask,p+ff_lastname+94);
1301                                 break;
1302                         case 1:
1303                                 strcpy(mask,p + ff_lastname + 1);
1304                                 ff_resume_key = 0;
1305                                 break;
1306                         }
1307                 }
1308                 else
1309                         strcpy(mask,"");
1310   
1311                 /* Now we are ready to parse smb directory entries. */
1312                 
1313                 for (i = 0; i < ff_searchcount; i ++) {
1314                         if (total_count < fpos) {
1315                                 p = smb_decode_long_dirent(p, NULL,
1316                                                            info_level);
1317                                 DPRINTK("smb_proc_readdir: skipped entry.\n");
1318                                 DDPRINTK("                  total_count = %d\n"
1319                                          "                i = %d, fpos = %d\n",
1320                                          total_count, i, fpos);
1321                         }
1322                         else if (total_count >= fpos + cache_size) {
1323                                 goto finished;
1324                         }
1325                         else {
1326                                 p = smb_decode_long_dirent(p, current_entry,
1327                                                            info_level);
1328                                 current_entry->f_pos = total_count;
1329                                 DDPRINTK("smb_proc_readdir: entry->f_pos = "
1330                                          "%lu\n", entry->f_pos);        
1331                                 current_entry += 1;
1332                         }
1333                         total_count += 1;
1334                 }
1335 
1336                 if (resp_data != NULL) {
1337                         smb_kfree_s(resp_data,  0);
1338                         resp_data = NULL;
1339                 }
1340                 if (resp_param != NULL) {
1341                         smb_kfree_s(resp_param, 0);
1342                         resp_param = NULL;
1343                 }
1344 
1345                 DPRINTK("received %d entries (eos=%d resume=%d)\n",
1346                         ff_searchcount,ff_eos,ff_resume_key);
1347 
1348                 first = 0;
1349         }
1350 
1351  finished:
1352         if (resp_data != NULL) {
1353                 smb_kfree_s(resp_data,  0);
1354                 resp_data = NULL;
1355         }
1356         if (resp_param != NULL) {
1357                 smb_kfree_s(resp_param, 0);
1358                 resp_param = NULL;
1359         }
1360 
1361         smb_unlock_server(server);
1362 
1363         return total_count - fpos;
1364 }
1365 
1366 int
1367 smb_proc_readdir(struct smb_server *server, struct inode *dir, int fpos,
     /* [previous][next][first][last][top][bottom][index][help] */
1368                  int cache_size, struct smb_dirent *entry)
1369 {
1370         if (server->protocol >= PROTOCOL_LANMAN2)
1371                 return smb_proc_readdir_long(server, dir, fpos, cache_size,
1372                                              entry);
1373         else
1374                 return smb_proc_readdir_short(server, dir, fpos, cache_size,
1375                                               entry);
1376 }
1377                 
1378 static int
1379 smb_proc_getattr_core(struct smb_server *server, const char *path, int len, 
     /* [previous][next][first][last][top][bottom][index][help] */
1380                       struct smb_dirent *entry)
1381 {
1382         int result;
1383         char *p;
1384         char *buf = server->packet;
1385 
1386         smb_lock_server(server);
1387 
1388         DDPRINTK("smb_proc_getattr: %s\n", path);
1389 
1390  retry:
1391         p = smb_setup_header(server, SMBgetatr, 0, 2 + len);
1392         smb_encode_ascii(p, path, len);
1393         
1394         if ((result = smb_request_ok(server, SMBgetatr, 10, 0)) < 0) {
1395                 if (smb_retry(server)) {
1396                         goto retry;
1397                 }
1398                 smb_unlock_server(server);
1399                 return result;
1400         }
1401 
1402         entry->attr         = WVAL(buf, smb_vwv0);
1403         entry->ctime = entry->atime = /* The server only tells us 1 time */
1404                 entry->mtime = local2utc(DVAL(buf, smb_vwv1));
1405 
1406         entry->size         = DVAL(buf, smb_vwv3);
1407         smb_unlock_server(server);
1408         return 0;
1409 }
1410 
1411 /* smb_proc_getattrE: entry->fid must be valid */
1412 
1413 static int
1414 smb_proc_getattrE(struct smb_server *server, struct smb_dirent *entry)
     /* [previous][next][first][last][top][bottom][index][help] */
1415 {
1416         char* buf = server->packet;
1417         int result;
1418 
1419         smb_setup_header_exclusive(server, SMBgetattrE, 1, 0);
1420         WSET(buf, smb_vwv0, entry->fileid);
1421 
1422         if ((result = smb_request_ok(server, SMBgetattrE, 11, 0)) != 0) {
1423                 smb_unlock_server(server);
1424                 return result;
1425         }
1426 
1427         entry->ctime = date_dos2unix(WVAL(buf, smb_vwv1), WVAL(buf, smb_vwv0));
1428         entry->atime = date_dos2unix(WVAL(buf, smb_vwv3), WVAL(buf, smb_vwv2));
1429         entry->mtime = date_dos2unix(WVAL(buf, smb_vwv5), WVAL(buf, smb_vwv4));
1430         entry->size  = DVAL(buf, smb_vwv6);
1431         entry->attr  = WVAL(buf, smb_vwv10);
1432 
1433         smb_unlock_server(server);
1434         return 0;
1435 }
1436 
1437 int
1438 smb_proc_getattr(struct smb_server *server, const char *path, int len, 
     /* [previous][next][first][last][top][bottom][index][help] */
1439                  struct smb_dirent *entry)
1440 {
1441         if (server->protocol >= PROTOCOL_LANMAN1) {
1442 
1443                 int result = 0;
1444                 struct smb_dirent temp_entry;
1445 
1446                 if ((result=smb_proc_open(server,path,len,
1447                                           &temp_entry)) < 0) {
1448                         /* We cannot open directories, so we try to use the
1449                            core variant */
1450                         return smb_proc_getattr_core(server,path,len,entry);
1451                 }
1452 
1453                 if ((result=smb_proc_getattrE(server, &temp_entry)) >= 0) {
1454                         entry->attr  = temp_entry.attr;
1455                         entry->atime = temp_entry.atime;
1456                         entry->mtime = temp_entry.mtime;
1457                         entry->ctime = temp_entry.ctime;
1458                         entry->size  = temp_entry.size;
1459                 }
1460                 
1461                 smb_proc_close(server, &temp_entry);
1462                 return result;
1463 
1464         } else {
1465                 return smb_proc_getattr_core(server, path, len, entry);
1466         }
1467 }
1468 
1469 
1470 /* In core protocol, there is only 1 time to be set, we use
1471    entry->mtime, to make touch work. */
1472 static int
1473 smb_proc_setattr_core(struct smb_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
1474                       const char *path, int len,
1475                       struct smb_dirent *new_finfo)
1476 {
1477         char *p;
1478         char *buf = server->packet;
1479         int result;
1480 
1481         smb_lock_server(server);
1482 
1483  retry:
1484         p = smb_setup_header(server, SMBsetatr, 8, 4 + len);
1485         WSET(buf, smb_vwv0, new_finfo->attr);
1486         DSET(buf, smb_vwv1, utc2local(new_finfo->mtime));
1487         p = smb_encode_ascii(p, path, len);
1488         p = smb_encode_ascii(p, "", 0);
1489 
1490         if ((result = smb_request_ok(server, SMBsetatr, 0, 0)) < 0) {
1491                 if (smb_retry(server)) {
1492                         goto retry;
1493                 }
1494         }
1495         smb_unlock_server(server);
1496         return result;
1497 }
1498 
1499 /* smb_proc_setattrE: we do not retry here, because we rely on fid,
1500    which would not be valid after a retry. */
1501 static int
1502 smb_proc_setattrE(struct smb_server *server, word fid,
     /* [previous][next][first][last][top][bottom][index][help] */
1503                   struct smb_dirent *new_entry)
1504 {
1505         char *buf = server->packet;
1506         word date, time;
1507 
1508         smb_setup_header_exclusive(server, SMBsetattrE, 7, 0);
1509 
1510         WSET(buf, smb_vwv0, fid);
1511 
1512         date_unix2dos(new_entry->ctime, &time, &date);
1513         WSET(buf, smb_vwv1, date);
1514         WSET(buf, smb_vwv2, time);
1515         
1516         date_unix2dos(new_entry->atime, &time, &date);
1517         WSET(buf, smb_vwv3, date);
1518         WSET(buf, smb_vwv4, time);
1519         
1520         date_unix2dos(new_entry->mtime, &time, &date);
1521         WSET(buf, smb_vwv5, date);
1522         WSET(buf, smb_vwv6, time);
1523 
1524         return smb_request_ok_unlock(server, SMBsetattrE, 0, 0);
1525 }
1526 
1527 /* smb_proc_setattr: for protocol >= LANMAN1 we expect the file to be
1528    opened for writing. */
1529 int
1530 smb_proc_setattr(struct smb_server *server, struct inode *inode,
     /* [previous][next][first][last][top][bottom][index][help] */
1531                  struct smb_dirent *new_finfo)
1532 {
1533         struct smb_dirent *finfo = SMB_FINFO(inode);
1534         int result;
1535 
1536         if (server->protocol >= PROTOCOL_LANMAN1) {
1537                 if ((result = smb_make_open(inode, O_RDWR)) < 0)
1538                         return result;
1539                 return smb_proc_setattrE(server, finfo->fileid, new_finfo);
1540         } else {
1541                 return smb_proc_setattr_core(server, finfo->path, finfo->len,
1542                                              new_finfo);
1543         }
1544 }
1545 
1546 int
1547 smb_proc_dskattr(struct super_block *super, struct smb_dskattr *attr)
     /* [previous][next][first][last][top][bottom][index][help] */
1548 {
1549         int error;
1550         char *p;
1551         struct smb_server *server = &(SMB_SBP(super)->s_server);
1552 
1553         smb_lock_server(server);
1554 
1555  retry:
1556         smb_setup_header(server, SMBdskattr, 0, 0);
1557         
1558         if ((error = smb_request_ok(server, SMBdskattr, 5, 0)) < 0) {
1559                 if (smb_retry(server)) {
1560                         goto retry;
1561                 }
1562                 smb_unlock_server(server);
1563                 return error;
1564         }
1565         
1566         p = SMB_VWV(server->packet);
1567         p = smb_decode_word(p, &attr->total);
1568         p = smb_decode_word(p, &attr->allocblocks);
1569         p = smb_decode_word(p, &attr->blocksize);
1570         p = smb_decode_word(p, &attr->free);
1571         smb_unlock_server(server);
1572         return 0;
1573 }
1574 
1575 /*****************************************************************************/
1576 /*                                                                           */
1577 /*  Mount/umount operations.                                                 */
1578 /*                                                                           */
1579 /*****************************************************************************/
1580 
1581 struct smb_prots {
1582         enum smb_protocol prot;
1583         const char *name;
1584 };
1585 
1586 /* smb_proc_reconnect: We expect the server to be locked, so that you
1587    can call the routine from within smb_retry. The socket must be
1588    created, like after a user-level socket()-call. It may not be
1589    connected. */
1590 
1591 int
1592 smb_proc_reconnect(struct smb_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
1593 {
1594         struct smb_prots prots[] =
1595         { { PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
1596           { PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
1597 #ifdef LANMAN1
1598           { PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
1599           { PROTOCOL_LANMAN1,"LANMAN1.0"},
1600 #endif
1601 #ifdef LANMAN2
1602           { PROTOCOL_LANMAN2,"LM1.2X002"},
1603 #endif
1604 #ifdef NT1
1605           { PROTOCOL_NT1,"NT LM 0.12"},
1606           { PROTOCOL_NT1,"NT LANMAN 1.0"},
1607 #endif
1608           {-1, NULL} };
1609         char dev[] = "A:";
1610         int i, plength;
1611         int max_xmit = 1024;    /* Space needed for first request. */
1612         int given_max_xmit = server->m.max_xmit;
1613         int result;
1614         byte *p;
1615 
1616         if ((result = smb_connect(server)) < 0) {
1617                 DPRINTK("smb_proc_reconnect: could not smb_connect\n");
1618                 goto fail;
1619         }
1620 
1621         /* Here we assume that the connection is valid */
1622         server->state = CONN_VALID;
1623 
1624         if (server->packet != NULL) {
1625                 smb_kfree_s(server->packet, server->max_xmit);
1626         }
1627         
1628         server->packet = smb_kmalloc(max_xmit, GFP_KERNEL);
1629 
1630         if (server->packet == NULL) {
1631                 printk("smb_proc_connect: No memory! Bailing out.\n");
1632                 result = -ENOMEM;
1633                 goto fail;
1634         }
1635 
1636         server->max_xmit = max_xmit;
1637 
1638         /*
1639          * Start with an RFC1002 session request packet.
1640          */
1641         p = server->packet + 4;
1642 
1643         p = smb_name_mangle(p, server->m.server_name);
1644         p = smb_name_mangle(p, server->m.client_name);
1645         
1646         smb_encode_smb_length(server->packet,
1647                               (void *)p - (void *)(server->packet));
1648         
1649         server->packet[0] = 0x81; /* SESSION REQUEST */
1650 
1651         if (smb_catch_keepalive(server) < 0) {
1652                 printk("smb_proc_connect: could not catch_keepalives\n");
1653         }
1654         
1655         if ((result = smb_request(server)) < 0) {
1656                 printk("smb_proc_connect: Failed to send SESSION REQUEST.\n");
1657                 smb_dont_catch_keepalive(server);
1658                 goto fail;
1659         }
1660         
1661         if (server->packet[0] != 0x82) {
1662                 printk("smb_proc_connect: Did not recieve positive response "
1663                        "(err = %x)\n", 
1664                        server->packet[0]);
1665                 smb_dont_catch_keepalive(server);
1666 #if DEBUG_SMB > 0
1667                 smb_dump_packet(server->packet);
1668 #endif
1669                 result = -EIO;
1670                 goto fail;
1671         }
1672 
1673         DPRINTK("smb_proc_connect: Passed SESSION REQUEST.\n");
1674         
1675         /* Now we are ready to send a SMB Negotiate Protocol packet. */
1676         memset(server->packet, 0, SMB_HEADER_LEN);
1677 
1678         plength = 0;
1679         for (i = 0; prots[i].name != NULL; i++) {
1680                 plength += strlen(prots[i].name) + 2;
1681         }
1682 
1683         smb_setup_header(server, SMBnegprot, 0, plength);
1684 
1685         p = SMB_BUF(server->packet);
1686         
1687         for (i = 0; prots[i].name != NULL; i++) {
1688                 p = smb_encode_dialect(p,prots[i].name, strlen(prots[i].name));
1689         }
1690         
1691         if ((result = smb_request_ok(server, SMBnegprot, 1, -1)) < 0) {
1692                 printk("smb_proc_connect: Failure requesting SMBnegprot\n");
1693                 smb_dont_catch_keepalive(server);
1694                 goto fail;
1695         } else {
1696                 DDPRINTK("smb_proc_connect: Request SMBnegprot..");
1697         }
1698 
1699         DDPRINTK("Verified!\n");
1700 
1701         p = SMB_VWV(server->packet);
1702         p = smb_decode_word(p, (word *)&i);
1703         server->protocol = prots[i].prot;
1704 
1705         DPRINTK("smb_proc_connect: Server wants %s protocol.\n",
1706                 prots[i].name);
1707 
1708         if (server->protocol > PROTOCOL_LANMAN1) {
1709 
1710                 word passlen = strlen(server->m.password);
1711                 word userlen = strlen(server->m.username);
1712                 
1713                 DPRINTK("smb_proc_connect: password = %s\n",
1714                         server->m.password);
1715                 DPRINTK("smb_proc_connect: usernam = %s\n",
1716                         server->m.username);
1717                 DPRINTK("smb_proc_connect: blkmode = %d\n",
1718                         WVAL(server->packet, smb_vwv5));
1719 
1720                 if (server->protocol >= PROTOCOL_NT1) {
1721                         server->maxxmt = DVAL(server->packet,smb_vwv3+1);
1722                         server->maxmux = WVAL(server->packet, smb_vwv1+1);
1723                         server->maxvcs = WVAL(server->packet, smb_vwv2+1);
1724                         server->blkmode= DVAL(server->packet, smb_vwv9+1);
1725                         server->sesskey= DVAL(server->packet, smb_vwv7+1);
1726                 } else {
1727                         server->maxxmt = WVAL(server->packet, smb_vwv2);
1728                         server->maxmux = WVAL(server->packet, smb_vwv3);
1729                         server->maxvcs = WVAL(server->packet, smb_vwv4);
1730                         server->blkmode= WVAL(server->packet, smb_vwv5);
1731                         server->sesskey= DVAL(server->packet, smb_vwv6);
1732                 }
1733 
1734 
1735                 if (server->protocol >= PROTOCOL_NT1) {
1736                         char *workgroup = "WORKGROUP";
1737                         char *OS_id = "Unix";
1738                         char *client_id = "ksmbfs";
1739 
1740                         smb_setup_header(server, SMBsesssetupX, 13,
1741                                          5 + userlen + passlen +
1742                                          strlen(workgroup) + strlen(OS_id) +
1743                                          strlen(client_id));
1744                         
1745                         WSET(server->packet, smb_vwv0, 0x00ff);
1746                         WSET(server->packet, smb_vwv1, 0);
1747                         WSET(server->packet, smb_vwv2, given_max_xmit);
1748                         WSET(server->packet, smb_vwv3, 2);
1749                         WSET(server->packet, smb_vwv4, server->pid);
1750                         DSET(server->packet, smb_vwv5, server->sesskey);
1751                         WSET(server->packet, smb_vwv7, passlen + 1);
1752                         WSET(server->packet, smb_vwv8, 0);
1753                         WSET(server->packet, smb_vwv9, 0);
1754 
1755                         p = SMB_BUF(server->packet);
1756                         strcpy(p, server->m.password);
1757                         p += passlen + 1;
1758                         strcpy(p, server->m.username);
1759                         p += userlen + 1;
1760                         strcpy(p, workgroup);
1761                         p += strlen(p) + 1;
1762                         strcpy(p, OS_id);
1763                         p += strlen(p) + 1;
1764                         strcpy(p, client_id);
1765                 } else {
1766                         smb_setup_header(server, SMBsesssetupX, 10,
1767                                          2 + userlen + passlen);
1768 
1769                         WSET(server->packet, smb_vwv0, 0x00ff);
1770                         WSET(server->packet, smb_vwv1, 0);
1771                         WSET(server->packet, smb_vwv2, given_max_xmit);
1772                         WSET(server->packet, smb_vwv3, 2);
1773                         WSET(server->packet, smb_vwv4, server->pid);
1774                         DSET(server->packet, smb_vwv5, server->sesskey);
1775                         WSET(server->packet, smb_vwv7, passlen + 1);
1776                         WSET(server->packet, smb_vwv8, 0);
1777                         WSET(server->packet, smb_vwv9, 0);
1778 
1779                         p = SMB_BUF(server->packet);
1780                         strcpy(p, server->m.password);
1781                         p += passlen + 1;
1782                         strcpy(p, server->m.username);
1783                 }
1784 
1785                 if ((result = smb_request_ok(server,SMBsesssetupX,3,0)) < 0) {
1786                         DPRINTK("smb_proc_connect: SMBsessetupX failed\n");
1787                         smb_dont_catch_keepalive(server);
1788                         goto fail;
1789                 }
1790                 smb_decode_word(server->packet+32, &(server->server_uid));
1791         }
1792         else
1793 
1794         {
1795                 server->maxxmt = 0;
1796                 server->maxmux = 0;
1797                 server->maxvcs = 0;
1798                 server->blkmode = 0;
1799                 server->sesskey = 0;
1800         }
1801 
1802         /* Fine! We have a connection, send a tcon message. */
1803 
1804         smb_setup_header(server, SMBtcon, 0,
1805                          6 + strlen(server->m.service) +
1806                          strlen(server->m.password) + strlen(dev));
1807         p = SMB_BUF(server->packet);
1808         p = smb_encode_ascii(p, server->m.service, strlen(server->m.service));
1809         p = smb_encode_ascii(p,server->m.password, strlen(server->m.password));
1810         p = smb_encode_ascii(p, dev, strlen(dev));
1811 
1812         if ((result = smb_request_ok(server, SMBtcon, 2, 0)) < 0) {
1813                 DPRINTK("smb_proc_connect: SMBtcon not verified.\n");
1814                 smb_dont_catch_keepalive(server);
1815                 goto fail;
1816         }
1817 
1818         DDPRINTK("OK! Managed to set up SMBtcon!\n");
1819    
1820         p = SMB_VWV(server->packet);
1821         p = smb_decode_word(p, &server->max_xmit);
1822 
1823         if (server->max_xmit > given_max_xmit)
1824                 server->max_xmit = given_max_xmit;
1825         
1826         p = smb_decode_word(p, &server->tid);
1827 
1828         /* Ok, everything is fine. max_xmit does not include */
1829         /* the TCP-SMB header of 4 bytes. */
1830         server->max_xmit += 4;
1831 
1832         DPRINTK("max_xmit = %d, tid = %d\n", server->max_xmit, server->tid);
1833 
1834         /* Now make a new packet with the correct size. */
1835         smb_kfree_s(server->packet, max_xmit); 
1836 
1837         server->packet = smb_kmalloc(server->max_xmit, GFP_KERNEL);
1838         if (server->packet == NULL) {
1839                 printk("smb_proc_connect: No memory left in end of "
1840                        "connection phase :-(\n");
1841                 smb_dont_catch_keepalive(server);
1842                 goto fail;
1843         }
1844 
1845         DPRINTK("smb_proc_connect: Normal exit\n");
1846         return 0;
1847 
1848  fail:
1849         server->state = CONN_INVALID;
1850         return result;
1851 }
1852 
1853 /* smb_proc_reconnect: server->packet is allocated with
1854    server->max_xmit bytes if and only if we return >= 0 */
1855 int
1856 smb_proc_connect(struct smb_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
1857 {
1858         int result;
1859         smb_lock_server(server);
1860         result = smb_proc_reconnect(server);
1861         if ((result < 0) && (server->packet != NULL)) {
1862                 smb_kfree_s(server->packet, server->max_xmit);
1863                 server->packet = NULL;
1864         }
1865         smb_unlock_server(server);
1866         return result;
1867 }
1868         
1869 int
1870 smb_proc_disconnect(struct smb_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
1871 {
1872         smb_setup_header_exclusive(server, SMBtdis, 0, 0);
1873         return smb_request_ok_unlock(server, SMBtdis, 0, 0);
1874 }
1875 
1876 /* error code stuff - put together by Merik Karman
1877    merik@blackadder.dsh.oz.au */
1878 
1879 #if DEBUG_SMB > 0
1880 
1881 typedef struct {
1882         char *name;
1883         int code;
1884         char *message;
1885 } err_code_struct;
1886 
1887 /* Dos Error Messages */
1888 err_code_struct dos_msgs[] = {
1889   { "ERRbadfunc",1,"Invalid function."},
1890   { "ERRbadfile",2,"File not found."},
1891   { "ERRbadpath",3,"Directory invalid."},
1892   { "ERRnofids",4,"No file descriptors available"},
1893   { "ERRnoaccess",5,"Access denied."},
1894   { "ERRbadfid",6,"Invalid file handle."},
1895   { "ERRbadmcb",7,"Memory control blocks destroyed."},
1896   { "ERRnomem",8,"Insufficient server memory to perform the requested function."},
1897   { "ERRbadmem",9,"Invalid memory block address."},
1898   { "ERRbadenv",10,"Invalid environment."},
1899   { "ERRbadformat",11,"Invalid format."},
1900   { "ERRbadaccess",12,"Invalid open mode."},
1901   { "ERRbaddata",13,"Invalid data."},
1902   { "ERR",14,"reserved."},
1903   { "ERRbaddrive",15,"Invalid drive specified."},
1904   { "ERRremcd",16,"A Delete Directory request attempted  to  remove  the  server's  current directory."},
1905   { "ERRdiffdevice",17,"Not same device."},
1906   { "ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."},
1907   { "ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing  FIDs  on the file."},
1908   { "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."},
1909   { "ERRfilexists",80,"The file named in a Create Directory, Make  New  File  or  Link  request already exists."},
1910   { "ERRbadpipe",230,"Pipe invalid."},
1911   { "ERRpipebusy",231,"All instances of the requested pipe are busy."},
1912   { "ERRpipeclosing",232,"Pipe close in progress."},
1913   { "ERRnotconnected",233,"No process on other end of pipe."},
1914   { "ERRmoredata",234,"There is more data to be returned."},
1915   { NULL,-1,NULL}};
1916 
1917 /* Server Error Messages */
1918 err_code_struct server_msgs[] = { 
1919   { "ERRerror",1,"Non-specific error code."},
1920   { "ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
1921   { "ERRbadtype",3,"reserved."},
1922   { "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."},
1923   { "ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."},
1924   { "ERRinvnetname",6,"Invalid network name in tree connect."},
1925   { "ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or  non-printer request made to printer connection."},
1926   { "ERRqfull",49,"Print queue full (files) -- returned by open print file."},
1927   { "ERRqtoobig",50,"Print queue full -- no space."},
1928   { "ERRqeof",51,"EOF on print queue dump."},
1929   { "ERRinvpfid",52,"Invalid print file FID."},
1930   { "ERRsmbcmd",64,"The server did not recognize the command received."},
1931   { "ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."},
1932   { "ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid  combination of values."},
1933   { "ERRreserved",68,"reserved."},
1934   { "ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination.  The server cannot set the requested attribute."},
1935   { "ERRreserved",70,"reserved."},
1936   { "ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."},
1937   { "ERRpaused",81,"Server is paused."},
1938   { "ERRmsgoff",82,"Not receiving messages."},
1939   { "ERRnoroom",83,"No room to buffer message."},
1940   { "ERRrmuns",87,"Too many remote user names."},
1941   { "ERRtimeout",88,"Operation timed out."},
1942   { "ERRnoresource",89,"No resources currently available for request."},
1943   { "ERRtoomanyuids",90,"Too many UIDs active on this session."},
1944   { "ERRbaduid",91,"The UID is not known as a valid ID on this session."},
1945   { "ERRusempx",250,"Temp unable to support Raw, use MPX mode."},
1946   { "ERRusestd",251,"Temp unable to support Raw, use standard read/write."},
1947   { "ERRcontmpx",252,"Continue in MPX mode."},
1948   { "ERRreserved",253,"reserved."},
1949   { "ERRreserved",254,"reserved."},
1950   { "ERRnosupport",0xFFFF,"Function not supported."},
1951   { NULL,-1,NULL}};
1952 
1953 /* Hard Error Messages */
1954 err_code_struct hard_msgs[] = { 
1955   { "ERRnowrite",19,"Attempt to write on write-protected diskette."},
1956   { "ERRbadunit",20,"Unknown unit."},
1957   { "ERRnotready",21,"Drive not ready."},
1958   { "ERRbadcmd",22,"Unknown command."},
1959   { "ERRdata",23,"Data error (CRC)."},
1960   { "ERRbadreq",24,"Bad request structure length."},
1961   { "ERRseek",25 ,"Seek error."},
1962   { "ERRbadmedia",26,"Unknown media type."},
1963   { "ERRbadsector",27,"Sector not found."},
1964   { "ERRnopaper",28,"Printer out of paper."},
1965   { "ERRwrite",29,"Write fault."},
1966   { "ERRread",30,"Read fault."},
1967   { "ERRgeneral",31,"General failure."},
1968   { "ERRbadshare",32,"A open conflicts with an existing open."},
1969   { "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."},
1970   { "ERRwrongdisk",34,"The wrong disk was found in a drive."},
1971   { "ERRFCBUnavail",35,"No FCBs are available to process request."},
1972   { "ERRsharebufexc",36,"A sharing buffer has been exceeded."},
1973   { NULL,-1,NULL}
1974 };
1975 
1976 
1977 struct { 
1978         int code;
1979         char *class;
1980         err_code_struct *err_msgs;
1981 } err_classes[] = {  
1982   { 0,"SUCCESS",NULL},
1983   { 0x01,"ERRDOS",dos_msgs},
1984   { 0x02,"ERRSRV",server_msgs},
1985   { 0x03,"ERRHRD",hard_msgs},
1986   { 0x04,"ERRXOS",NULL},
1987   { 0xE1,"ERRRMX1",NULL},
1988   { 0xE2,"ERRRMX2",NULL},
1989   { 0xE3,"ERRRMX3",NULL},
1990   { 0xFF,"ERRCMD",NULL},
1991   { -1,NULL,NULL}
1992 };
1993 
1994 void
1995 smb_printerr(int class, int num)
     /* [previous][next][first][last][top][bottom][index][help] */
1996 {
1997         int i,j;
1998         err_code_struct *err;
1999 
2000         for (i=0; err_classes[i].class; i++) {
2001                 if (err_classes[i].code != class)
2002                         continue;
2003                 if (!err_classes[i].err_msgs) {
2004                         printk("%s - %d", err_classes[i].class, num);
2005                         return;
2006                 }
2007 
2008                 err = err_classes[i].err_msgs;
2009                 for (j=0; err[j].name; j++) {
2010                         if (num != err[j].code)
2011                                 continue;
2012                         printk("%s - %s (%s)",
2013                                err_classes[i].class, err[j].name,
2014                                err[j].message);
2015                         return;
2016                 }
2017         }
2018         
2019         printk("Unknown error - (%d,%d)", class, num);
2020         return;
2021 }
2022 
2023 #endif /* DEBUG_SMB > 0 */
2024 
2025 /*
2026  * Overrides for Emacs so that we follow Linus's tabbing style.
2027  * Emacs will notice this stuff at the end of the file and automatically
2028  * adjust the settings for this buffer only.  This must remain at the end
2029  * of the file.
2030  * ---------------------------------------------------------------------------
2031  * Local variables:
2032  * c-indent-level: 8
2033  * c-brace-imaginary-offset: 0
2034  * c-brace-offset: -8
2035  * c-argdecl-indent: 8
2036  * c-label-offset: -8
2037  * c-continued-statement-offset: 8
2038  * c-continued-brace-offset: 0
2039  * End:
2040  */

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