root/fs/smbfs/proc.c

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

DEFINITIONS

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

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