root/fs/smbfs/dir.c

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

DEFINITIONS

This source file includes following definitions.
  1. str_upper
  2. str_lower
  3. smb_dir_read
  4. smb_readdir1
  5. smb_readdir
  6. smb_init_dir_cache
  7. smb_invalid_dir_cache
  8. smb_free_dir_cache
  9. get_pname_static
  10. get_pname
  11. put_pname
  12. smb_iget
  13. smb_free_inode_info
  14. smb_init_root
  15. smb_stat_root
  16. smb_free_all_inodes
  17. smb_invalidate_all_inodes
  18. smb_find_inode
  19. smb_lookup
  20. smb_create
  21. smb_mkdir
  22. smb_rmdir
  23. smb_unlink
  24. smb_rename

   1 /*
   2  *  dir.c
   3  *
   4  *  Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke
   5  *
   6  */
   7 
   8 #include <linux/config.h>
   9 #ifdef MODULE
  10 #include <linux/module.h>
  11 #include <linux/version.h>
  12 #endif
  13 
  14 #include <linux/sched.h>
  15 #include <linux/errno.h>
  16 #include <linux/stat.h>
  17 #include <linux/kernel.h>
  18 #include <linux/malloc.h>
  19 #include <linux/mm.h>
  20 #include <linux/smb_fs.h>
  21 #include <asm/segment.h>
  22 #include <linux/errno.h>
  23 
  24 #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
  25 #define ROUND_UP(x) (((x)+3) & ~3)
  26 
  27 static int 
  28 smb_dir_read(struct inode *inode, struct file *filp, char *buf, int count);
  29 
  30 static int 
  31 smb_readdir(struct inode *inode, struct file *filp,
  32             void *dirent, filldir_t filldir);
  33 
  34 static int 
  35 get_pname(struct inode *dir, const char *name, int len,
  36           char **res_path, int *res_len);
  37 
  38 static int
  39 get_pname_static(struct inode *dir, const char *name, int len,
  40                  char *path, int *res_len);
  41 
  42 static struct inode *
  43 smb_iget(struct inode *dir, char *path, struct smb_dirent *finfo);
  44 
  45 static void 
  46 put_pname(char *path);
  47 
  48 static struct smb_inode_info *
  49 smb_find_inode(struct smb_server *server, const char *path);
  50 
  51 static int
  52 smb_lookup(struct inode *dir, const char *__name,
  53            int len, struct inode **result);
  54 
  55 static int 
  56 smb_create(struct inode *dir, const char *name, int len, int mode, 
  57            struct inode **result);
  58 
  59 static int 
  60 smb_mkdir(struct inode *dir, const char *name, int len, int mode);
  61 
  62 static int 
  63 smb_rmdir(struct inode *dir, const char *name, int len);
  64 
  65 static int
  66 smb_unlink(struct inode *dir, const char *name, int len);
  67 
  68 static int
  69 smb_rename(struct inode *old_dir, const char *old_name, int old_len, 
  70            struct inode *new_dir, const char *new_name, int new_len);
  71 
  72 static inline void str_upper(char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
  73 {
  74         while (*name) {
  75                 if (*name >= 'a' && *name <= 'z')
  76                         *name -= ('a' - 'A');
  77                 name++;
  78         }
  79 }
  80 
  81 static inline void str_lower(char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
  82 {
  83         while (*name) {
  84                 if (*name >= 'A' && *name <= 'Z')
  85                         *name += ('a' - 'A');
  86                 name ++;
  87         }
  88 }
  89 
  90 static struct file_operations smb_dir_operations = {
  91         NULL,                   /* lseek - default */
  92         smb_dir_read,           /* read - bad */
  93         NULL,                   /* write - bad */
  94         smb_readdir,            /* readdir */
  95         NULL,                   /* select - default */
  96         smb_ioctl,              /* ioctl - default */
  97         NULL,                   /* mmap */
  98         NULL,                   /* no special open code */
  99         NULL,                   /* no special release code */
 100         NULL                    /* fsync */
 101 };
 102 
 103 struct inode_operations smb_dir_inode_operations = 
 104 {
 105         &smb_dir_operations,    /* default directory file ops */
 106         smb_create,             /* create */
 107         smb_lookup,             /* lookup */
 108         NULL,                   /* link */
 109         smb_unlink,             /* unlink */
 110         NULL,                   /* symlink */
 111         smb_mkdir,              /* mkdir */
 112         smb_rmdir,              /* rmdir */
 113         NULL,                   /* mknod */
 114         smb_rename,             /* rename */
 115         NULL,                   /* readlink */
 116         NULL,                   /* follow_link */
 117         NULL,                   /* bmap */
 118         NULL,                   /* truncate */
 119         NULL,                   /* permission */
 120         NULL                    /* smap */
 121 };
 122 
 123 
 124 static int 
 125 smb_dir_read(struct inode *inode, struct file *filp, char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 126 {
 127         return -EISDIR;
 128 }
 129 
 130 /*
 131  * Description:
 132  *  smb_readdir provides a listing in the form of filling the dirent structure.
 133  *  Note that dirent resides in the user space. This is to support reading of a
 134  *  directory "stream". 
 135  * Arguments:
 136  *  inode   ---  Pointer to to the directory.
 137  *  filp    ---  The directory stream. (filp->f_pos indicates
 138  *               position in the stream.)
 139  *  dirent  ---  Will hold count directory entries. (Is in user space.)
 140  *  count   ---  Number of entries to be read. Should indicate the total 
 141  *               buffer space available for filling with dirents.
 142  * Return values:
 143  *     < 0     ---  An error occured (linux/errno.h).
 144  *     = 0     ---
 145  *     > 0     ---  Success, amount of bytes written to dirent.
 146  * Notes:
 147  *     Since we want to reduce directory lookups we revert into a
 148  *     dircache. It is taken rather directly out of the nfs_readdir.
 149  */
 150 
 151 /* In smbfs, we have unique inodes across all mounted filesystems, for
 152    all inodes that are in memory. That's why it's enough to index the
 153    directory cache by the inode number. */
 154 
 155 static unsigned long      c_ino = 0;
 156 static int                c_size;
 157 static int                c_seen_eof;
 158 static int                c_last_returned_index;
 159 static struct smb_dirent* c_entry = NULL;
 160 
 161 static int
 162 smb_readdir1(struct inode *inode, const struct file *filp,
     /* [previous][next][first][last][top][bottom][index][help] */
 163              struct smb_dirent *ret,ino_t *ino)
 164 {
 165         int result, i = 0;
 166         struct smb_dirent *entry = NULL;
 167         struct smb_server *server = SMB_SERVER(inode);
 168 
 169         DDPRINTK("smb_readdir: filp->f_pos = %d\n", (int)filp->f_pos);
 170         DDPRINTK("smb_readdir: inode->i_ino = %ld, c_ino = %ld\n",
 171                  inode->i_ino, c_ino);
 172 
 173         if (!inode || !S_ISDIR(inode->i_mode)) {
 174                 printk("smb_readdir: inode is NULL or not a directory\n");
 175                 return -EBADF;
 176         }
 177 
 178         if (c_entry == NULL) 
 179         {
 180                 i = sizeof (struct smb_dirent) * SMB_READDIR_CACHE_SIZE;
 181                 c_entry = (struct smb_dirent *) smb_kmalloc(i, GFP_KERNEL);
 182                 for (i = 0; i < SMB_READDIR_CACHE_SIZE; i++) {
 183                         c_entry[i].path =
 184                                 (char *) smb_kmalloc(SMB_MAXNAMELEN + 1,
 185                                                      GFP_KERNEL);
 186                         if (c_entry[i].path == NULL) {
 187                                 DPRINTK("smb_readdir: could not alloc path\n");
 188                         }
 189                 }
 190         }
 191 
 192         if (filp->f_pos == 0) {
 193                 smb_invalid_dir_cache(inode->i_ino);
 194         }
 195 
 196         if (inode->i_ino == c_ino) {
 197                 for (i = 0; i < c_size; i++) {
 198                         if (filp->f_pos == c_entry[i].f_pos) {
 199                                 entry = &c_entry[i];
 200                                 c_last_returned_index = i;
 201                                 break;
 202                         }
 203                 }
 204                 if ((entry == NULL) && c_seen_eof)
 205                         return 0;
 206         }
 207 
 208         if (entry == NULL) {
 209                 DPRINTK("smb_readdir: Not found in cache.\n");
 210                 result = smb_proc_readdir(server, inode,
 211                                           filp->f_pos, SMB_READDIR_CACHE_SIZE,
 212                                           c_entry);
 213 
 214                 if (result < 0) {
 215                         c_ino = 0;
 216                         return result;
 217                 }
 218 
 219                 if (result > 0) {
 220                         c_seen_eof = (result < SMB_READDIR_CACHE_SIZE);
 221                         c_ino  = inode->i_ino;
 222                         c_size = result;
 223                         entry = c_entry;
 224                         c_last_returned_index = 0;
 225                         for (i = 0; i < c_size; i++) {
 226 
 227                                 switch (server->case_handling) 
 228                                 {
 229                                 case CASE_UPPER:
 230                                         str_upper(c_entry[i].path); break;
 231                                 case CASE_LOWER:
 232                                         str_lower(c_entry[i].path); break;
 233                                 case CASE_DEFAULT:
 234                                         break;
 235                                 }
 236                         }
 237                 }
 238         }
 239         
 240         if (entry) {
 241 
 242                 /* We found it.  For getwd(), we have to return the
 243                    correct inode in d_ino if the inode is currently in
 244                    use. Otherwise the inode number does not
 245                    matter. */ 
 246 
 247                 int  path_len;
 248                 struct smb_inode_info *ino_info;
 249                 char complete_path[SMB_MAXPATHLEN];
 250 
 251                 
 252 
 253                 i = strlen(entry->path);
 254                 if ((result = get_pname_static(inode, entry->path, i,
 255                                                complete_path,
 256                                                &path_len)) < 0)
 257                         return result;
 258 
 259                 ino_info = smb_find_inode(server, complete_path);
 260 
 261                 /* Some programs seem to be confused about a zero
 262                    inode number, so we set it to one.  Thanks to
 263                    Gordon Chaffee for this one. */
 264                 if (ino_info == NULL) {
 265                         ino_info = (struct smb_inode_info *) 1;
 266                 }
 267 
 268                 DDPRINTK("smb_readdir: entry->path = %s\n", entry->path);
 269                 DDPRINTK("smb_readdir: entry->f_pos = %ld\n", entry->f_pos);
 270 
 271                 *ino = (ino_t)ino_info; /* use the pointer as the
 272                                           inode - dangerous if we have
 273                                           64 bit pointers! FIXME */
 274 
 275                 *ret = *entry;
 276                 return 1;
 277         }
 278 
 279         return 0;
 280 }
 281 
 282 static int 
 283 smb_readdir(struct inode *inode, struct file *filp,
     /* [previous][next][first][last][top][bottom][index][help] */
 284             void *dirent, filldir_t filldir)
 285 {
 286         struct smb_dirent d;
 287         ino_t ino;
 288 
 289         while (smb_readdir1(inode,filp,&d,&ino) == 1) {         
 290                 if (filldir(dirent,d.path,strlen(d.path)+1,
 291                             filp->f_pos,ino) < 0) {
 292                         return 0;
 293                 }
 294                 filp->f_pos++;
 295         }
 296         return 0;
 297 }
 298 
 299 void
 300 smb_init_dir_cache(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 301 {
 302         c_ino   = 0;
 303         c_entry = NULL;
 304 }
 305 
 306 void
 307 smb_invalid_dir_cache(unsigned long ino)
     /* [previous][next][first][last][top][bottom][index][help] */
 308 {
 309         if (ino == c_ino) {
 310                 c_ino = 0;
 311                 c_seen_eof = 0;
 312         }
 313 }
 314 
 315 void
 316 smb_free_dir_cache(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 317 {
 318         int i;
 319 
 320         DPRINTK("smb_free_dir_cache: enter\n");
 321         
 322         if (c_entry == NULL)
 323                 return;
 324 
 325         for (i = 0; i < SMB_READDIR_CACHE_SIZE; i++) {
 326                 smb_kfree_s(c_entry[i].path, NAME_MAX + 1);
 327         }
 328 
 329         smb_kfree_s(c_entry,
 330                     sizeof(struct smb_dirent) * SMB_READDIR_CACHE_SIZE);
 331         c_entry = NULL;
 332 
 333         DPRINTK("smb_free_dir_cache: exit\n");
 334 }
 335 
 336 
 337 /* get_pname_static: it expects the res_path to be a preallocated
 338    string of len SMB_MAXPATHLEN. */
 339 
 340 static int
 341 get_pname_static(struct inode *dir, const char *name, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 342                  char *path, int *res_len)
 343 {
 344         char *parentname = SMB_INOP(dir)->finfo.path;
 345         int   parentlen  = SMB_INOP(dir)->finfo.len;
 346 
 347 #if 1
 348         if (parentlen != strlen(parentname)) {
 349                 printk("get_pname: parent->finfo.len = %d instead of %d\n",
 350                        parentlen, strlen(parentname));
 351                 parentlen = strlen(parentname);
 352         }
 353         
 354 #endif
 355         DDPRINTK("get_pname_static: parentname = %s, len = %d\n",
 356                  parentname, parentlen);
 357         
 358         if (len > SMB_MAXNAMELEN) {
 359                 return -ENAMETOOLONG;
 360         }
 361 
 362         /* Fast cheat for . */
 363         if (len == 0 || (len == 1 && name[0] == '.')) {
 364 
 365                 memcpy(path, parentname, parentlen + 1);
 366                 *res_len = parentlen;
 367                 return 0;
 368         }
 369         
 370         /* Hmm, what about .. ? */
 371         if (len == 2 && name[0] == '.' && name[1] == '.') {
 372 
 373                 char *pos = strrchr(parentname, '\\');
 374 
 375                 if (   (pos == NULL)
 376                     && (parentlen == 0)) {
 377 
 378                         /* We're at the top */
 379 
 380                         path[0] = '\\';
 381                         path[1] = '\0';
 382                         *res_len  = 2;
 383                         return 0;
 384                 }
 385                         
 386                 
 387                 if (pos == NULL) {
 388                         printk("smb_make_name: Bad parent SMB-name: %s",
 389                                parentname);
 390                         return -ENODATA;
 391                 }
 392                 
 393                 len = pos - parentname;
 394 
 395                 memcpy(path, parentname, len);
 396                 path[len] = '\0';
 397         }
 398         else
 399         {
 400                 if (len + parentlen + 2 > SMB_MAXPATHLEN) 
 401                         return -ENAMETOOLONG;
 402                                 
 403                 memcpy(path, parentname, parentlen);
 404                 path[parentlen] = '\\';
 405                 memcpy(path + parentlen + 1, name, len);
 406                 path[parentlen + 1 + len] = '\0';
 407                 len = parentlen + len + 1;
 408         }
 409 
 410         switch (SMB_SERVER(dir)->case_handling) 
 411         {
 412         case CASE_UPPER: 
 413                 str_upper(path); 
 414                 break;
 415         case CASE_LOWER: 
 416                 str_lower(path); 
 417                 break;
 418         case CASE_DEFAULT: 
 419                 break;
 420         }
 421 
 422         *res_len = len;
 423 
 424         DDPRINTK("get_pname: path = %s, *pathlen = %d\n",
 425                  path, *res_len);
 426         return 0;
 427 }
 428         
 429 static int 
 430 get_pname(struct inode *dir, const char *name, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 431           char **res_path, int *res_len)
 432 {
 433         char result[SMB_MAXPATHLEN];
 434         int  result_len;
 435         int  res;
 436 
 437         if ((res = get_pname_static(dir,name,len,result,&result_len) != 0)) {
 438                 return res;
 439         }
 440 
 441         if ((*res_path = smb_kmalloc(result_len+1, GFP_KERNEL)) == NULL) {
 442                 printk("get_pname: Out of memory while allocating name.");
 443                 return -ENOMEM;
 444         }
 445 
 446         strcpy(*res_path, result);
 447         *res_len = result_len;
 448         return 0;
 449 }
 450 
 451 static void
 452 put_pname(char *path)
     /* [previous][next][first][last][top][bottom][index][help] */
 453 {
 454         smb_kfree_s(path, 0);
 455 }
 456 
 457 /* Insert a NEW smb_inode_info into the inode tree of our filesystem,
 458    under dir. The caller must assure that it's not already there. We
 459    assume that path is allocated for us. */
 460 
 461 static struct inode *
 462 smb_iget(struct inode *dir, char *path, struct smb_dirent *finfo)
     /* [previous][next][first][last][top][bottom][index][help] */
 463 {
 464         struct smb_dirent newent = { 0 };
 465         struct inode *inode;
 466         int error, len;
 467         struct smb_inode_info *new_inode_info;
 468         struct smb_inode_info *root;
 469 
 470         if (!dir) {
 471                 printk("smb_iget: dir is NULL\n");
 472                 return NULL;
 473         }
 474 
 475         if (!path) {
 476                 printk("smb_iget: path is NULL\n");
 477                 return NULL;
 478         }
 479 
 480         len = strlen(path);
 481         
 482         if (!finfo) {
 483                 error = smb_proc_getattr(&(SMB_SBP(dir->i_sb)->s_server),
 484                                          path, len, &newent);
 485                 if (error) {
 486                         printk("smb_iget: getattr error = %d\n", -error);
 487                         return NULL;
 488                 }               
 489                 finfo = &newent;
 490                 DPRINTK("smb_iget: Read finfo:\n");
 491                 DPRINTK("smb_iget: finfo->attr = 0x%X\n", finfo->attr);
 492         }
 493 
 494         new_inode_info = smb_kmalloc(sizeof(struct smb_inode_info),
 495                                      GFP_KERNEL);
 496 
 497         if (new_inode_info == NULL) {
 498                 printk("smb_iget: could not alloc mem for %s\n", path);
 499                 return NULL;
 500         }
 501 
 502         new_inode_info->state = INODE_LOOKED_UP;
 503         new_inode_info->nused = 0;
 504         new_inode_info->dir   = SMB_INOP(dir);
 505 
 506         new_inode_info->finfo        = *finfo;
 507         new_inode_info->finfo.opened = 0;
 508         new_inode_info->finfo.path   = path;
 509         new_inode_info->finfo.len    = len;
 510 
 511         SMB_INOP(dir)->nused += 1;
 512 
 513         /* We have to link the new inode_info into the doubly linked
 514            list of inode_infos to make a complete linear search
 515            possible. */
 516 
 517         root = &(SMB_SERVER(dir)->root);
 518 
 519         new_inode_info->prev = root;
 520         new_inode_info->next = root->next;
 521         root->next->prev = new_inode_info;
 522         root->next = new_inode_info;
 523         
 524         if (!(inode = iget(dir->i_sb, (int)new_inode_info))) {
 525                 printk("smb_iget: iget failed!");
 526                 return NULL;
 527         }
 528 
 529         return inode;
 530 }
 531 
 532 void
 533 smb_free_inode_info(struct smb_inode_info *i)
     /* [previous][next][first][last][top][bottom][index][help] */
 534 {
 535         if (i == NULL) {
 536                 printk("smb_free_inode: i == NULL\n");
 537                 return;
 538         }
 539 
 540         i->state = INODE_CACHED;
 541         while ((i->nused == 0) && (i->state == INODE_CACHED)) {
 542                 struct smb_inode_info *dir = i->dir;
 543 
 544                 i->next->prev = i->prev;
 545                 i->prev->next = i->next;
 546 
 547                 smb_kfree_s(i->finfo.path, i->finfo.len+1);
 548                 smb_kfree_s(i, sizeof(struct smb_inode_info));
 549 
 550                 if (dir == NULL) return;
 551 
 552                 (dir->nused)--;
 553                 i = dir;
 554         }
 555 }
 556         
 557 void
 558 smb_init_root(struct smb_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
 559 {
 560         struct smb_inode_info *root = &(server->root);
 561 
 562         root->finfo.path = server->m.root_path;
 563         root->finfo.len  = strlen(root->finfo.path);
 564         root->finfo.opened = 0;
 565 
 566         root->state = INODE_LOOKED_UP;
 567         root->nused = 1;
 568         root->dir   = NULL;
 569         root->next = root->prev = root;
 570         return;
 571 }
 572 
 573 int
 574 smb_stat_root(struct smb_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
 575 {
 576         struct smb_inode_info *root = &(server->root);
 577         int result;
 578 
 579         if (root->finfo.len == 0) {
 580                 result = smb_proc_getattr(server, "\\", 1, &(root->finfo));
 581         }
 582         else
 583         {
 584                 result = smb_proc_getattr(server, 
 585                                           root->finfo.path, root->finfo.len,
 586                                           &(root->finfo));
 587         }
 588         return result;
 589 }
 590 
 591 void
 592 smb_free_all_inodes(struct smb_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
 593 {
 594         /* Here nothing should be to do. I do not know whether it's
 595            better to leave some memory allocated or be stuck in an
 596            endless loop */
 597 #if 1
 598         struct smb_inode_info *root = &(server->root);
 599 
 600         if (root->next != root) {
 601                 printk("smb_free_all_inodes: INODES LEFT!!!\n");
 602         }
 603 
 604         while (root->next != root) {
 605                 printk("smb_free_all_inodes: freeing inode\n");
 606                 smb_free_inode_info(root->next);
 607                 /* In case we have an endless loop.. */
 608                 schedule();
 609         }
 610 #endif        
 611         
 612         return;
 613 }
 614 
 615 /* This has to be called when a connection has gone down, so that all
 616    file-handles we got from the server are invalid */
 617 
 618 void
 619 smb_invalidate_all_inodes(struct smb_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
 620 {
 621         struct smb_inode_info *ino = &(server->root);
 622 
 623         do {
 624                 ino->finfo.opened = 0;
 625                 ino = ino->next;
 626         } while (ino != &(server->root));
 627         
 628         return;
 629 }
 630         
 631 
 632 /* We will search the inode that belongs to this name, currently by a
 633    complete linear search through the inodes belonging to this
 634    filesystem. This has to be fixed. */
 635 
 636 static struct smb_inode_info *
 637 smb_find_inode(struct smb_server *server, const char *path)
     /* [previous][next][first][last][top][bottom][index][help] */
 638 {
 639         struct smb_inode_info *result = &(server->root);
 640 
 641         if (path == NULL)
 642                 return NULL;
 643 
 644         do {
 645                 if (strcmp(result->finfo.path, path) == 0)
 646                         return result;
 647                 result = result->next;
 648 
 649         } while (result != &(server->root));
 650 
 651         return NULL;
 652 }
 653 
 654 
 655 static int 
 656 smb_lookup(struct inode *dir, const char *__name, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 657            struct inode **result)
 658 {
 659         char *name = NULL;
 660         struct smb_dirent finfo;
 661         struct smb_inode_info *result_info;
 662         int error;
 663         int found_in_cache;
 664 
 665         *result = NULL;
 666 
 667         if (!dir || !S_ISDIR(dir->i_mode)) {
 668                 printk("smb_lookup: inode is NULL or not a directory.\n");
 669                 iput(dir);
 670                 return -ENOENT;
 671         }
 672 
 673         DDPRINTK("smb_lookup: %s\n", __name);
 674 
 675         /* Fast cheat for . */
 676         if (len == 0 || (len == 1 && __name[0] == '.')) {
 677                 *result = dir;
 678                 return 0;
 679         }
 680 
 681         /* Now we will have to build up an SMB filename. */
 682         if ((error = get_pname(dir, __name, len, &name, &len)) < 0) {
 683                 iput(dir);
 684                 return error;
 685         }
 686 
 687         result_info = smb_find_inode(SMB_SERVER(dir), name);
 688 
 689         if (result_info != 0) {
 690 
 691                 if (result_info->state == INODE_CACHED)
 692                         result_info->state = INODE_LOOKED_UP;
 693 
 694                 put_pname(name);
 695 
 696                 /* Here we convert the inode_info address into an
 697                    inode number */
 698 
 699                 *result = iget(dir->i_sb, (int)result_info);
 700                 iput(dir);
 701 
 702                 if (*result == NULL) {
 703                         return -EACCES;
 704                 } else {
 705                         return 0;
 706                 }
 707         }
 708 
 709         /* Ok, now we have made our name. We have to build a new
 710            smb_inode_info struct and insert it into the tree, if it is
 711            a name that exists on the server */
 712 
 713         /* If the file is in the dir cache, we do not have to ask the
 714            server. */
 715 
 716         found_in_cache = 0;
 717         
 718         if (dir->i_ino == c_ino) {
 719                 int first = c_last_returned_index - 1;
 720                 int i;
 721 
 722                 if (first < 0) {
 723                         first = c_size - 1;
 724                 }
 725 
 726                 i = first;
 727                 do {
 728                         DDPRINTK("smb_lookup: trying index: %d, name: %s\n",
 729                                 i, c_entry[i].path);
 730                         if (strcmp(c_entry[i].path, __name) == 0) {
 731                                 DPRINTK("smb_lookup: found in cache!\n");
 732                                 finfo = c_entry[i];
 733                                 finfo.path = NULL; /* It's not ours! */
 734                                 found_in_cache = 1;
 735                                 break;
 736                         }
 737                         i = (i + 1) % c_size;
 738 
 739                 } while (i != first);
 740         }
 741 
 742         if (found_in_cache == 0) {
 743                 error = smb_proc_getattr(SMB_SERVER(dir), name, len, &finfo);
 744                 if (error < 0) {
 745                         put_pname(name);
 746                         iput(dir);
 747                         return error;
 748                 }
 749         }
 750 
 751         if (!(*result = smb_iget(dir, name, &finfo))) {
 752                 put_pname(name);
 753                 iput(dir);
 754                 return -EACCES;
 755         }
 756 
 757         DDPRINTK("smb_lookup: %s => %lu\n", name, (unsigned long)result_info);
 758         iput(dir);
 759         return 0;
 760 }
 761 
 762 static int 
 763 smb_create(struct inode *dir, const char *name, int len, int mode,
     /* [previous][next][first][last][top][bottom][index][help] */
 764            struct inode **result)
 765 {
 766         int error;
 767         char *path = NULL;
 768         struct smb_dirent entry;
 769 
 770         *result = NULL;
 771 
 772         if (!dir || !S_ISDIR(dir->i_mode)) {
 773                 printk("smb_create: inode is NULL or not a directory\n");
 774                 iput(dir);
 775                 return -ENOENT;
 776         }
 777 
 778         /* Now we will have to build up an SMB filename. */
 779         if ((error = get_pname(dir, name, len, &path, &len)) < 0) {
 780                 iput(dir);
 781                 return error;
 782         }
 783 
 784         entry.attr  = 0;
 785         entry.ctime = CURRENT_TIME;
 786         entry.atime = CURRENT_TIME;
 787         entry.mtime = CURRENT_TIME;
 788         entry.size  = 0;
 789 
 790         error = smb_proc_create(SMB_SERVER(dir), path, len, &entry);
 791         if (error < 0) {
 792                 put_pname(path);
 793                 iput(dir);
 794                 return error;
 795         }
 796 
 797         smb_invalid_dir_cache(dir->i_ino);
 798 
 799         if (!(*result = smb_iget(dir, path, &entry)) < 0) {
 800                 put_pname(path);
 801                 iput(dir);
 802                 return error;
 803         }
 804         iput(dir);
 805         return 0;       
 806 }
 807 
 808 static int
 809 smb_mkdir(struct inode *dir, const char *name, int len, int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 810 {
 811         int error;
 812         char path[SMB_MAXPATHLEN];
 813 
 814         if (!dir || !S_ISDIR(dir->i_mode)) {
 815                 printk("smb_mkdir: inode is NULL or not a directory\n");
 816                 iput(dir);
 817                 return -ENOENT;
 818         }
 819 
 820         /* Now we will have to build up an SMB filename. */
 821         if ((error = get_pname_static(dir, name, len, path, &len)) < 0) {
 822                 iput(dir);
 823                 return error;
 824         }
 825 
 826         if ((error = smb_proc_mkdir(SMB_SERVER(dir), path, len)) == 0) {
 827                 smb_invalid_dir_cache(dir->i_ino);
 828         }
 829 
 830         iput(dir);
 831         return error;
 832 }
 833 
 834 static int
 835 smb_rmdir(struct inode *dir, const char *name, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 836 {
 837         int error;
 838         char path[SMB_MAXPATHLEN];
 839 
 840         if (!dir || !S_ISDIR(dir->i_mode)) {
 841                 printk("smb_rmdir: inode is NULL or not a directory\n");
 842                 iput(dir);
 843                 return -ENOENT;
 844         }
 845         if ((error = get_pname_static(dir, name, len, path, &len)) < 0) {
 846                 iput(dir);
 847                 return error;
 848         }
 849         if (smb_find_inode(SMB_SERVER(dir), path) != NULL) {
 850                 error = -EBUSY;
 851         } else {
 852                 if ((error = smb_proc_rmdir(SMB_SERVER(dir), path, len)) == 0)
 853                         smb_invalid_dir_cache(dir->i_ino);
 854         }
 855         iput(dir);
 856         return error;
 857 }
 858 
 859 static int
 860 smb_unlink(struct inode *dir, const char *name, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 861 {
 862         int error;
 863         char path[SMB_MAXPATHLEN];
 864 
 865         if (!dir || !S_ISDIR(dir->i_mode)) {
 866                 printk("smb_unlink: inode is NULL or not a directory\n");
 867                 iput(dir);
 868                 return -ENOENT;
 869         }
 870         if ((error = get_pname_static(dir, name, len, path, &len)) < 0) {
 871                 iput(dir);
 872                 return error;
 873         }
 874         if (smb_find_inode(SMB_SERVER(dir), path) != NULL) {
 875                 error = -EBUSY;
 876         } else {
 877                 if ((error = smb_proc_unlink(SMB_SERVER(dir), path, len)) == 0)
 878                         smb_invalid_dir_cache(dir->i_ino);
 879         }
 880 
 881         iput(dir);
 882         return error;
 883 }
 884 
 885 static int
 886 smb_rename(struct inode *old_dir, const char *old_name, int old_len,
     /* [previous][next][first][last][top][bottom][index][help] */
 887            struct inode *new_dir, const char *new_name, int new_len)
 888 {
 889         int res;
 890         char old_path[SMB_MAXPATHLEN], new_path[SMB_MAXPATHLEN];
 891 
 892         if (!old_dir || !S_ISDIR(old_dir->i_mode)) {
 893                 printk("smb_rename: old inode is NULL or not a directory\n");
 894                 res = -ENOENT;
 895                 goto finished;
 896         }
 897 
 898         if (!new_dir || !S_ISDIR(new_dir->i_mode)) {
 899                 printk("smb_rename: new inode is NULL or not a directory\n");
 900                 res = -ENOENT;
 901                 goto finished;
 902         }
 903 
 904         res = get_pname_static(old_dir, old_name, old_len, old_path, &old_len);
 905         if (res < 0) {
 906                 goto finished;
 907         }
 908 
 909         res = get_pname_static(new_dir, new_name, new_len, new_path, &new_len);
 910         if (res < 0) {
 911                 goto finished;
 912         }
 913         
 914         if (   (smb_find_inode(SMB_SERVER(old_dir), old_path) != NULL)
 915             || (smb_find_inode(SMB_SERVER(new_dir), new_path) != NULL)) {
 916                 res = -EBUSY;
 917                 goto finished;
 918         }
 919 
 920         res = smb_proc_mv(SMB_SERVER(old_dir), old_path, old_len,
 921                           new_path, new_len);
 922 
 923         if (res == 0) {
 924                 smb_invalid_dir_cache(old_dir->i_ino);
 925                 smb_invalid_dir_cache(new_dir->i_ino);
 926         }
 927         
 928  finished:
 929         iput(old_dir); 
 930         iput(new_dir);
 931         return res;
 932 }
 933         
 934 /*
 935  * Overrides for Emacs so that we follow Linus's tabbing style.
 936  * Emacs will notice this stuff at the end of the file and automatically
 937  * adjust the settings for this buffer only.  This must remain at the end
 938  * of the file.
 939  * ---------------------------------------------------------------------------
 940  * Local variables:
 941  * c-indent-level: 8
 942  * c-brace-imaginary-offset: 0
 943  * c-brace-offset: -8
 944  * c-argdecl-indent: 8
 945  * c-label-offset: -8
 946  * c-continued-statement-offset: 8
 947  * c-continued-brace-offset: 0
 948  * End:
 949  */

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