Npfcall* diod_symlink(Npfid *fid, Npstr *name, Npstr *symtgt, u32 gid) { Fid *f = fid->aux; Npfcall *ret = NULL; char *target = NULL, *npath = NULL; Npqid qid; struct stat sb; mode_t saved_umask; int created = 0; if ((f->xflags & XFLAGS_RO)) { np_uerror (EROFS); goto error_quiet; } if (!(npath = _mkpath(f->path, name))) { np_uerror (ENOMEM); goto error; } if (!(target = np_strdup (symtgt))) { np_uerror (ENOMEM); goto error; } saved_umask = umask(0); if (symlink (target, npath) < 0) { np_uerror (errno); goto error_quiet; } created = 1; umask(saved_umask); if (lstat (npath, &sb) < 0) { np_uerror (errno); goto error; /* shouldn't happen? */ } _ustat2qid (&sb, &qid); if (!((ret = np_create_rsymlink (&qid)))) { np_uerror (ENOMEM); goto error; } free (npath); free (target); return ret; error: errn (np_rerror (), "diod_symlink %s@%s:%s/%.*s", fid->user->uname, np_conn_get_client_id (fid->conn), f->path, name->len, name->str); error_quiet: if (created && npath) (void)unlink (npath); if (npath) free (npath); if (target) free (target); if (ret) free (ret); return NULL; }
Npfcall* diod_symlink(Npfid *fid, Npstr *name, Npstr *symtgt, u32 gid) { Npsrv *srv = fid->conn->srv; Fid *f = fid->aux; Npfcall *ret; char *target = NULL; Path npath = NULL; Npqid qid; struct stat sb; if ((f->flags & DIOD_FID_FLAGS_ROFS)) { np_uerror (EROFS); goto error_quiet; } if (!(npath = path_append (srv, f->path, name))) { np_uerror (ENOMEM); goto error; } if (!(target = np_strdup (symtgt))) { np_uerror (ENOMEM); goto error; } if (symlink (target, path_s (npath)) < 0 || lstat (path_s (npath), &sb) < 0) { np_uerror (errno); goto error_quiet; } diod_ustat2qid (&sb, &qid); if (!((ret = np_create_rsymlink (&qid)))) { (void)unlink (path_s (npath)); np_uerror (ENOMEM); goto error; } path_decref (srv, npath); free (target); return ret; error: errn (np_rerror (), "diod_symlink %s@%s:%s/%.*s", fid->user->uname, np_conn_get_client_id (fid->conn), path_s (f->path), name->len, name->str); error_quiet: if (npath) path_decref (srv, npath); if (target) free (target); return NULL; }
static void test_rsymlink (void) { Npfcall *fc, *fc2; struct p9_qid qid = { 1, 2, 3 }; if (!(fc = np_create_rsymlink (&qid))) msg_exit ("out of memory"); fc2 = _rcv_buf (fc, P9_RSYMLINK, __FUNCTION__); assert (fc->u.rsymlink.qid.type == fc2->u.rsymlink.qid.type); assert (fc->u.rsymlink.qid.version == fc2->u.rsymlink.qid.version); assert (fc->u.rsymlink.qid.path == fc2->u.rsymlink.qid.path); free (fc); free (fc2); }