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

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