root/fs/ncpfs/dir.c

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

DEFINITIONS

This source file includes following definitions.
  1. str_upper
  2. str_lower
  3. ncp_dir_read
  4. ncp_readdir
  5. ncp_read_volume_list
  6. ncp_do_readdir
  7. ncp_init_dir_cache
  8. ncp_invalid_dir_cache
  9. ncp_free_dir_cache
  10. ncp_iget
  11. ncp_free_inode_info
  12. ncp_init_root
  13. ncp_free_all_inodes
  14. ncp_find_inode
  15. ncp_lookup
  16. ncp_create
  17. ncp_mkdir
  18. ncp_rmdir
  19. ncp_unlink
  20. ncp_rename
  21. utc2local
  22. local2utc
  23. ncp_date_dos2unix
  24. ncp_date_unix2dos

   1 /*
   2  *  dir.c
   3  *
   4  *  Copyright (C) 1995 by Volker Lendecke
   5  *
   6  */
   7 
   8 #include <linux/sched.h>
   9 #include <linux/errno.h>
  10 #include <linux/stat.h>
  11 #include <linux/kernel.h>
  12 #include <linux/malloc.h>
  13 #include <linux/mm.h>
  14 #include <linux/ncp_fs.h>
  15 #include <asm/segment.h>
  16 #include <linux/errno.h>
  17 #include "ncplib_kernel.h"
  18 
  19 struct ncp_dirent {
  20         struct nw_info_struct i;
  21         struct nw_search_sequence s; /* given back for i */
  22         unsigned long f_pos;
  23 };
  24 
  25 static int 
  26 ncp_dir_read(struct inode *inode, struct file *filp, char *buf, int count);
  27 
  28 static int 
  29 ncp_readdir(struct inode *inode, struct file *filp,
  30             void *dirent, filldir_t filldir);
  31 
  32 static int
  33 ncp_read_volume_list(struct ncp_server *server, int start_with,
  34                      int cache_size);
  35 
  36 static int
  37 ncp_do_readdir(struct ncp_server *server, struct inode *dir, int fpos,
  38                int cache_size, struct ncp_dirent *entry);
  39 
  40 static struct inode *
  41 ncp_iget(struct inode *dir, struct nw_file_info *finfo);
  42 
  43 static struct ncp_inode_info *
  44 ncp_find_inode(struct inode *dir, const char *name);
  45 
  46 static int
  47 ncp_lookup(struct inode *dir, const char *__name,
  48            int len, struct inode **result);
  49 
  50 static int 
  51 ncp_create(struct inode *dir, const char *name, int len, int mode, 
  52            struct inode **result);
  53 
  54 static int 
  55 ncp_mkdir(struct inode *dir, const char *name, int len, int mode);
  56 
  57 static int 
  58 ncp_rmdir(struct inode *dir, const char *name, int len);
  59 
  60 static int
  61 ncp_unlink(struct inode *dir, const char *name, int len);
  62 
  63 static int
  64 ncp_rename(struct inode *old_dir, const char *old_name, int old_len, 
  65            struct inode *new_dir, const char *new_name, int new_len);
  66 
  67 static inline void
  68 str_upper(char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
  69 {
  70         while (*name)
  71         {
  72                 if (*name >= 'a' && *name <= 'z')
  73                 {
  74                         *name -= ('a' - 'A');
  75                 }
  76                 name++;
  77         }
  78 }
  79 
  80 static inline void
  81 str_lower(char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
  82 {
  83         while (*name)
  84         {
  85                 if (*name >= 'A' && *name <= 'Z')
  86                 {
  87                         *name += ('a' - 'A');
  88                 }
  89                 name ++;
  90         }
  91 }
  92 
  93 static struct file_operations ncp_dir_operations = {
  94         NULL,                   /* lseek - default */
  95         ncp_dir_read,           /* read - bad */
  96         NULL,                   /* write - bad */
  97         ncp_readdir,            /* readdir */
  98         NULL,                   /* select - default */
  99         ncp_ioctl,              /* ioctl */
 100         NULL,                   /* mmap */
 101         NULL,                   /* no special open code */
 102         NULL,                   /* no special release code */
 103         NULL                    /* fsync */
 104 };
 105 
 106 struct inode_operations ncp_dir_inode_operations = {
 107         &ncp_dir_operations,    /* default directory file ops */
 108         ncp_create,             /* create */
 109         ncp_lookup,             /* lookup */
 110         NULL,                   /* link */
 111         ncp_unlink,             /* unlink */
 112         NULL,                   /* symlink */
 113         ncp_mkdir,              /* mkdir */
 114         ncp_rmdir,              /* rmdir */
 115         NULL,                   /* mknod */
 116         ncp_rename,             /* rename */
 117         NULL,                   /* readlink */
 118         NULL,                   /* follow_link */
 119         NULL,                   /* bmap */
 120         NULL,                   /* truncate */
 121         NULL,                   /* permission */
 122         NULL                    /* smap */
 123 };
 124 
 125 
 126 static int 
 127 ncp_dir_read(struct inode *inode, struct file *filp, char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 128 {
 129         return -EISDIR;
 130 }
 131 
 132 /* In ncpfs, we have unique inodes across all mounted filesystems, for
 133    all inodes that are in memory. That's why it's enough to index the
 134    directory cache by the inode number. */
 135 
 136 static unsigned long      c_ino = 0;
 137 static int                c_size;
 138 static int                c_seen_eof;
 139 static int                c_last_returned_index;
 140 static struct ncp_dirent* c_entry = NULL;
 141 
 142 static int
 143 ncp_readdir(struct inode *inode, struct file *filp,
     /* [previous][next][first][last][top][bottom][index][help] */
 144             void *dirent, filldir_t filldir)
 145 {
 146         int result, i = 0;
 147         int index = 0;
 148         struct ncp_dirent *entry = NULL;
 149         struct ncp_server *server = NCP_SERVER(inode);
 150         struct ncp_inode_info *dir = (struct ncp_inode_info *)(inode->i_ino);
 151 
 152         DDPRINTK("ncp_readdir: filp->f_pos = %d\n", (int)filp->f_pos);
 153         DDPRINTK("ncp_readdir: inode->i_ino = %ld, c_ino = %ld\n",
 154                  inode->i_ino, c_ino);
 155 
 156         if (!inode || !S_ISDIR(inode->i_mode))
 157         {
 158                 printk("ncp_readdir: inode is NULL or not a directory\n");
 159                 return -EBADF;
 160         }
 161 
 162         if (!ncp_conn_valid(NCP_SERVER(inode)))
 163         {
 164                 return -EIO;
 165         }
 166 
 167         if (c_entry == NULL) 
 168         {
 169                 i = sizeof (struct ncp_dirent) * NCP_READDIR_CACHE_SIZE;
 170                 c_entry = (struct ncp_dirent *) ncp_kmalloc(i, GFP_KERNEL);
 171                 if (c_entry == NULL)
 172                 {
 173                         printk("ncp_readdir: no MEMORY for cache\n");
 174                         return -ENOMEM;
 175                 }
 176         }
 177 
 178         if (filp->f_pos == 0)
 179         {
 180                 ncp_invalid_dir_cache(inode->i_ino);
 181                 if (filldir(dirent,".",1, filp->f_pos, (int)dir) < 0)
 182                 {
 183                         return 0;
 184                 }
 185                 filp->f_pos += 1;
 186         }
 187 
 188         if (filp->f_pos == 1)
 189         {
 190                 if (filldir(dirent,"..",2, filp->f_pos, (int)(dir->dir)) < 0)
 191                 {
 192                         return 0;
 193                 }
 194                 filp->f_pos += 1;
 195         }
 196 
 197         if (inode->i_ino == c_ino)
 198         {
 199                 for (i = 0; i < c_size; i++)
 200                 {
 201                         if (filp->f_pos == c_entry[i].f_pos)
 202                         {
 203                                 entry = &c_entry[i];
 204                                 c_last_returned_index = i;
 205                                 index = i;
 206                                 break;
 207                         }
 208                 }
 209                 if ((entry == NULL) && c_seen_eof)
 210                 {
 211                         return 0;
 212                 }
 213         }
 214 
 215         if (entry == NULL)
 216         {
 217                 DDPRINTK("ncp_readdir: Not found in cache.\n");
 218 
 219                 if (inode->i_ino == (int)&(server->root))
 220                 {
 221                         result = ncp_read_volume_list(server, filp->f_pos,
 222                                                       NCP_READDIR_CACHE_SIZE);
 223                         DPRINTK("ncp_read_volume_list returned %d\n", result);
 224 
 225                 }
 226                 else
 227                 {
 228                         result = ncp_do_readdir(server, inode, filp->f_pos,
 229                                                 NCP_READDIR_CACHE_SIZE,
 230                                                 c_entry);
 231                         DPRINTK("ncp_readdir returned %d\n", result);
 232                 }
 233 
 234                 if (result < 0)
 235                 {
 236                         c_ino = 0;
 237                         return result;
 238                 }
 239 
 240                 if (result > 0)
 241                 {
 242                         c_seen_eof = (result < NCP_READDIR_CACHE_SIZE);
 243                         c_ino  = inode->i_ino;
 244                         c_size = result;
 245                         entry = c_entry;
 246                         c_last_returned_index = 0;
 247                         index = 0;
 248 
 249                         for (i = 0; i < c_size; i++)
 250                         {
 251                                 str_lower(c_entry[i].i.entryName);
 252                         }
 253                 }
 254         }
 255 
 256         if (entry == NULL)
 257         {
 258                 /* Nothing found, even from a ncp call */
 259                 return 0;
 260         }
 261 
 262         while (index < c_size)
 263         {
 264                 /* We found it.  For getwd(), we have to return the
 265                    correct inode in d_ino if the inode is currently in
 266                    use. Otherwise the inode number does not
 267                    matter. (You can argue a lot about this..) */ 
 268 
 269                 struct ncp_inode_info *ino_info;
 270                 ino_info = ncp_find_inode(inode, entry->i.entryName);
 271 
 272                 /* Some programs seem to be confused about a zero
 273                    inode number, so we set it to one.  Thanks to
 274                    Gordon Chaffee for this one. */
 275                 if (ino_info == NULL)
 276                 {
 277                         ino_info = (struct ncp_inode_info *) 1;
 278                 }
 279 
 280                 DDPRINTK("ncp_readdir: entry->path= %s\n", entry->i.entryName);
 281                 DDPRINTK("ncp_readdir: entry->f_pos = %ld\n", entry->f_pos);
 282 
 283                 if (filldir(dirent, entry->i.entryName, entry->i.nameLen,
 284                             entry->f_pos, (ino_t)ino_info) < 0)
 285                 {
 286                         break;
 287                 }
 288 
 289                 if (   (inode->i_ino != c_ino)
 290                     || (entry->f_pos != filp->f_pos))
 291                 {
 292                         /* Someone has destroyed the cache while we slept
 293                            in filldir */
 294                         break;
 295                 }
 296                 filp->f_pos += 1;
 297                 index += 1;
 298                 entry += 1;
 299         }
 300         return 0;
 301 }
 302 
 303 static int
 304 ncp_read_volume_list(struct ncp_server *server, int fpos, int cache_size)
     /* [previous][next][first][last][top][bottom][index][help] */
 305 {
 306         struct ncp_dirent *entry = c_entry;
 307 
 308         int total_count = 2;
 309         int i;
 310 
 311 #if 1
 312         if (fpos < 2)
 313         {
 314                 printk("OOPS, we expect fpos >= 2");
 315                 fpos = 2;
 316         }
 317 #endif
 318 
 319         for (i=0; i<NCP_NUMBER_OF_VOLUMES; i++)
 320         {
 321                 struct ncp_volume_info info;
 322 
 323                 if (ncp_get_volume_info_with_number(server, i, &info) != 0)
 324                 {
 325                         return total_count;
 326                 }
 327 
 328                 if (strlen(info.volume_name) > 0)
 329                 {
 330                         if (total_count < fpos)
 331                         {
 332                                 DPRINTK("ncp_read_volumes: skipped vol: %s\n",
 333                                         info.volume_name);
 334                         }
 335                         else if (total_count >= fpos + cache_size)
 336                         {
 337                                 return (total_count - fpos);
 338                         }
 339                         else
 340                         {
 341                                 DPRINTK("ncp_read_volumes: found vol: %s\n",
 342                                         info.volume_name);
 343 
 344                                 if (ncp_do_lookup(server, NULL,
 345                                                   info.volume_name,
 346                                                   &(entry->i)) != 0)
 347                                 {
 348                                         printk("ncpfs: could not lookup vol "
 349                                                "%s\n", info.volume_name);
 350                                         continue;
 351                                 }
 352 
 353                                 entry->f_pos = total_count;
 354                                 entry += 1;
 355                         }
 356                         total_count += 1;
 357                 }
 358         }
 359         return (total_count - fpos);
 360 }
 361 
 362 static int
 363 ncp_do_readdir(struct ncp_server *server, struct inode *dir, int fpos,
     /* [previous][next][first][last][top][bottom][index][help] */
 364                int cache_size, struct ncp_dirent *entry)
 365 {
 366         static struct nw_search_sequence seq;
 367         static struct inode *last_dir;
 368         static int total_count;
 369 
 370 #if 1
 371         if (fpos < 2)
 372         {
 373                 printk("OOPS, we expect fpos >= 2");
 374                 fpos = 2;
 375         }
 376 #endif
 377         DPRINTK("ncp_do_readdir: fpos = %d\n", fpos);
 378 
 379         if (fpos == 2)
 380         {
 381                 last_dir = NULL;
 382                 total_count = 2;
 383         }
 384 
 385         if ((fpos != total_count) || (dir != last_dir))
 386         {
 387                 total_count = 2;
 388                 last_dir = dir;
 389 
 390                 DPRINTK("ncp_do_readdir: re-used seq for %s\n",
 391                         NCP_ISTRUCT(dir)->entryName);
 392 
 393                 if (ncp_initialize_search(server, NCP_ISTRUCT(dir), &seq)!=0)
 394                 {
 395                         DPRINTK("ncp_init_search failed\n");
 396                         return total_count - fpos;
 397                 }
 398         }
 399 
 400         while (total_count < fpos + cache_size)
 401         {
 402                 if (ncp_search_for_file_or_subdir(server, &seq,
 403                                                   &(entry->i)) != 0)
 404                 {
 405                         return total_count - fpos;
 406                 }
 407 
 408                 if (total_count < fpos)
 409                 {
 410                         DPRINTK("ncp_do_readdir: skipped file: %s\n",
 411                                 entry->i.entryName);
 412                 }
 413                 else
 414                 {
 415                         DDPRINTK("ncp_do_r: file: %s, f_pos=%d,total_count=%d",
 416                                  entry->i.entryName, fpos, total_count);
 417                         entry->s = seq;
 418                         entry->f_pos = total_count;
 419                         entry += 1;
 420                 }
 421                 total_count += 1;
 422         }
 423         return (total_count - fpos);
 424 }
 425 
 426 void
 427 ncp_init_dir_cache(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 428 {
 429         c_ino   = 0;
 430         c_entry = NULL;
 431 }
 432 
 433 void
 434 ncp_invalid_dir_cache(unsigned long ino)
     /* [previous][next][first][last][top][bottom][index][help] */
 435 {
 436         if (ino == c_ino)
 437         {
 438                 c_ino = 0;
 439                 c_seen_eof = 0;
 440         }
 441 }
 442 
 443 void
 444 ncp_free_dir_cache(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 445 {
 446         DPRINTK("ncp_free_dir_cache: enter\n");
 447         
 448         if (c_entry == NULL)
 449         {
 450                 return;
 451         }
 452 
 453         ncp_kfree_s(c_entry,
 454                     sizeof(struct ncp_dirent) * NCP_READDIR_CACHE_SIZE);
 455         c_entry = NULL;
 456 
 457         DPRINTK("ncp_free_dir_cache: exit\n");
 458 }
 459 
 460 
 461 static struct inode *
 462 ncp_iget(struct inode *dir, struct nw_file_info *finfo)
     /* [previous][next][first][last][top][bottom][index][help] */
 463 {
 464         struct inode *inode;
 465         struct ncp_inode_info *new_inode_info;
 466         struct ncp_inode_info *root;
 467 
 468         if (dir == NULL)
 469         {
 470                 printk("ncp_iget: dir is NULL\n");
 471                 return NULL;
 472         }
 473 
 474         if (finfo == NULL)
 475         {
 476                 printk("ncp_iget: finfo is NULL\n");
 477                 return NULL;
 478         }
 479 
 480         new_inode_info = ncp_kmalloc(sizeof(struct ncp_inode_info),
 481                                      GFP_KERNEL);
 482 
 483         if (new_inode_info == NULL)
 484         {
 485                 printk("ncp_iget: could not alloc mem for %s\n",
 486                        finfo->i.entryName);
 487                 return NULL;
 488         }
 489 
 490         new_inode_info->state = NCP_INODE_LOOKED_UP;
 491         new_inode_info->nused = 0;
 492         new_inode_info->dir   = NCP_INOP(dir);
 493         new_inode_info->finfo = *finfo;
 494 
 495         NCP_INOP(dir)->nused += 1;
 496 
 497         /* We have to link the new inode_info into the doubly linked
 498            list of inode_infos to make a complete linear search
 499            possible. */
 500 
 501         root = &(NCP_SERVER(dir)->root);
 502 
 503         new_inode_info->prev = root;
 504         new_inode_info->next = root->next;
 505         root->next->prev = new_inode_info;
 506         root->next = new_inode_info;
 507         
 508         if (!(inode = iget(dir->i_sb, (int)new_inode_info)))
 509         {
 510                 printk("ncp_iget: iget failed!");
 511                 return NULL;
 512         }
 513 
 514         return inode;
 515 }
 516 
 517 void
 518 ncp_free_inode_info(struct ncp_inode_info *i)
     /* [previous][next][first][last][top][bottom][index][help] */
 519 {
 520         if (i == NULL)
 521         {
 522                 printk("ncp_free_inode: i == NULL\n");
 523                 return;
 524         }
 525 
 526         i->state = NCP_INODE_CACHED;
 527         while ((i->nused == 0) && (i->state == NCP_INODE_CACHED))
 528         {
 529                 struct ncp_inode_info *dir = i->dir;
 530 
 531                 i->next->prev = i->prev;
 532                 i->prev->next = i->next;
 533 
 534                 DDPRINTK("ncp_free_inode_info: freeing %s\n",
 535                          i->finfo.i.entryName);
 536 
 537                 ncp_kfree_s(i, sizeof(struct ncp_inode_info));
 538 
 539                 if (dir == i) return;
 540 
 541                 (dir->nused)--;
 542                 i = dir;
 543         }
 544 }
 545         
 546 void
 547 ncp_init_root(struct ncp_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
 548 {
 549         struct ncp_inode_info *root = &(server->root);
 550         struct nw_info_struct *i = &(root->finfo.i);
 551         unsigned short dummy;
 552 
 553         DPRINTK("ncp_init_root: server %s\n", server->m.server_name);
 554         DPRINTK("ncp_init_root: i = %x\n", (int)i);
 555 
 556         root->finfo.opened = 0;
 557         i->attributes  = aDIR;
 558         i->dataStreamSize = 1024;
 559         i->volNumber = NCP_NUMBER_OF_VOLUMES+1; /* illegal volnum */
 560         ncp_date_unix2dos(0, &(i->creationTime), &(i->creationDate));
 561         ncp_date_unix2dos(0, &(i->modifyTime), &(i->modifyDate));
 562         ncp_date_unix2dos(0, &dummy, &(i->lastAccessDate));
 563         i->nameLen = 0;
 564         i->entryName[0] = '\0';
 565 
 566         root->state = NCP_INODE_LOOKED_UP;
 567         root->nused = 1;
 568         root->dir   = root;
 569         root->next = root->prev = root;
 570         return;
 571 }
 572 
 573 void
 574 ncp_free_all_inodes(struct ncp_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
 575 {
 576         /* Here nothing should be to do. I do not know whether it's
 577            better to leave some memory allocated or be stuck in an
 578            endless loop */
 579 #if 1
 580         struct ncp_inode_info *root = &(server->root);
 581 
 582         if (root->next != root)
 583         {
 584                 printk("ncp_free_all_inodes: INODES LEFT!!!\n");
 585         }
 586 
 587         while (root->next != root)
 588         {
 589                 printk("ncp_free_all_inodes: freeing inode\n");
 590                 ncp_free_inode_info(root->next);
 591                 /* In case we have an endless loop.. */
 592                 schedule();
 593         }
 594 #endif        
 595         
 596         return;
 597 }
 598 
 599 /* We will search the inode that belongs to this name, currently by a
 600    complete linear search through the inodes belonging to this
 601    filesystem. This has to be fixed. */
 602 static struct ncp_inode_info *
 603 ncp_find_inode(struct inode *dir, const char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 604 {
 605         struct ncp_server *server = NCP_SERVER(dir);
 606         struct nw_info_struct *dir_info = NCP_ISTRUCT(dir);
 607         struct ncp_inode_info *result = &(server->root);
 608 
 609         if (name == NULL)
 610         {
 611                 return NULL;
 612         }
 613 
 614         do
 615         {
 616                 if (   (result->dir->finfo.i.DosDirNum == dir_info->DosDirNum)
 617                     && (result->dir->finfo.i.volNumber == dir_info->volNumber)
 618                     && (strcmp(result->finfo.i.entryName, name) == 0))
 619                 {
 620                         return result;
 621                 }
 622                 result = result->next;
 623 
 624         }
 625         while (result != &(server->root));
 626 
 627         return NULL;
 628 }
 629 
 630 static int 
 631 ncp_lookup(struct inode *dir, const char *__name, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 632            struct inode **result)
 633 {
 634         struct nw_file_info finfo;
 635         struct ncp_server *server;
 636         struct ncp_inode_info *result_info;
 637         int found_in_cache;
 638         char name[len+1];
 639 
 640         *result = NULL;
 641 
 642         if (!dir || !S_ISDIR(dir->i_mode))
 643         {
 644                 printk("ncp_lookup: inode is NULL or not a directory.\n");
 645                 iput(dir);
 646                 return -ENOENT;
 647         }
 648         if (!ncp_conn_valid(NCP_SERVER(dir)))
 649         {
 650                 iput(dir);
 651                 return -EIO;
 652         }
 653 
 654         DDPRINTK("ncp_lookup: %s, len %d\n", __name, len);
 655 
 656         server = NCP_SERVER(dir);
 657 
 658         /* Fast cheat for . */
 659         if (len == 0 || (len == 1 && __name[0] == '.'))
 660         {
 661                 *result = dir;
 662                 return 0;
 663         }
 664 
 665         /* ..and for .. */
 666         if (len == 2 && __name[0] == '.' && __name[1] == '.')
 667         {
 668                 struct ncp_inode_info *parent = NCP_INOP(dir)->dir;
 669 
 670                 if (parent->state == NCP_INODE_CACHED)
 671                 {
 672                         parent->state = NCP_INODE_LOOKED_UP;
 673                 }
 674 
 675                 *result = iget(dir->i_sb, (int)parent);
 676                 iput(dir);
 677                 if (*result == 0)
 678                 {
 679                         return -EACCES;
 680                 }
 681                 else
 682                 {
 683                         return 0;
 684                 }
 685         }
 686 
 687         memcpy(name, __name, len);
 688         name[len] = 0;
 689         result_info = ncp_find_inode(dir, name);
 690 
 691         if (result_info != 0)
 692         {
 693                 if (result_info->state == NCP_INODE_CACHED)
 694                 {
 695                         result_info->state = NCP_INODE_LOOKED_UP;
 696                 }
 697 
 698                 /* Here we convert the inode_info address into an
 699                    inode number */
 700 
 701                 *result = iget(dir->i_sb, (int)result_info);
 702                 iput(dir);
 703 
 704                 if (*result == NULL)
 705                 {
 706                         return -EACCES;
 707                 }
 708 
 709                 return 0;
 710         }
 711 
 712         /* If the file is in the dir cache, we do not have to ask the
 713            server. */
 714 
 715         found_in_cache = 0;
 716         
 717         if (dir->i_ino == c_ino)
 718         {
 719                 int first = c_last_returned_index;
 720                 int i;
 721 
 722                 i = first;
 723                 do
 724                 {
 725                         DDPRINTK("ncp_lookup: trying index: %d, name: %s\n",
 726                                 i, c_entry[i].i.entryName);
 727 
 728                         if (strcmp(c_entry[i].i.entryName, name) == 0)
 729                         {
 730                                 DPRINTK("ncp_lookup: found in cache!\n");
 731                                 finfo.i = c_entry[i].i;
 732                                 found_in_cache = 1;
 733                                 break;
 734                         }
 735                         i = (i + 1) % c_size;
 736                 }
 737                 while (i != first);
 738         }
 739 
 740         if (found_in_cache == 0)
 741         {
 742                 str_upper(name);
 743 
 744                 DDPRINTK("ncp_lookup: do_lookup on %s/%s\n",
 745                          NCP_ISTRUCT(dir)->entryName, name);
 746 
 747                 if (ncp_do_lookup(server,
 748                                   dir->i_ino == (int)&(NCP_SERVER(dir)->root)
 749                                   ? NULL : NCP_ISTRUCT(dir),
 750                                   name, &(finfo.i)) != 0)
 751                 {
 752                         iput(dir);
 753                         return -ENOENT;
 754                 }
 755         }
 756 
 757         finfo.opened = 0;
 758         str_lower(finfo.i.entryName);
 759 
 760         if (!(*result = ncp_iget(dir, &finfo)))
 761         {
 762                 iput(dir);
 763                 return -EACCES;
 764         }
 765 
 766         iput(dir);
 767         return 0;
 768 }
 769 
 770 static int 
 771 ncp_create(struct inode *dir, const char *name, int len, int mode,
     /* [previous][next][first][last][top][bottom][index][help] */
 772            struct inode **result)
 773 {
 774         struct nw_file_info finfo;
 775         __u8 _name[len+1];
 776 
 777         *result = NULL;
 778 
 779         if (!dir || !S_ISDIR(dir->i_mode))
 780         {
 781                 printk("ncp_create: inode is NULL or not a directory\n");
 782                 iput(dir);
 783                 return -ENOENT;
 784         }
 785         if (!ncp_conn_valid(NCP_SERVER(dir)))
 786         {
 787                 iput(dir);
 788                 return -EIO;
 789         }
 790 
 791         strncpy(_name, name, len);
 792         _name[len] = '\0';
 793         str_upper(_name);
 794 
 795         if (ncp_open_create_file_or_subdir(NCP_SERVER(dir),
 796                                            NCP_ISTRUCT(dir), _name,
 797                                            OC_MODE_CREATE|OC_MODE_OPEN|
 798                                            OC_MODE_REPLACE,
 799                                            0, AR_READ|AR_WRITE,
 800                                            &finfo) != 0)
 801         {
 802                 iput(dir);
 803                 return -EACCES;
 804         }
 805 
 806         ncp_invalid_dir_cache(dir->i_ino);
 807 
 808         str_lower(finfo.i.entryName);
 809         finfo.access = O_RDWR;
 810 
 811         if (!(*result = ncp_iget(dir, &finfo)) < 0)
 812         {
 813                 ncp_close_file(NCP_SERVER(dir), finfo.file_handle);
 814                 iput(dir);
 815                 return -EINVAL;
 816         }
 817 
 818         iput(dir);
 819         return 0;       
 820 }
 821 
 822 static int
 823 ncp_mkdir(struct inode *dir, const char *name, int len, int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 824 {
 825         int error;
 826         struct nw_file_info new_dir;
 827         __u8 _name[len+1];
 828 
 829         if (   (name[0] == '.')
 830             && (   (len == 1)
 831                 || (   (len == 2)
 832                     && (name[1] == '.'))))
 833         {
 834                 return -EEXIST;
 835         }
 836 
 837         strncpy(_name, name, len);
 838         _name[len] = '\0';
 839         str_upper(_name);
 840 
 841         if (!dir || !S_ISDIR(dir->i_mode))
 842         {
 843                 printk("ncp_mkdir: inode is NULL or not a directory\n");
 844                 iput(dir);
 845                 return -ENOENT;
 846         }
 847         if (!ncp_conn_valid(NCP_SERVER(dir)))
 848         {
 849                 iput(dir);
 850                 return -EIO;
 851         }
 852 
 853         if (ncp_open_create_file_or_subdir(NCP_SERVER(dir),
 854                                            NCP_ISTRUCT(dir), _name,
 855                                            OC_MODE_CREATE, aDIR, 0xffff,
 856                                            &new_dir) != 0)
 857         {
 858                 error = -EACCES;
 859         }
 860         else
 861         {
 862                 error = 0;
 863                 ncp_invalid_dir_cache(dir->i_ino);
 864         }
 865 
 866         iput(dir);
 867         return error;
 868 }
 869 
 870 static int
 871 ncp_rmdir(struct inode *dir, const char *name, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 872 {
 873         int error;
 874         __u8 _name[len+1];
 875 
 876         if (!dir || !S_ISDIR(dir->i_mode))
 877         {
 878                 printk("ncp_rmdir: inode is NULL or not a directory\n");
 879                 iput(dir);
 880                 return -ENOENT;
 881         }
 882         if (!ncp_conn_valid(NCP_SERVER(dir)))
 883         {
 884                 iput(dir);
 885                 return -EIO;
 886         }
 887         if (ncp_find_inode(dir, name) != NULL)
 888         {
 889                 iput(dir);
 890                 error = -EBUSY;
 891         }
 892         else
 893         {
 894 
 895                 strncpy(_name, name, len);
 896                 _name[len] = '\0';
 897                 str_upper(_name);
 898 
 899                 if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir),
 900                                                     NCP_ISTRUCT(dir),
 901                                                     _name)) == 0)
 902                 {
 903                         ncp_invalid_dir_cache(dir->i_ino);
 904                 }
 905                 else
 906                 {
 907                         error = -EACCES;
 908                 }
 909         }
 910         iput(dir);
 911         return error;
 912 }
 913 
 914 static int
 915 ncp_unlink(struct inode *dir, const char *name, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 916 {
 917         int error;
 918         __u8 _name[len+1];
 919 
 920         if (!dir || !S_ISDIR(dir->i_mode))
 921         {
 922                 printk("ncp_unlink: inode is NULL or not a directory\n");
 923                 iput(dir);
 924                 return -ENOENT;
 925         }
 926         if (!ncp_conn_valid(NCP_SERVER(dir)))
 927         {
 928                 iput(dir);
 929                 return -EIO;
 930         }
 931         if (ncp_find_inode(dir, name) != NULL)
 932         {
 933                 iput(dir);
 934                 error = -EBUSY;
 935         }
 936         else
 937         {
 938                 strncpy(_name, name, len);
 939                 _name[len] = '\0';
 940                 str_upper(_name);
 941 
 942                 if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir),
 943                                                     NCP_ISTRUCT(dir),
 944                                                     _name)) == 0)
 945                 {
 946                         ncp_invalid_dir_cache(dir->i_ino);
 947                 }
 948                 else
 949                 {
 950                         error = -EACCES;
 951                 }
 952         }
 953         iput(dir);
 954         return error;
 955 }
 956 
 957 static int
 958 ncp_rename(struct inode *old_dir, const char *old_name, int old_len,
     /* [previous][next][first][last][top][bottom][index][help] */
 959            struct inode *new_dir, const char *new_name, int new_len)
 960 {
 961         int res;
 962         char _old_name[old_len+1];
 963         char _new_name[new_len+1];
 964 
 965         if (!old_dir || !S_ISDIR(old_dir->i_mode))
 966         {
 967                 printk("ncp_rename: old inode is NULL or not a directory\n");
 968                 res = -ENOENT;
 969                 goto finished;
 970         }
 971 
 972         if (!ncp_conn_valid(NCP_SERVER(old_dir)))
 973         {
 974                 res = -EIO;
 975                 goto finished;
 976         }
 977 
 978         if (!new_dir || !S_ISDIR(new_dir->i_mode))
 979         {
 980                 printk("ncp_rename: new inode is NULL or not a directory\n");
 981                 res = -ENOENT;
 982                 goto finished;
 983         }
 984 
 985         if (   (ncp_find_inode(old_dir, old_name) != NULL)
 986             || (ncp_find_inode(new_dir, new_name) != NULL))
 987         {
 988                 res = -EBUSY;
 989                 goto finished;
 990         }
 991 
 992         strncpy(_old_name, old_name, old_len);
 993         _old_name[old_len] = '\0';
 994         str_upper(_old_name);
 995 
 996         strncpy(_new_name, new_name, new_len);
 997         _new_name[new_len] = '\0';
 998         str_upper(_new_name);
 999 
1000         res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
1001                                             NCP_ISTRUCT(old_dir), _old_name,
1002                                             NCP_ISTRUCT(new_dir), _new_name);
1003 
1004         if (res == 0)
1005         {
1006                 ncp_invalid_dir_cache(old_dir->i_ino);
1007                 ncp_invalid_dir_cache(new_dir->i_ino);
1008         }
1009         else
1010         {
1011                 res = -EACCES;
1012         }
1013         
1014  finished:
1015         iput(old_dir); 
1016         iput(new_dir);
1017         return res;
1018 }
1019 
1020 /* The following routines are taken directly from msdos-fs */
1021 
1022 /* Linear day numbers of the respective 1sts in non-leap years. */
1023 
1024 static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 };
1025                   /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */
1026 
1027 
1028 extern struct timezone sys_tz;
1029 
1030 static int
1031 utc2local(int time)
     /* [previous][next][first][last][top][bottom][index][help] */
1032 {
1033         return time - sys_tz.tz_minuteswest*60;
1034 }
1035 
1036 static int
1037 local2utc(int time)
     /* [previous][next][first][last][top][bottom][index][help] */
1038 {
1039         return time + sys_tz.tz_minuteswest*60;
1040 }
1041 
1042 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
1043 
1044 int
1045 ncp_date_dos2unix(unsigned short time,unsigned short date)
     /* [previous][next][first][last][top][bottom][index][help] */
1046 {
1047         int month,year,secs;
1048 
1049         month = ((date >> 5) & 15)-1;
1050         year = date >> 9;
1051         secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400*
1052             ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
1053             month < 2 ? 1 : 0)+3653);
1054                         /* days since 1.1.70 plus 80's leap day */
1055         return local2utc(secs);
1056 }
1057 
1058 
1059 /* Convert linear UNIX date to a MS-DOS time/date pair. */
1060 void
1061 ncp_date_unix2dos(int unix_date,unsigned short *time, unsigned short *date)
     /* [previous][next][first][last][top][bottom][index][help] */
1062 {
1063         int day,year,nl_day,month;
1064 
1065         unix_date = utc2local(unix_date);
1066         *time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+
1067             (((unix_date/3600) % 24) << 11);
1068         day = unix_date/86400-3652;
1069         year = day/365;
1070         if ((year+3)/4+365*year > day) year--;
1071         day -= (year+3)/4+365*year;
1072         if (day == 59 && !(year & 3)) {
1073                 nl_day = day;
1074                 month = 2;
1075         }
1076         else {
1077                 nl_day = (year & 3) || day <= 59 ? day : day-1;
1078                 for (month = 0; month < 12; month++)
1079                         if (day_n[month] > nl_day) break;
1080         }
1081         *date = nl_day-day_n[month-1]+1+(month << 5)+(year << 9);
1082 }

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