int rdonly(Session *s, Share *sp, char *path, int rdonly) { int rc; FInfo fi; if(Sess->caps & CAP_NT_SMBS) rc = T2queryall(s, sp, path, &fi); else rc = T2querystandard(s, sp, path, &fi); if(rc == -1) return -1; if((rdonly && !(fi.attribs & ATTR_READONLY)) || (!rdonly && (fi.attribs & ATTR_READONLY))){ fi.attribs &= ~ATTR_READONLY; fi.attribs |= rdonly? ATTR_READONLY: 0; rc = CIFSsetinfo(s, sp, path, &fi); } return rc; }
static int smbcreateopen(Aux *a, char *path, int mode, int perm, int is_create, int is_dir, FInfo *fip) { int rc, action, attrs, access, result; if(is_create && is_dir){ if(CIFScreatedirectory(Sess, a->sp, path) == -1) return -1; return 0; } if(mode & DMAPPEND) { werrstr("filesystem does not support DMAPPEND"); return -1; } if(is_create) action = 0x12; else if(mode & OTRUNC) action = 0x02; else action = 0x01; if(perm & 0222) attrs = ATTR_NORMAL; else attrs = ATTR_NORMAL|ATTR_READONLY; switch (mode & OMASK){ case OREAD: access = 0; break; case OWRITE: access = 1; break; case ORDWR: access = 2; break; case OEXEC: access = 3; break; default: werrstr("%d bad open mode", mode & OMASK); return -1; break; } if(mode & DMEXCL == 0) access |= 0x10; else access |= 0x40; if((a->fh = CIFS_SMB_opencreate(Sess, a->sp, path, access, attrs, action, &result)) == -1) return -1; if(Sess->caps & CAP_NT_SMBS) rc = T2queryall(Sess, a->sp, mapfile(a->path), fip); else rc = T2querystandard(Sess, a->sp, mapfile(a->path), fip); if(rc == -1){ fprint(2, "internal error: stat of newly open/created file failed\n"); return -1; } if((mode & OEXCL) && (result & 0x8000) == 0){ werrstr("%d bad open mode", mode & OMASK); return -1; } return 0; }
static char* fswalk1(Fid *fid, char *name, Qid *qid) { FInfo fi; int rc, n, i; Aux *a = fid->aux; static char e[ERRMAX]; char *p, *npath, *winpath; *e = 0; npath = newpath(a->path, name); if(strcmp(npath, "/") == 0){ /* root dir */ *qid = mkqid("/", 1, 1, Proot, 0); free(a->path); a->path = npath; fid->qid = *qid; return nil; } if(strrchr(npath, '/') == npath){ /* top level dir */ if((n = walkinfo(name)) != -1){ /* info file */ *qid = mkqid(npath, 0, 1, Pinfo, n); } else { /* volume name */ for(i = 0; i < Nshares; i++){ n = strlen(Shares[i].name); if(cistrncmp(npath+1, Shares[i].name, n) != 0) continue; if(Checkcase && strncmp(npath+1, Shares[i].name, n) != 0) continue; if(npath[n+1] != 0 && npath[n+1] != '/') continue; break; } if(i >= Nshares){ free(npath); return "not found"; } a->sp = Shares+i; *qid = mkqid(npath, 1, 1, Pshare, i); } free(a->path); a->path = npath; fid->qid = *qid; return nil; } /* must be a vanilla file or directory */ again: if(mapshare(npath, &a->sp) == -1){ rerrstr(e, sizeof(e)); free(npath); return e; } winpath = mapfile(npath); memset(&fi, 0, sizeof fi); if(Sess->caps & CAP_NT_SMBS) rc = T2queryall(Sess, a->sp, winpath, &fi); else rc = T2querystandard(Sess, a->sp, winpath, &fi); if(rc == -1){ rerrstr(e, sizeof(e)); free(npath); return e; } if((a->sp->options & SMB_SHARE_IS_IN_DFS) != 0 && (fi.attribs & ATTR_REPARSE) != 0){ if(redirect(Sess, a->sp, npath) != -1) goto again; } if((p = strrchr(fi.name, '/')) == nil && (p = strrchr(fi.name, '\\')) == nil) p = fi.name; else p++; if(! validfile(p, name, winpath, a->sp)){ free(npath); return "not found"; } *qid = mkqid(npath, fi.attribs & ATTR_DIRECTORY, fi.changed, 0, 0); free(a->path); a->path = npath; fid->qid = *qid; return nil; }