create.c 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. #include "logfsos.h"
  2. #include "logfs.h"
  3. #include "local.h"
  4. char *
  5. logfsservercreate(LogfsServer *server, u32int fid, char *name, u32int perm, uchar mode, Qid *qid)
  6. {
  7. Fid *f;
  8. char *uid;
  9. ulong newpath;
  10. char *errmsg;
  11. Entry *e, *xe, *pe;
  12. Path *pp;
  13. LogMessage s;
  14. if(server->trace > 1)
  15. print("logfsservercreate(%ud, %s, 0%uo, %.2ux)\n", fid, name, perm, mode);
  16. f = logfsfidmapfindentry(server->fidmap, fid);
  17. if(f == nil)
  18. return logfsebadfid;
  19. if(f->openmode >= 0)
  20. return logfsefidopen;
  21. pe = f->entry;
  22. if((pe->qid.type & QTDIR) == 0)
  23. return Enotdir;
  24. if((perm & DMDIR) != 0 && ((mode & OTRUNC) != 0 || (mode & 3) != OREAD))
  25. return Eperm;
  26. if(!logfsuserpermcheck(server, pe, f, DMWRITE))
  27. return Eperm;
  28. /*
  29. * illegal names
  30. */
  31. if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
  32. return Eperm;
  33. for(xe = pe->u.dir.list; xe; xe = xe->next)
  34. if(strcmp(xe->name, name) == 0)
  35. return Eexist;
  36. newpath = ++server->path;
  37. while(logfspathmapfindentry(server->pathmap, newpath))
  38. newpath++; /* shouldn't happen */
  39. uid = logfsisfindidfromname(server->is, f->uname);
  40. errmsg = logfsentrynew(server, 1, newpath,
  41. pe, name, uid, f->entry->gid, logfsnow(), uid, perm, 0, 0, &e);
  42. if(errmsg)
  43. return errmsg;
  44. errmsg = logfspathmapnewentry(server->pathmap, newpath, e, &pp);
  45. /* pp is guaranteed to be non-null */
  46. if(errmsg) {
  47. logfsfreemem(e);
  48. return errmsg;
  49. }
  50. s.type = LogfsLogTcreate;
  51. s.path = e->parent->qid.path;
  52. s.u.create.perm = e->perm;
  53. s.u.create.newpath = e->qid.path;
  54. s.u.create.mtime = e->mtime;
  55. /* TODO - check with forsyth whether cvers is needed in dirs */
  56. s.u.create.cvers = (e->qid.type & QTDIR) ? 0 : e->u.file.cvers;
  57. s.u.create.name = e->name;
  58. s.u.create.uid = e->uid;
  59. s.u.create.gid = e->gid;
  60. errmsg = logfslog(server, 1, &s);
  61. if(errmsg) {
  62. logfsfreemem(e);
  63. logfspathmapdeleteentry(server->pathmap, newpath);
  64. return errmsg;
  65. }
  66. server->path = newpath;
  67. e->inuse++;
  68. e->qid.vers++;
  69. e->next = pe->u.dir.list;
  70. pe->u.dir.list = e;
  71. f->openmode = mode;
  72. /*
  73. * TODO why does forsyth increment inuse for dir? - we're moving the fid onto the new file
  74. * so a decrement seems better
  75. */
  76. logfsentryclunk(pe);
  77. f->entry = e;
  78. *qid = e->qid;
  79. return nil;
  80. }