Npfcall* diod_lcreate(Npfid *fid, Npstr *name, u32 flags, u32 mode, u32 gid) { Fid *f = fid->aux; Npfcall *ret = NULL; char *npath = NULL; Npqid qid; int fd = -1; struct stat sb; mode_t saved_umask; int created = 0; u32 iounit = 0; /* client will use msize-P9_IOHDRSZ */ if ((f->xflags & XFLAGS_RO)) { np_uerror (EROFS); goto error_quiet; } if (!(flags & O_CREAT)) /* can't happen? */ flags |= O_CREAT; if (!(npath = _mkpath(f->path, name))) { np_uerror (ENOMEM); goto error; } saved_umask = umask(0); if ((fd = open (npath, flags, mode)) < 0) { np_uerror (errno); goto error_quiet; } created = 1; umask(saved_umask); if (fstat (fd, &sb) < 0) { np_uerror (errno); goto error; /* shouldn't happen? */ } _ustat2qid (&sb, &qid); //iounit = sb.st_blksize; if (!((ret = np_create_rlcreate (&qid, iounit)))) { np_uerror (ENOMEM); goto error; } free (f->path); f->path = npath; f->fd = fd; return ret; error: errn (np_rerror (), "diod_lcreate %s@%s:%s/%.*s", fid->user->uname, np_conn_get_client_id (fid->conn), f->path, name->len, name->str); error_quiet: if (fd >= 0) { (void)close (fd); } if (created && npath) (void)unlink (npath); if (npath) free (npath); if (ret) free (ret); return NULL; }
Npfcall* diod_lcreate(Npfid *fid, Npstr *name, u32 flags, u32 mode, u32 gid) { Npsrv *srv = fid->conn->srv; Fid *f = fid->aux; Npfcall *ret; Path opath = NULL; if ((f->flags & DIOD_FID_FLAGS_ROFS)) { np_uerror (EROFS); goto error_quiet; } flags = _remap_oflags (flags); if (flags & O_DIRECT) { np_uerror (EINVAL); /* O_DIRECT not allowed - see issue 110 */ goto error_quiet; } if (!(flags & O_CREAT)) /* can't happen? */ flags |= O_CREAT; if (f->ioctx != NULL) { msg ("diod_lcreate: fid is already open"); np_uerror (EINVAL); goto error; } opath = f->path; if (!(f->path = path_append (srv, opath, name))) { np_uerror (ENOMEM); goto error; } if (ioctx_open (fid, flags, mode) < 0) { if (np_rerror () == ENOMEM) goto error; goto error_quiet; } if (!((ret = np_create_rlcreate (ioctx_qid (f->ioctx), ioctx_iounit (f->ioctx))))) { (void)ioctx_close (fid, 0); (void)unlink (path_s (f->path)); np_uerror (ENOMEM); goto error; } path_decref (srv, opath); return ret; error: errn (np_rerror (), "diod_lcreate %s@%s:%s/%.*s", fid->user->uname, np_conn_get_client_id (fid->conn), opath ? path_s (opath) : path_s (f->path), name->len, name->str); error_quiet: if (opath) { if (f->path) path_decref (srv, f->path); f->path = opath; } return NULL; }
static void test_rlcreate (void) { Npfcall *fc, *fc2; struct p9_qid qid = { 1, 2, 3 }; if (!(fc = np_create_rlcreate (&qid, 2))) msg_exit ("out of memory"); fc2 = _rcv_buf (fc, P9_RLCREATE, __FUNCTION__); assert (fc->u.rlcreate.qid.type == fc2->u.rlcreate.qid.type); assert (fc->u.rlcreate.qid.version == fc2->u.rlcreate.qid.version); assert (fc->u.rlcreate.qid.path == fc2->u.rlcreate.qid.path); assert (fc->u.rlcreate.iounit == fc2->u.rlcreate.iounit); free (fc); free (fc2); }