|
|
1.1 root 1: /* ftamd-select.c - FTAM responder -- selection regime */
2:
3: #ifndef lint
4: static char *rcsid = "$Header: /f/osi/ftam2/RCS/ftamd-select.c,v 7.1 90/07/01 21:03:20 mrose Exp $";
5: #endif
6:
7: /*
8: * $Header: /f/osi/ftam2/RCS/ftamd-select.c,v 7.1 90/07/01 21:03:20 mrose Exp $
9: *
10: *
11: * $Log: ftamd-select.c,v $
12: * Revision 7.1 90/07/01 21:03:20 mrose
13: * pepsy
14: *
15: * Revision 7.0 89/11/23 21:54:29 mrose
16: * Release 6.0
17: *
18: */
19:
20: /*
21: * NOTICE
22: *
23: * Acquisition, use, and distribution of this module and related
24: * materials are subject to the restrictions of a license agreement.
25: * Consult the Preface in the User's Manual for the full terms of
26: * this agreement.
27: *
28: */
29:
30:
31: #include <grp.h>
32: #include <stdio.h>
33: #include <pwd.h>
34: #include "ftamsystem.h"
35:
36:
37: #define NUID 400
38: #define NGID 400
39:
40:
41: #define FA_CHATTR \
42: (FA_FILENAME | FA_ACCOUNT)
43:
44:
45: #define FA_PERM_WRITE (FA_PERM_INSERT | FA_PERM_REPLACE | FA_PERM_EXTEND \
46: | FA_PERM_ERASE)
47: #define FA_PERM_OWNER FA_PERM_CHNGATTR
48: #define FA_PERM_PARENT FA_PERM_DELETE
49:
50:
51: #ifdef SYS5
52: struct group *getgrnam ();
53: struct passwd *getpwnam (), *getpwent (), *getpwuid ();
54: #endif
55:
56: /* DATA */
57:
58: static char mvfile[MAXPATHLEN];
59: static PE rdparam = NULLPE;
60:
61: char *getfile ();
62: #ifdef BRIDGE
63: #define E_OK R_OK
64: #else
65: char *getuser (), *getgroup ();
66: #endif
67:
68:
69: long lseek ();
70:
71: #ifdef SYS5
72: #define EACCESS access
73:
74: #define rename(f1,f2) \
75: (unlink (f2), link (f1, f2) != NOTOK ? unlink (f1) : NOTOK)
76: #endif
77:
78: #ifdef BRIDGE
79: #define ftp_access(file,mode) ftp_exist (file)
80: #endif
81:
82: /* SELECTION REGIME */
83:
84: int ftam_selection (ftg, ftm)
85: register struct FTAMgroup *ftg,
86: *ftm;
87: {
88: int action,
89: state;
90:
91: bzero ((char *) ftm, sizeof *ftm);
92: ftm -> ftg_flags = ftg -> ftg_flags;
93:
94: statok = 0;
95:
96: state = FSTATE_SUCCESS;
97: if (ftg -> ftg_flags & FTG_SELECT) {
98: register struct FTAMselect *ftse = &ftg -> ftg_select;
99: register struct FTAMattributes *fa = &ftse -> ftse_attrs;
100: struct FTAMdiagnostic *dp = ftm -> ftg_select.ftse_diags;
101:
102: errno = 0;
103: if (!(fa -> fa_present & FA_FILENAME)
104: || fa -> fa_nfile != 1
105: || (myfile = getfile (fa -> fa_files[0])) == NULL
106: #ifdef BRIDGE
107: || ftp_access (myfile, E_OK) == NOTOK) {
108: #else
109: || stat (myfile, &myst) == NOTOK) {
110: #endif
111: dp -> ftd_type = DIAG_PERM;
112: dp -> ftd_identifier = FS_SEL_FILENAME;
113: dp -> ftd_observer = dp -> ftd_source = EREF_RFSU;
114: dp -> ftd_delay = DIAG_NODELAY;
115: if (errno) {
116: (void) strcpy (dp -> ftd_data, sys_errname (errno));
117: dp -> ftd_cc = strlen (dp -> ftd_data);
118: }
119: else
120: dp -> ftd_cc = 0;
121: dp++;
122:
123: state = FSTATE_FAILURE;
124: goto done_select;
125: }
126: statok = 1;
127: #ifndef BRIDGE
128: switch (myst.st_mode & S_IFMT) {
129: case S_IFREG:
130: case S_IFDIR:
131: break;
132:
133: default:
134: if (myst.st_dev == null_dev && myst.st_ino == null_ino) {
135: myst.st_mode &= ~S_IFMT, myst.st_mode |= S_IFREG;
136: break;
137: }
138: dp -> ftd_type = DIAG_PERM;
139: dp -> ftd_identifier = FS_SEL_AVAIL;
140: dp -> ftd_observer = dp -> ftd_source = EREF_RFSU;
141: dp -> ftd_delay = DIAG_NODELAY;
142: dp -> ftd_cc = 0;
143: dp++;
144:
145: state = FSTATE_FAILURE;
146: goto done_select;
147: }
148: #else
149: /* can't check a file you don't have */
150: #endif
151:
152: if (ftg -> ftg_flags & FTG_RDATTR)
153: ftse -> ftse_access |= FA_PERM_READATTR;
154: if (ftg -> ftg_flags & FTG_CHATTR)
155: ftse -> ftse_access |= FA_PERM_CHNGATTR;
156: if (ftg -> ftg_flags & FTG_DELETE)
157: ftse -> ftse_access |= FA_PERM_DELETE;
158: if (chkaccess (NOTOK, ftse -> ftse_access, &ftse -> ftse_conctl, &dp)
159: == NOTOK) {
160: state = FSTATE_FAILURE;
161: goto done_select;
162: }
163: #ifndef BRIDGE
164: if (ftse -> ftse_account) {
165: if ((mygid = findgid (ftse -> ftse_account)) == NOTOK) {
166: dp -> ftd_type = DIAG_PERM;
167: dp -> ftd_identifier = FS_SEL_ACCOUNT;
168: dp -> ftd_observer = EREF_RFSU, dp -> ftd_source = EREF_IFSU;
169: dp -> ftd_delay = DIAG_NODELAY;
170: dp -> ftd_cc = 0;
171: dp++;
172:
173: state = FSTATE_FAILURE;
174: goto done_select;
175: }
176: }
177: else
178: #else
179: /* no account checking */
180: #endif
181: mygid = NOTOK;
182:
183: done_select: ;
184: myaccess = ftse -> ftse_access;
185: ftm -> ftg_select.ftse_state = state;
186: ftm -> ftg_select.ftse_ndiag = dp - ftm -> ftg_select.ftse_diags;
187: }
188:
189: if (ftg -> ftg_flags & FTG_CREATE) {
190: register struct FTAMcreate *ftce = &ftg -> ftg_create;
191: register struct FTAMattributes *fa = &ftce -> ftce_attrs;
192: struct FTAMdiagnostic *dp = ftm -> ftg_create.ftce_diags;
193: register struct vfsmap *vf;
194:
195: if (!(fa -> fa_present & FA_FILENAME)
196: || fa -> fa_nfile != 1
197: || (myfile = getfile (fa -> fa_files[0])) == NULL) {
198: dp -> ftd_type = DIAG_PERM;
199: dp -> ftd_identifier = FS_SEL_FILENAME;
200: dp -> ftd_observer = dp -> ftd_source = EREF_RFSU;
201: dp -> ftd_delay = DIAG_NODELAY;
202: dp -> ftd_cc = 0;
203: dp++;
204:
205: state = FSTATE_FAILURE;
206: goto done_create;
207: }
208: #ifdef BRIDGE
209: if (ftp_access (myfile, E_OK) != NOTOK)
210: #else
211: if (stat (myfile, &myst) != NOTOK)
212: #endif
213: statok = 1;
214: if (statok) {
215: #ifndef BRIDGE /* Assume file type allow corrective action */
216: switch (myst.st_mode & S_IFMT) {
217: case S_IFREG:
218: break;
219:
220: case S_IFDIR:
221: switch (ftce -> ftce_override) {
222: case FOVER_WRITE:
223: dp -> ftd_type = DIAG_PERM;
224: dp -> ftd_identifier = FS_SEL_CRELOSE;
225: dp -> ftd_observer = dp -> ftd_source = EREF_RFSU;
226: dp -> ftd_delay = DIAG_NODELAY;
227: dp -> ftd_cc = 0;
228: dp++;
229:
230: state = FSTATE_FAILURE;
231: goto done_create;
232:
233: default:
234: break;
235: }
236: break;
237:
238: default:
239: if (myst.st_dev == null_dev && myst.st_ino == null_ino) {
240: myst.st_mode &= ~S_IFMT, myst.st_mode |= S_IFREG;
241: break;
242: }
243: dp -> ftd_type = DIAG_PERM;
244: dp -> ftd_identifier = FS_SEL_AVAIL;
245: dp -> ftd_observer = dp -> ftd_source = EREF_RFSU;
246: dp -> ftd_delay = DIAG_NODELAY;
247: dp -> ftd_cc = 0;
248: dp++;
249:
250: state = FSTATE_FAILURE;
251: goto done_create;
252: }
253: #endif
254: switch (ftce -> ftce_override) {
255: case FOVER_FAIL:
256: dp -> ftd_type = DIAG_PERM;
257: dp -> ftd_identifier = FS_SEL_EXISTS;
258: dp -> ftd_observer = dp -> ftd_source = EREF_RFSU;
259: dp -> ftd_delay = DIAG_NODELAY;
260: dp -> ftd_cc = 0;
261: dp++;
262:
263: state = FSTATE_FAILURE;
264: goto done_create;
265:
266: case FOVER_SELECT:
267: if (ftg -> ftg_flags & FTG_RDATTR)
268: ftce -> ftce_access |= FA_PERM_READATTR;
269: if (ftg -> ftg_flags & FTG_CHATTR)
270: ftce -> ftce_access |= FA_PERM_CHNGATTR;
271: if (ftg -> ftg_flags & FTG_DELETE)
272: ftce -> ftce_access |= FA_PERM_DELETE;
273: if (chkaccess (NOTOK, ftce -> ftce_access,
274: &ftce -> ftce_conctl, &dp) == NOTOK) {
275: state = FSTATE_FAILURE;
276: goto done_create;
277: }
278: break;
279:
280: default:
281: break;
282: }
283: }
284:
285: for (vf = vfs; vf -> vf_entry; vf++)
286: if (vf -> vf_oid
287: && oid_cmp (vf -> vf_oid, fa -> fa_contents) == 0)
288: break;
289: if (!vf -> vf_entry) {
290: (void) sprintf (dp -> ftd_data,
291: "invalid contents-type %s",
292: sprintoid (fa -> fa_contents));
293: dp -> ftd_cc = strlen (dp -> ftd_data);
294: dp -> ftd_type = DIAG_PERM;
295: dp -> ftd_identifier = FS_SEL_ATRVALUE;
296: dp -> ftd_observer = EREF_RFSU, dp -> ftd_source = EREF_IFSU;
297: dp -> ftd_delay = DIAG_NODELAY;
298: dp++;
299:
300: state = FSTATE_FAILURE;
301: goto done_create;
302: }
303:
304: if (chkattrs (fa, fa -> fa_present & ~(FA_FILENAME | FA_CONTENTS),
305: 1, &dp) == NOTOK) {
306: state = FSTATE_FAILURE;
307: goto done_create;
308: }
309:
310: #ifndef BRIDGE /* no account checking */
311: if (ftce -> ftce_account) {
312: if ((mygid = findgid (ftce -> ftce_account)) == NOTOK) {
313: dp -> ftd_type = DIAG_PERM;
314: dp -> ftd_identifier = FS_SEL_ACCOUNT;
315: dp -> ftd_observer = EREF_RFSU, dp -> ftd_source = EREF_IFSU;
316: dp -> ftd_delay = DIAG_NODELAY;
317: dp -> ftd_cc = 0;
318: dp++;
319:
320: state = FSTATE_FAILURE;
321: goto done_create;
322: }
323: }
324: else
325: #endif
326: mygid = NOTOK;
327:
328: done_create: ;
329: ftm -> ftg_create.ftce_state = state;
330: ftm -> ftg_create.ftce_ndiag = dp - ftm -> ftg_create.ftce_diags;
331: }
332:
333: if (ftg -> ftg_flags & FTG_RDATTR)
334: ftm -> ftg_readattr.ftra_action = FACTION_SUCCESS;
335:
336: if (ftg -> ftg_flags & FTG_CHATTR) {
337: register struct FTAMchngattr *ftca = &ftg -> ftg_chngattr;
338: register struct FTAMattributes *fa = &ftca -> ftca_attrs;
339: struct FTAMdiagnostic *dp = ftm -> ftg_chngattr.ftca_diags;
340:
341: if (chkattrs (fa, fa -> fa_present, 0, &dp) == NOTOK)
342: action = FACTION_PERM;
343: else
344: action = FACTION_SUCCESS;
345:
346: ftm -> ftg_chngattr.ftca_action = action;
347: ftm -> ftg_chngattr.ftca_ndiag = dp - ftm -> ftg_chngattr.ftca_diags;
348: }
349:
350: if (ftg -> ftg_flags & FTG_OPEN) {
351: register struct FTAMopen *ftop = &ftm -> ftg_open;
352:
353: ftop -> ftop_state = FSTATE_FAILURE;
354: ftop -> ftop_action = FACTION_SUCCESS;
355: if (ftop -> ftop_contents = ftg -> ftg_open.ftop_contents)
356: ftop -> ftop_parameter = ftg -> ftg_open.ftop_parameter;
357:
358: FCINIT (&ftop -> ftop_conctl);
359: }
360:
361: if (ftg -> ftg_flags & FTG_CLOSE)
362: ftm -> ftg_close.ftcl_action = FACTION_SUCCESS;
363:
364: if (ftg -> ftg_flags & FTG_DESELECT)
365: ftm -> ftg_deselect.ftde_action = FACTION_SUCCESS;
366:
367: if (ftg -> ftg_flags & FTG_DELETE)
368: ftm -> ftg_delete.ftxe_action = FACTION_SUCCESS;
369:
370: if (ftg -> ftg_flags & FTG_SELECT) {
371: register struct FTAMselect *ftse = &ftm -> ftg_select;
372: register struct FTAMattributes *fa = &ftse -> ftse_attrs;
373:
374: if (state != FSTATE_SUCCESS) {
375: ftse -> ftse_action = FACTION_PERM;
376: *fa = ftg -> ftg_select.ftse_attrs; /* struct copy */
377: ftm -> ftg_flags &= ~(FTG_RDATTR | FTG_CHATTR | FTG_OPEN);
378: return;
379: }
380: ftse -> ftse_action = FACTION_SUCCESS;
381: fa -> fa_present = FA_FILENAME;
382: fa -> fa_nfile = 0;
383: fa -> fa_files[fa -> fa_nfile++] = myfile;
384: }
385:
386: if (ftg -> ftg_flags & FTG_CREATE) {
387: register struct FTAMattributes *fa = &ftg -> ftg_create.ftce_attrs;
388: register struct FTAMcreate *ftce = &ftm -> ftg_create;
389: struct FTAMdiagnostic *dp = ftce -> ftce_diags + ftce -> ftce_ndiag;
390:
391: if (state != FSTATE_SUCCESS) {
392: ftce -> ftce_action = FACTION_PERM;
393: ftce -> ftce_attrs = *fa; /* struct copy */
394: ftm -> ftg_flags &= ~(FTG_RDATTR | FTG_CHATTR | FTG_OPEN);
395: return;
396: }
397: switch (ftg -> ftg_create.ftce_override) {
398: case FOVER_SELECT:
399: default:
400: if (statok)
401: break;
402: goto do_create;
403:
404: case FOVER_DELETE:
405: #ifdef BRIDGE
406: if (statok && ftp_delete (myfile) == NOTOK) {
407: #else
408: if (statok
409: && ((myst.st_mode & S_IFMT) == S_IFREG
410: ? unlink (myfile)
411: : rmdir (myfile)) == NOTOK) {
412: bad_override: ;
413: #endif
414: dp -> ftd_type = DIAG_PERM;
415: dp -> ftd_identifier = FS_SEL_CRELOSE;
416: dp -> ftd_observer = dp -> ftd_source = EREF_RFSU;
417: dp -> ftd_delay = DIAG_NODELAY;
418: #ifdef BRIDGE
419: (void) strcpy (dp -> ftd_data, ftp_error);
420: #else
421: (void) strcpy (dp -> ftd_data, sys_errname (errno));
422: #endif
423: dp -> ftd_cc = strlen (dp -> ftd_data);
424: dp++;
425:
426: bad_create: ;
427: ftce -> ftce_action = FACTION_PERM;
428: ftce -> ftce_attrs = *fa; /* struct copy */
429: ftce -> ftce_ndiag = dp - ftce -> ftce_diags;
430:
431: ftce -> ftce_state = FSTATE_FAILURE;
432: ftm -> ftg_flags &= ~(FTG_RDATTR | FTG_CHATTR | FTG_OPEN);
433: return;
434: }
435: /* else fall */
436:
437: case FOVER_FAIL:
438: statok = 0;
439: do_create: ;
440: if (!(fa -> fa_present & FA_CONTENTS)
441: || oid_cmp (vfs[VFS_FDF].vf_oid, fa -> fa_contents)) {
442: #ifdef BRIDGE
443: if (ftp_create (myfile) == NOTOK) {
444: #else
445: if ((myfd = open (myfile, O_RDWR | O_CREAT | O_TRUNC,
446: 0666)) == NOTOK) {
447: #endif
448: bad_open: ;
449: dp -> ftd_type = DIAG_PERM;
450: dp -> ftd_identifier = FS_SEL_CREATE;
451: dp -> ftd_observer = dp -> ftd_source = EREF_RFSU;
452: dp -> ftd_delay = DIAG_NODELAY;
453: (void) strcpy (dp -> ftd_data, sys_errname (errno));
454: dp -> ftd_cc = strlen (dp -> ftd_data);
455: dp++;
456:
457: goto bad_create;
458: }
459: }
460: else
461: #ifdef BRIDGE
462: if (ftp_mkdir (myfile) == NOTOK)
463: #else
464: if (mkdir (myfile, 0755) == NOTOK)
465: #endif
466: goto bad_open;
467: if (chngattrs (fa -> fa_present
468: & ~(FA_FILENAME | FA_CONTENTS), fa, &dp) == NOTOK)
469: goto bad_create;
470: break;
471:
472: case FOVER_WRITE:
473: if (!statok)
474: goto do_create;
475: #ifndef BRIDGE
476: #ifdef SUNOS4
477: if (myst.st_size > 0 && truncate (myfile, (off_t) 0) == NOTOK)
478: goto bad_override;
479: #else
480: if (myst.st_size > 0 && truncate (myfile, 0) == NOTOK)
481: goto bad_override;
482: #endif
483: #endif
484: break;
485: }
486:
487: ftce -> ftce_action = FACTION_SUCCESS;
488: (void) readattrs (FA_FILENAME | FA_ACTIONS | FA_CONTENTS,
489: &ftce -> ftce_attrs, fa -> fa_contents,
490: fa -> fa_parameter, myfile, &myst, &dp);
491: if (fa -> fa_present & FA_ACTIONS)
492: ftce -> ftce_attrs.fa_permitted &= fa -> fa_permitted;
493: ftce -> ftce_ndiag = dp - ftce -> ftce_diags;
494: }
495:
496: if (ftg -> ftg_flags & FTG_RDATTR
497: && (ftm -> ftg_readattr.ftra_action == FACTION_SUCCESS)) {
498: register struct FTAMreadattr *ftra = &ftm -> ftg_readattr;
499: struct FTAMdiagnostic *dp = ftra -> ftra_diags + ftra -> ftra_ndiag;
500:
501: if (!statok) {
502: #ifdef BRIDGE
503: if (0) { /* assume OK */
504: #else
505: if ((myfd != NOTOK ? fstat (myfd, &myst)
506: : stat (myfile, &myst)) == NOTOK) {
507: dp -> ftd_type = DIAG_PERM;
508: dp -> ftd_identifier = FS_MGT_READ;
509: dp -> ftd_observer = dp -> ftd_source = EREF_RFSU;
510: dp -> ftd_delay = DIAG_NODELAY;
511: dp -> ftd_cc = 0;
512: dp++;
513: #endif
514:
515: bad_readattr: ;
516: ftra -> ftra_action = FACTION_PERM;
517: ftra -> ftra_ndiag = dp - ftra -> ftra_diags;
518: return;
519: }
520: else
521: statok++;
522: }
523: if (readattrs (ftg -> ftg_readattr.ftra_attrnames,
524: &ftra -> ftra_attrs, ftg -> ftg_flags & FTG_OPEN
525: ? ftg -> ftg_open.ftop_contents : NULLOID, NULLPE,
526: myfile, &myst, &dp) == NOTOK)
527: goto bad_readattr;
528: ftra -> ftra_ndiag = dp - ftra -> ftra_diags;
529: }
530:
531: if (ftg -> ftg_flags & FTG_CHATTR
532: && (ftm -> ftg_chngattr.ftca_action == FACTION_SUCCESS)) {
533: register struct FTAMchngattr *ftca = &ftm -> ftg_chngattr;
534: register struct FTAMattributes *fa = &ftg -> ftg_chngattr.ftca_attrs;
535: struct FTAMdiagnostic *dp = ftca -> ftca_diags + ftca -> ftca_ndiag;
536:
537: if (chngattrs (fa -> fa_present, fa, &dp) == NOTOK) {
538: ftca -> ftca_action = FACTION_PERM;
539: ftca -> ftca_ndiag = dp - ftca -> ftca_diags;
540: return;
541: }
542:
543: ftca -> ftca_ndiag = dp - ftca -> ftca_diags;
544: }
545:
546: if (ftg -> ftg_flags & FTG_OPEN) {
547: #ifndef BRIDGE
548: int mode;
549: #endif
550: register struct FTAMopen *ftop = &ftm -> ftg_open;
551: struct FTAMdiagnostic *dp = ftop -> ftop_diags + ftop -> ftop_ndiag;
552:
553: ftop -> ftop_state = FSTATE_SUCCESS;
554: if (statok == 0) {
555: if (stat (myfile, &myst) == NOTOK) {
556: #ifndef BRIDGE
557: unavailable: ;
558: #endif
559: dp -> ftd_type = DIAG_PERM;
560: dp -> ftd_identifier = FS_SEL_AVAIL;
561: dp -> ftd_observer = dp -> ftd_source = EREF_RFSU;
562: dp -> ftd_delay = DIAG_NODELAY;
563: if (errno) {
564: (void) strcpy (dp -> ftd_data, sys_errname (errno));
565: dp -> ftd_cc = strlen (dp -> ftd_data);
566: }
567: else
568: dp -> ftd_cc = 0;
569: dp++;
570:
571: ftop -> ftop_state = FSTATE_FAILURE;
572: goto done_open;
573: }
574: else
575: statok = 1;
576: }
577:
578: if (ftop -> ftop_contents == NULL) {
579: register struct FTAMattributes *fa;
580:
581: if (ftg -> ftg_flags & FTG_CREATE) {
582: fa = &ftg -> ftg_create.ftce_attrs;
583:
584: ftop -> ftop_contents = fa -> fa_contents;
585: ftop -> ftop_parameter = fa -> fa_parameter;
586: advise (LLOG_DEBUG, NULLCP,
587: "using contents-type from CREATE <%s, 0x%x>",
588: oid2ode (ftop -> ftop_contents),
589: ftop -> ftop_parameter);
590: goto find_myvfs;
591: }
592:
593: if ((ftg -> ftg_flags & FTG_RDATTR)
594: && ftm -> ftg_readattr.ftra_action == FACTION_SUCCESS
595: && ((fa = &ftm -> ftg_readattr.ftra_attrs) -> fa_present
596: & FA_CONTENTS)) {
597: ftop -> ftop_contents = fa -> fa_contents;
598: ftop -> ftop_parameter = fa -> fa_parameter;
599: advise (LLOG_DEBUG, NULLCP,
600: "using contents-type from READ-ATTRIBUTE <%s, 0x%x>",
601: oid2ode (ftop -> ftop_contents),
602: ftop -> ftop_parameter);
603:
604: find_myvfs: ;
605: if ((myvf = st2vfs (myfd, myfile, &myst, ftop -> ftop_contents,
606: ftamfd)) == NULL)
607: goto no_ascertain;
608: if (oid_cmp (ftop -> ftop_contents, myvf -> vf_oid) == 0)
609: goto find_param;
610: advise (LLOG_DEBUG, NULLCP,
611: "wrong intuition; back to step one");
612: ftop -> ftop_contents = NULLOID;
613: ftop -> ftop_parameter = NULLPE;
614: }
615:
616: if ((myvf = st2vfs (myfd, myfile, &myst, NULLOID, ftamfd))
617: == NULL) {
618: no_ascertain: ;
619: (void) strcpy (dp -> ftd_data,
620: "unable to ascertain contents-type");
621: dp -> ftd_cc = strlen (dp -> ftd_data);
622: dp -> ftd_type = DIAG_PERM;
623: dp -> ftd_identifier = FS_ACC_LCL;
624: dp -> ftd_observer = dp -> ftd_source = EREF_RFSU;
625: dp -> ftd_delay = DIAG_NODELAY;
626: dp++;
627:
628: ftop -> ftop_state = FSTATE_FAILURE;
629: goto done_open;
630: }
631: ftop -> ftop_contents = myvf -> vf_oid;
632: advise (LLOG_DEBUG, NULLCP,
633: "using contents-type from st2vfs: %s",
634: oid2ode (ftop -> ftop_contents));
635:
636: find_param: ;
637: if (myvf -> vf_mandatory > 0 && ftop -> ftop_parameter == NULL) {
638: char buffer[BUFSIZ];
639:
640: if (rdparam)
641: pe_free (rdparam), rdparam = NULLPE;
642: if (enc_f (myvf -> vf_number, &_ZDOCS_mod, &rdparam, 1, 0,
643: NULLCP, myvf -> vf_parameter) == NOTOK) {
644: advise (LLOG_EXCEPTIONS, NULLCP,
645: "unable to build parameter: %s", PY_pepy);
646: if (rdparam)
647: pe_free (rdparam), rdparam = NULLPE;
648: goto no_ascertain;
649: }
650: ftop -> ftop_parameter = rdparam;
651:
652: vpushstr (buffer);
653: vunknown (ftop -> ftop_parameter);
654: vpopstr ();
655: advise (LLOG_DEBUG, NULLCP,
656: "generating parameter from vfs: %s", buffer);
657: }
658: else
659: if (!myvf -> vf_mandatory && ftop -> ftop_parameter)
660: ftop -> ftop_parameter = NULLPE;
661: }
662: else
663: if ((myvf = st2vfs (myfd, myfile, &myst, ftop -> ftop_contents,
664: ftamfd)) == NULL) {
665: dp -> ftd_cc = 0;
666: bad_param: ;
667: dp -> ftd_type = DIAG_PERM;
668: dp -> ftd_identifier = FS_ACC_TYPINCON;
669: dp -> ftd_observer = EREF_RFSU, dp -> ftd_source = EREF_IFSU;
670: dp -> ftd_delay = DIAG_NODELAY;
671: dp++;
672:
673: ftop -> ftop_state = FSTATE_FAILURE;
674: goto done_open;
675: }
676:
677: if (oid_cmp (ftop -> ftop_contents, myvf -> vf_oid)) {
678: advise (LLOG_NOTICE, NULLCP, "simplifying document type");
679:
680: ftop -> ftop_contents = myvf -> vf_oid;
681: ftop -> ftop_parameter = NULLPE;
682: if (myvf -> vf_mandatory) {
683: char buffer[BUFSIZ];
684:
685: if (rdparam)
686: pe_free (rdparam), rdparam = NULLPE;
687: if (enc_f (myvf -> vf_number, &_ZDOCS_mod, &rdparam, 1, 0,
688: NULLCP, myvf -> vf_parameter) == NOTOK) {
689: advise (LLOG_EXCEPTIONS, NULLCP,
690: "unable to build parameter: %s", PY_pepy);
691: if (rdparam)
692: pe_free (rdparam), rdparam = NULLPE;
693: goto no_ascertain;
694: }
695: ftop -> ftop_parameter = rdparam;
696:
697: vpushstr (buffer);
698: vunknown (ftop -> ftop_parameter);
699: vpopstr ();
700: advise (LLOG_DEBUG, NULLCP,
701: "generating parameter from myvf: %s", buffer);
702: }
703: }
704:
705: if (ftop -> ftop_parameter) {
706: if (myvf -> vf_number < 0) {
707: (void) sprintf (dp -> ftd_data,
708: "unexpected document type parameter");
709: dp -> ftd_cc = strlen (dp -> ftd_data);
710: goto bad_param;
711: }
712: myparam = NULL;
713: if (dec_f (myvf -> vf_number, &_ZDOCS_mod, ftop -> ftop_parameter,
714: 1, NULLIP, NULLVP, &myparam) == NOTOK) {
715: (void) sprintf (dp -> ftd_data,
716: "unable to parse document type parameter: %s",
717: PY_pepy);
718: dp -> ftd_cc = strlen (dp -> ftd_data);
719: goto bad_param;
720: }
721: if (myvf -> vf_check
722: && (*myvf -> vf_check) (myparam, dp -> ftd_data)
723: == NOTOK)
724: goto bad_param;
725: }
726: else
727: if (myvf -> vf_mandatory > 0) {
728: (void) strcpy (dp -> ftd_data,
729: "mandatory document type parameter missing");
730: dp -> ftd_cc = strlen (dp -> ftd_data);
731: goto bad_param;
732: }
733:
734: mymode = ftg -> ftg_open.ftop_mode;
735: #ifndef BRIDGE
736: if (mymode & FA_PERM_WRITE)
737: mode = (mymode & FA_PERM_READ) ? O_RDWR : O_WRONLY;
738: else
739: mode = O_RDONLY;
740: #endif
741:
742: errno = 0;
743: #ifndef BRIDGE
744: switch (myst.st_mode & S_IFMT) {
745: case S_IFREG:
746: if (myfd == NOTOK && (myfd = open (myfile, mode)) == NOTOK)
747: goto unavailable;
748: break;
749:
750: case S_IFDIR:
751: if (mode == O_RDONLY)
752: break;
753: /* else fall */
754:
755: default:
756: goto unavailable;
757: }
758: #endif
759:
760: myconctl = ftg -> ftg_open.ftop_conctl; /* struct copy */
761: ftm -> ftg_open.ftop_conctl = myconctl; /* .. */
762: mylockstyle = ftg -> ftg_open.ftop_locking;
763:
764: if (chkaccess (myfd, mymode, &myconctl, &dp) == NOTOK) {
765: ftop -> ftop_state = FSTATE_FAILURE;
766: goto done_open;
767: }
768:
769: done_open: ;
770: ftop -> ftop_ndiag = dp - ftop -> ftop_diags;
771:
772: if (ftop -> ftop_state != FSTATE_SUCCESS) {
773: ftop -> ftop_action = FACTION_PERM;
774: return;
775: }
776: }
777:
778: if (ftg -> ftg_flags & FTG_CLOSE
779: && (ftm -> ftg_close.ftcl_action == FACTION_SUCCESS)) {
780: if (myfd != NOTOK) {
781: #ifdef BRIDGE
782: (void) close (myfd);
783: (void) ftp_reply ();
784: #else
785: unlock ();
786: (void) close (myfd);
787: #endif
788: myfd = NOTOK;
789: }
790: if (myvf && myparam) {
791: fre_obj (myparam, _ZDOCS_mod.md_dtab[myvf -> vf_number],
792: &_ZDOCS_mod);
793: myparam = NULL;
794: }
795: }
796:
797: if (ftg -> ftg_flags & FTG_DESELECT) {
798: register struct FTAMdeselect *ftde = &ftm -> ftg_deselect;
799:
800: if (ftde -> ftde_action == FACTION_SUCCESS) {
801: /* anything to charge if (mygid != NOTOK)? ha! */
802: }
803: }
804:
805: if (ftg -> ftg_flags & FTG_DELETE) {
806: register struct FTAMdelete *ftxe = &ftm -> ftg_delete;
807: struct FTAMdiagnostic *dp = ftxe -> ftxe_diags + ftxe -> ftxe_ndiag;
808:
809: if (ftxe -> ftxe_action == FACTION_SUCCESS) {
810: #ifdef BRIDGE
811: if (ftp_delete (myfile) == NOTOK) {
812: #else
813: if (!statok && stat (myfile, &myst) == NOTOK)
814: myst.st_mode = S_IFREG;
815: if (((myst.st_mode & S_IFMT) == S_IFREG ? unlink (myfile)
816: : rmdir (myfile))
817: == NOTOK) {
818: #endif
819: dp -> ftd_type = DIAG_PERM;
820: dp -> ftd_identifier = FS_SEL_DELETE;
821: dp -> ftd_observer = dp -> ftd_source = EREF_RFSU;
822: dp -> ftd_delay = DIAG_NODELAY;
823: #ifdef BRIDGE
824: (void) strcpy (dp -> ftd_data, ftp_error);
825: #else
826: (void) strcpy (dp -> ftd_data, sys_errname (errno));
827: #endif
828: dp -> ftd_cc = strlen (dp -> ftd_data);
829: dp++;
830:
831: ftxe -> ftxe_action = FACTION_PERM;
832: ftxe -> ftxe_ndiag = dp - ftxe -> ftxe_diags;
833: return;
834: }
835: advise (LLOG_NOTICE, NULLCP, "delete %s", myfile);
836: }
837: }
838: }
839:
840: /* */
841:
842: #ifdef BRIDGE
843: /* ARGSUSED */
844: #endif
845:
846: static int chkaccess (fd, request, fc, diags)
847: int fd,
848: request;
849: #ifndef BRIDGE
850: register
851: #endif
852: struct FTAMconcurrency *fc;
853: register struct FTAMdiagnostic **diags;
854: {
855: int result;
856: #ifndef BRIDGE
857: register char *cp;
858: #endif
859: register struct FTAMdiagnostic *dp = *diags;
860:
861: result = OK;
862:
863: #ifndef BRIDGE
864: if (((request & FA_PERM_READ) && EACCESS (myfile, R_OK) == NOTOK)
865: || ((request & FA_PERM_WRITE) && EACCESS (myfile, W_OK) == NOTOK)
866: || ((request & FA_PERM_OWNER)
867: && (myuid != myst.st_uid && myuid != 0))) {
868: no_access: ;
869: dp -> ftd_type = DIAG_PERM;
870: dp -> ftd_identifier = FS_SEL_ACCAVAIL;
871: dp -> ftd_observer = dp -> ftd_source = EREF_RFSU;
872: dp -> ftd_delay = DIAG_NODELAY;
873: dp -> ftd_cc = 0;
874: dp++;
875:
876: result = NOTOK;
877: goto out;
878: }
879: if (request & FA_PERM_PARENT) {
880: if (cp = rindex (myfile, '/')) {
881: *cp = NULL;
882: result = EACCESS (*myfile ? myfile : "/", W_OK);
883: *cp = '/';
884: }
885: else
886: result = EACCESS (".", W_OK);
887:
888: if (result == NOTOK)
889: goto no_access;
890: }
891: #else
892: /* already selected file and know it exists, FTP cannot tell us more */
893: #endif
894:
895: #ifndef BRIDGE
896: out: ;
897:
898: if (attrs & FATTR_STORAGE) {
899: if (fd == NOTOK) {
900: mylock = 0;
901:
902: if (((request & FA_PERM_READATTR)
903: && (fc -> fc_readattrlock & FLOCK_RESTRICT))
904: || ((request & FA_PERM_CHNGATTR)
905: && (fc -> fc_chngattrlock & FLOCK_RESTRICT))
906: || ((request & FA_PERM_DELETE)
907: && (fc -> fc_deletelock & FLOCK_RESTRICT))) {
908: dp -> ftd_type = DIAG_PERM;
909: dp -> ftd_identifier = FS_SEL_CONSUPRT;
910: dp -> ftd_observer = dp -> ftd_source = EREF_RFSU;
911: dp -> ftd_delay = DIAG_NODELAY;
912: dp -> ftd_cc = 0;
913: dp++;
914:
915: result = NOTOK;
916: }
917: }
918: else {
919: #ifdef SYS5
920: struct flock fs;
921: #endif
922:
923: if ((request & FA_PERM_WRITE)
924: && ((fc -> fc_insertlock & FLOCK_RESTRICT)
925: || (fc -> fc_replacelock & FLOCK_RESTRICT)
926: || (fc -> fc_eraselock & FLOCK_RESTRICT)
927: || (fc -> fc_extendlock & FLOCK_RESTRICT))) {
928: mylock = 1;
929: #ifndef SYS5
930: if (flock (fd, LOCK_EX) == NOTOK)
931: goto bad_concur;
932: #else
933: fs.l_type = F_WRLCK;
934: fs.l_whence = L_SET;
935: fs.l_start = fs.l_len = 0;
936: if (fcntl (fd, F_SETLKW, &fs) == NOTOK)
937: goto bad_concur;
938: #endif
939: }
940: else
941: if ((request & FA_PERM_READ)
942: && (fc -> fc_readlock & FLOCK_RESTRICT)) {
943: mylock = 1;
944: #ifndef SYS5
945: if (flock (fd, LOCK_SH) == NOTOK) {
946: #else
947: fs.l_type = F_RDLCK;
948: fs.l_whence = L_SET;
949: fs.l_start = fs.l_len = 0;
950: if (fcntl (fd, F_SETLKW, &fs) == NOTOK) {
951: #endif
952: bad_concur: ;
953: dp -> ftd_type = DIAG_PERM;
954: dp -> ftd_identifier = FS_ACC_CONAVAIL;
955: dp -> ftd_observer = dp -> ftd_source = EREF_RFSU;
956: dp -> ftd_delay = DIAG_NODELAY;
957: (void) strcpy (dp -> ftd_data, sys_errname (errno));
958: dp -> ftd_cc = strlen (dp -> ftd_data);
959: dp++;
960:
961: mylock = 0;
962: result = NOTOK;
963: }
964: }
965: }
966: }
967: #endif
968:
969: *diags = dp;
970: return result;
971: }
972:
973: /* */
974:
975: static int chkattrs (fa, present, select, diags)
976: register struct FTAMattributes *fa;
977: long present;
978: int select;
979: register struct FTAMdiagnostic **diags;
980: {
981: int id,
982: result;
983: char *file;
984: register struct FTAMdiagnostic *dp = *diags;
985:
986: result = OK;
987:
988: present &= ~FA_FUTURESIZE; /* be liberal in what you accept... */
989: if (present & ~(FA_CHATTR | FA_RDATTR)) {
990: dp -> ftd_type = DIAG_PERM;
991: dp -> ftd_identifier = select ? FS_SEL_INITIAL
992: : (present & FA_RDATTR) ? FS_MGT_CHANGE : FS_MGT_EXIST;
993: dp -> ftd_observer = dp -> ftd_source = EREF_RFSU;
994: dp -> ftd_delay = DIAG_NODELAY;
995: dp -> ftd_cc = 0;
996: dp++;
997:
998: result = NOTOK;
999: }
1000:
1001: id = select ? FS_SEL_ATRVALUE : FS_MGT_VALUE;
1002:
1003: if (present & FA_FILENAME) {
1004: if (fa -> fa_nfile != 1
1005: || (file = getfile (fa -> fa_files[0])) == NULL) {
1006: dp -> ftd_type = DIAG_PERM;
1007: dp -> ftd_identifier = id;
1008: dp -> ftd_observer = EREF_RFSU, dp -> ftd_source = EREF_IFSU;
1009: dp -> ftd_delay = DIAG_NODELAY;
1010: (void) strcpy (dp -> ftd_data, "00bad filename");
1011: dp -> ftd_cc = strlen (dp -> ftd_data);
1012: dp++;
1013:
1014: result = NOTOK;
1015: }
1016: else
1017: (void) strcpy (mvfile, file);
1018: }
1019:
1020: #ifndef BRIDGE
1021: if ((present & FA_ACCOUNT) && findgid (fa -> fa_account) == NOTOK) {
1022: dp -> ftd_type = DIAG_PERM;
1023: dp -> ftd_identifier = id;
1024: dp -> ftd_observer = EREF_RFSU, dp -> ftd_source = EREF_IFSU;
1025: dp -> ftd_delay = DIAG_NODELAY;
1026: (void) strcpy (dp -> ftd_data, "02bad storage account");
1027: dp -> ftd_cc = strlen (dp -> ftd_data);
1028: dp++;
1029:
1030: result = NOTOK;
1031: }
1032:
1033: if ((present & FA_FILESIZE) && fa -> fa_filesize < 0) {
1034: dp -> ftd_type = DIAG_PERM;
1035: dp -> ftd_identifier = id;
1036: dp -> ftd_observer = EREF_RFSU, dp -> ftd_source = EREF_IFSU;
1037: dp -> ftd_delay = DIAG_NODELAY;
1038: (void) strcpy (dp -> ftd_data, "13bad filesize");
1039: dp -> ftd_cc = strlen (dp -> ftd_data);
1040: dp++;
1041:
1042: result = NOTOK;
1043: }
1044: #endif
1045:
1046: *diags = dp;
1047: return result;
1048: }
1049:
1050: /* */
1051:
1052: int readattrs (attrnames, fa, proposed, parameter, file, st, diags)
1053: int attrnames;
1054: register struct FTAMattributes *fa;
1055: OID proposed;
1056: PE parameter;
1057: char *file;
1058: struct stat *st;
1059: register struct FTAMdiagnostic **diags;
1060: {
1061: #ifndef BRIDGE
1062: int result;
1063: char *cp;
1064: register struct tm *tm;
1065: #endif
1066: register struct FTAMdiagnostic *dp = *diags;
1067:
1068: fa -> fa_present = attrnames;
1069: fa -> fa_novalue = attrnames & (FA_SECURITY | FA_PRIVATE);
1070:
1071: if (attrnames & FA_FILENAME) {
1072: fa -> fa_nfile = 0;
1073: fa -> fa_files[fa -> fa_nfile++] = file;
1074: }
1075:
1076: if (attrnames & FA_ACTIONS) {
1077: fa -> fa_permitted = 0;
1078: #ifndef BRIDGE
1079: if (EACCESS (file, R_OK) != NOTOK)
1080: #endif
1081: fa -> fa_permitted |= FA_PERM_READ;
1082:
1083: #ifndef BRIDGE
1084: if (EACCESS (file, W_OK) != NOTOK)
1085: #endif
1086: fa -> fa_permitted |= FA_PERM_WRITE;
1087:
1088: if (fa -> fa_permitted & (FA_PERM_READ | FA_PERM_WRITE))
1089: fa -> fa_permitted |= FA_PERM_TRAVERSAL;
1090:
1091: fa -> fa_permitted |= FA_PERM_READATTR;
1092:
1093: #ifndef BRIDGE
1094: if (myuid == st -> st_uid || myuid == 0)
1095: #endif
1096: fa -> fa_permitted |= FA_PERM_OWNER;
1097:
1098: #ifndef BRIDGE
1099: if (cp = rindex (file, '/')) {
1100: *cp = NULL;
1101: result = EACCESS (*file ? file : "/", W_OK);
1102: *cp = '/';
1103: }
1104: else
1105: result = EACCESS (".", W_OK);
1106: if (result != NOTOK)
1107: #endif
1108: fa -> fa_permitted |= FA_PERM_PARENT;
1109: }
1110:
1111: if (attrnames & FA_CONTENTS) {
1112: register struct vfsmap *vf;
1113:
1114: if (vf = st2vfs (myfd, file, st, proposed, ftamfd)) {
1115: fa -> fa_contents = vf -> vf_oid;
1116: if (proposed
1117: && oid_cmp (proposed, vf -> vf_oid) == 0
1118: && parameter
1119: && vf -> vf_number >= 0
1120: && vf -> vf_check) {
1121: caddr_t p = NULL;
1122:
1123: if (dec_f (vf -> vf_number, &_ZDOCS_mod, parameter, 1, NULLIP,
1124: NULLVP, &p) == NOTOK) {
1125: advise (LLOG_NOTICE, NULLCP,
1126: "unable to parse document type parameter: %s",
1127: PY_pepy);
1128: goto bad_param;
1129: }
1130: if ((*vf -> vf_check) (p, dp -> ftd_data) == NOTOK) {
1131: advise (LLOG_NOTICE, NULLCP,
1132: "unacceptable document type parameter: %s",
1133: dp -> ftd_data);
1134: goto bad_param;
1135: }
1136: fre_obj (p, _ZDOCS_mod.md_dtab[vf -> vf_number], &_ZDOCS_mod);
1137: fa -> fa_parameter = parameter;
1138: }
1139: bad_param: ;
1140:
1141: if (vf -> vf_parameter) {
1142: if (rdparam)
1143: pe_free (rdparam), rdparam = NULLPE;
1144:
1145: if (enc_f (vf -> vf_number, &_ZDOCS_mod, &rdparam, 1, 0,
1146: NULLCP, vf -> vf_parameter) == NOTOK) {
1147: advise (LLOG_EXCEPTIONS, NULLCP,
1148: "unable to build parameter: %s", PY_pepy);
1149: if (rdparam)
1150: pe_free (rdparam), rdparam = NULLPE;
1151: }
1152: fa -> fa_parameter = rdparam;
1153: }
1154: else
1155: fa -> fa_parameter = NULLPE;
1156: }
1157: else
1158: fa -> fa_present &= ~FA_CONTENTS;
1159: }
1160:
1161: #ifdef BRIDGE
1162: /* these values cannot be obtained from FTP */
1163: if (attrnames & FA_ACCOUNT)
1164: #else
1165: if ((attrnames & FA_ACCOUNT)
1166: && (fa -> fa_account = getgroup (st -> st_gid)) == NULL)
1167: #endif
1168: fa -> fa_present &= ~FA_ACCOUNT;
1169:
1170: if (attrnames & FA_DATE_CREATE)
1171: #ifndef BRIDGE
1172: if (tm = gmtime ((long *) &st -> st_mtime))
1173: tm2ut (tm, &fa -> fa_date_create);
1174: else
1175: #endif
1176: fa -> fa_novalue |= FA_DATE_CREATE;
1177:
1178: if (attrnames & FA_DATE_MODIFY)
1179: #ifndef BRIDGE
1180: if (tm = gmtime ((long *) &st -> st_mtime))
1181: tm2ut (tm, &fa -> fa_date_modify);
1182: else
1183: #endif
1184: fa -> fa_novalue |= FA_DATE_MODIFY;
1185:
1186: if (attrnames & FA_DATE_READ)
1187: #ifndef BRIDGE
1188: if (tm = gmtime ((long *) &st -> st_atime))
1189: tm2ut (tm, &fa -> fa_date_read);
1190: else
1191: #endif
1192: fa -> fa_novalue |= FA_DATE_READ;
1193:
1194: if (attrnames & FA_DATE_ATTR)
1195: #ifndef BRIDGE
1196: if (tm = gmtime ((long *) &st -> st_ctime))
1197: tm2ut (tm, &fa -> fa_date_attribute);
1198: else
1199: #endif
1200: fa -> fa_novalue |= FA_DATE_ATTR;
1201:
1202: #ifdef BRIDGE
1203: if (attrnames & FA_ID_CREATE)
1204: #else
1205: if ((attrnames & FA_ID_CREATE)
1206: && (fa -> fa_id_create = getuser (st -> st_uid)) == NULL)
1207: #endif
1208: fa -> fa_novalue |= FA_ID_CREATE;
1209:
1210: #ifdef BRIDGE
1211: if (attrnames & FA_ID_MODIFY)
1212: #else
1213: if ((attrnames & FA_ID_MODIFY)
1214: && ((st -> st_mode & 0022)
1215: || (fa -> fa_id_modify = getuser (st -> st_uid)) == NULL))
1216: #endif
1217: fa -> fa_novalue |= FA_ID_MODIFY;
1218:
1219: #ifdef BRIDGE
1220: if (attrnames & FA_ID_READ)
1221: #else
1222: if ((attrnames & FA_ID_READ)
1223: && ((st -> st_mode & 0044)
1224: || (fa -> fa_id_read = getuser (st -> st_uid)) == NULL))
1225: #endif
1226: fa -> fa_novalue |= FA_ID_READ;
1227:
1228: #ifdef BRIDGE
1229: if (attrnames & FA_ID_ATTR)
1230: #else
1231: if ((attrnames & FA_ID_ATTR)
1232: && ( (st -> st_mode & 0022)
1233: || (fa -> fa_id_attribute = getuser (st -> st_uid))
1234: == NULL))
1235: #endif
1236: fa -> fa_novalue |= FA_ID_ATTR;
1237:
1238: if (attrnames & FA_AVAILABILITY)
1239: fa -> fa_availability = FA_AVAIL_IMMED;
1240:
1241: if (attrnames & FA_FILESIZE)
1242: #ifdef BRIDGE
1243: fa -> fa_novalue |= FA_FILESIZE;
1244: #else
1245: fa -> fa_filesize = (int) st -> st_size;
1246: #endif
1247:
1248: if (attrnames & FA_FUTURESIZE)
1249: fa -> fa_novalue |= FA_FUTURESIZE;
1250:
1251: *diags = dp;
1252: return OK;
1253: }
1254:
1255: /* */
1256:
1257: static int chngattrs (present, fa, diags)
1258: long present;
1259: register struct FTAMattributes *fa;
1260: register struct FTAMdiagnostic **diags;
1261: {
1262: #ifndef BRIDGE
1263: int gid,
1264: result;
1265: #endif
1266: register struct FTAMdiagnostic *dp = *diags;
1267:
1268:
1269: #ifdef BRIDGE
1270: statok = 1;
1271: #else
1272: if ((myfd != NOTOK ? fstat (myfd, &myst) : stat (myfile, &myst))
1273: == NOTOK) {
1274: bad_system: ;
1275: (void) strcpy (dp -> ftd_data, sys_errname (errno));
1276: dp -> ftd_cc = strlen (dp -> ftd_data);
1277: goto no_change;
1278: }
1279: statok = 1;
1280: if (myuid != myst.st_uid && myuid != 0) {
1281: errno = EPERM;
1282: goto bad_system;
1283: }
1284: #endif
1285:
1286: #ifndef BRIDGE
1287: if ((present & FA_ACCOUNT)
1288: && (gid = findgid (fa -> fa_account)) != NOTOK) {
1289: #ifndef SYS5
1290: (void) seteuid (0);
1291: result = myfd != NOTOK ? fchown (myfd, -1, gid)
1292: : chown (myfile, -1, gid);
1293: (void) seteuid (myuid);
1294: #else
1295: result = chgrp (myfile, gid);
1296: #endif
1297:
1298: if (result == NOTOK) {
1299: (void) sprintf (dp -> ftd_data, "%s: %s", fa -> fa_account,
1300: sys_errname (errno));
1301: dp -> ftd_cc = strlen (dp -> ftd_data);
1302:
1303: no_change: ;
1304: dp -> ftd_type = DIAG_PERM;
1305: dp -> ftd_identifier = FS_MGT_CHANGE;
1306: dp -> ftd_observer = dp -> ftd_source = EREF_RFSU;
1307: dp -> ftd_delay = DIAG_NODELAY;
1308: dp++;
1309:
1310: *diags = dp;
1311: return NOTOK;
1312: }
1313:
1314: myst.st_gid = gid;
1315: }
1316: #endif
1317:
1318: if (present & FA_FILENAME) {
1319: #ifdef BRIDGE
1320: if (ftp_rename (myfile, mvfile) == NOTOK) {
1321: (void) sprintf (dp -> ftd_data, "%s: %s", fa -> fa_files[0],
1322: ftp_error);
1323: #else
1324: if (rename (myfile, mvfile) == NOTOK) { /* on EXDEV could do gonzo
1325: copy, but why bother? */
1326: (void) sprintf (dp -> ftd_data, "%s: %s", fa -> fa_files[0],
1327: sys_errname (errno));
1328: #endif
1329: dp -> ftd_cc = strlen (dp -> ftd_data);
1330: #ifndef BRIDGE
1331: goto no_change;
1332: #else
1333: dp -> ftd_type = DIAG_PERM;
1334: dp -> ftd_identifier = FS_MGT_CHANGE;
1335: dp -> ftd_observer = dp -> ftd_source = EREF_RFSU;
1336: dp -> ftd_delay = DIAG_NODELAY;
1337: dp++;
1338:
1339: *diags = dp;
1340: return NOTOK;
1341: #endif
1342: }
1343: advise (LLOG_NOTICE, NULLCP, "rename %s to %s", myfile, mvfile);
1344:
1345: myfile = mvfile;
1346: }
1347:
1348: *diags = dp;
1349: return OK;
1350: }
1351:
1352: /* */
1353:
1354: static char *getfile (file)
1355: char *file;
1356: {
1357: register char *bp;
1358: #ifndef BRIDGE
1359: register char *cp,
1360: *pp;
1361: register struct passwd *pw;
1362: #endif
1363: static int i = 0;
1364: static char buffer1[MAXPATHLEN],
1365: buffer2[MAXPATHLEN];
1366:
1367: bp = (i++ % 2) ? buffer1 : buffer2;
1368:
1369: #ifndef BRIDGE
1370: switch (*file) {
1371: case '/':
1372: if (strlen (file) >= MAXPATHLEN)
1373: goto trunc;
1374:
1375: (void) strcpy (bp, file);
1376: break;
1377:
1378: case '~':
1379: if (cp = index (pp = file + 1, '/'))
1380: *cp = NULL;
1381:
1382: if (*pp == NULL)
1383: pp = myhome;
1384: else {
1385: if ((pw = getpwnam (pp)) == NULL)
1386: return NULL;
1387: else
1388: pp = pw -> pw_dir;
1389: }
1390:
1391: if (strlen (pp) + 1 + (cp ? strlen (cp) : 0) >= MAXPATHLEN)
1392: goto trunc;
1393:
1394: (void) sprintf (bp, "%s/%s", pp, cp ? cp + 1 : "");
1395: if (cp)
1396: *cp = '/';
1397: break;
1398:
1399: default:
1400: if (strlen (file) + myhomelen + 1 >= MAXPATHLEN)
1401: goto trunc;
1402:
1403: (void) sprintf (bp, "%s/%s", myhome, file);
1404: break;
1405: }
1406:
1407: compath (bp);
1408:
1409: #ifndef apollo /* always return RELATIVE pathnames */
1410: if (strncmp (bp, myhome, myhomelen - 1) == 0)
1411: switch (bp[myhomelen - 1]) {
1412: case NULL:
1413: (void) strcpy (bp, ".");
1414: break;
1415:
1416: case '/':
1417: bp += myhomelen;
1418: break;
1419:
1420: default:
1421: break;
1422: }
1423: #endif
1424:
1425: return bp;
1426:
1427: trunc: ;
1428: errno = 0;
1429: return NULLCP;
1430: #else
1431: (void) strcpy (bp, file);
1432: return bp;
1433: #endif
1434: }
1435:
1436: /* */
1437:
1438: #ifndef BRIDGE
1439: /* originally used algorithms similar to those in /bin/ls; Don Preuss of
1440: Apollo suggested these algorithms as they work better with distributed
1441: /etc/passwd and /etc/group files */
1442:
1443: static char *getuser (uid)
1444: int uid;
1445: {
1446: static struct passwd *pw = NULL;
1447:
1448: if (pw == NULL || pw -> pw_uid != uid)
1449: pw = getpwuid (uid);
1450: return (pw ? pw -> pw_name : NULL);
1451: }
1452:
1453: /* */
1454:
1455: static char *getgroup (gid)
1456: int gid;
1457: {
1458: register struct group *gr;
1459: static int my_gid = -1;
1460: static char my_name[NMAX + 1];
1461:
1462: if (my_gid != gid) {
1463: if ((gr = getgrgid (gid)) == NULL)
1464: return NULL;
1465:
1466: my_gid = gr -> gr_gid;
1467: (void) strcpy (my_name, gr -> gr_name);
1468: }
1469:
1470: return my_name;
1471: }
1472:
1473: /* */
1474:
1475: int findgid (group)
1476: char *group;
1477: {
1478: int i;
1479: #ifdef BSD42
1480: int gidset[NGROUPS];
1481: #endif
1482: register struct group *gr;
1483: static int my_gid = -1;
1484: static char my_name[NMAX + 1] = "";
1485:
1486: if (*group == NULL)
1487: return NOTOK;
1488:
1489: if (strcmp (my_name, group) != 0) {
1490: if ((gr = getgrnam (group)) == NULL)
1491: return NOTOK;
1492:
1493: #ifdef BSD42
1494: for (i = getgroups (NGROUPS, gidset) - 1; i >= 0; i--)
1495: if (gr -> gr_gid == gidset[i])
1496: break;
1497: if (i < 0)
1498: return NOTOK;
1499: #endif
1500:
1501: (void) strcpy (my_name, gr -> gr_name);
1502: my_gid = gr -> gr_gid;
1503: }
1504:
1505: return my_gid;
1506: }
1507: #endif
1508:
1509: /* */
1510:
1511: #ifndef SYS5
1512: #ifndef BRIDGE
1513: static int EACCESS (file, mode)
1514: char *file;
1515: int mode;
1516: {
1517: int result;
1518:
1519: (void) seteuid (0);
1520: (void) setruid (myuid);
1521:
1522: result = access (file, mode);
1523:
1524: (void) setruid (0);
1525: (void) seteuid (myuid);
1526:
1527: return result;
1528: }
1529: #endif
1530: #else
1531:
1532: /* */
1533:
1534: static int chgrp (file, gid)
1535: char *file;
1536: int gid;
1537: {
1538: int i,
1539: pid,
1540: status;
1541: char group[10];
1542: struct stat st;
1543:
1544: (void) sprintf (group, "%d", gid);
1545:
1546: switch (pid = fork ()) {
1547: case NOTOK:
1548: return NOTOK;
1549:
1550: case OK:
1551: execl ("/bin/chgrp", "chgrp", group, file, NULLCP);
1552: execl ("/usr/bin/chgrp", "chgrp", group, file, NULLCP);
1553: execl ("/etc/chgrp", "chgrp", group, file, NULLCP);
1554: _exit (NOTOK);
1555:
1556: default:
1557: while ((i = wait (&status)) != NOTOK && pid != i)
1558: continue;
1559: if (i != NOTOK && status) {
1560: if (stat (file, &st) == NOTOK || st.st_gid != gid) {
1561: i = NOTOK;
1562: errno = EACCES;
1563: }
1564: else
1565: status = OK;
1566: }
1567: return (i == NOTOK ? NOTOK : status);
1568: }
1569: }
1570:
1571: /* */
1572:
1573: static int mkdir (dir, mode)
1574: char *dir;
1575: int mode;
1576: {
1577: int i,
1578: pid,
1579: status;
1580: struct stat st;
1581:
1582: switch (pid = fork ()) {
1583: case NOTOK:
1584: return NOTOK;
1585:
1586: case OK:
1587: (void) umask (~mode);
1588: execl ("/bin/mkdir", "mkdir", dir, NULLCP);
1589: execl ("/usr/bin/mkdir", "mkdir", dir, NULLCP);
1590: execl ("/etc/mkdir", "mkdir", dir, NULLCP);
1591: _exit (NOTOK);
1592:
1593: default:
1594: while ((i = wait (&status)) != NOTOK && pid != i)
1595: continue;
1596: if (i != NOTOK && status) {
1597: if (stat (dir, &st) == NOTOK
1598: || (st.st_mode & S_IFMT) != S_IFDIR) {
1599: i = NOTOK;
1600: errno = EACCES;
1601: }
1602: else
1603: status = OK;
1604: }
1605: return (i == NOTOK ? NOTOK : status);
1606: }
1607: }
1608:
1609: /* */
1610:
1611: static int rmdir (dir)
1612: char *dir;
1613: {
1614: int i,
1615: pid,
1616: status;
1617:
1618: switch (pid = fork ()) {
1619: case NOTOK:
1620: return NOTOK;
1621:
1622: case OK:
1623: execl ("/bin/rmdir", "rmdir", dir, NULLCP);
1624: execl ("/usr/bin/rmdir", "rmdir", dir, NULLCP);
1625: execl ("/etc/rmdir", "rmdir", dir, NULLCP);
1626: _exit (NOTOK);
1627:
1628: default:
1629: while ((i = wait (&status)) != NOTOK && pid != i)
1630: continue;
1631: if (i != NOTOK && status) {
1632: if (access (dir, 0x00) != NOTOK) {
1633: i = NOTOK;
1634: errno = EACCES;
1635: }
1636: else
1637: status = OK;
1638: }
1639: return (i == NOTOK ? NOTOK : status);
1640: }
1641: }
1642:
1643: /* */
1644:
1645: static int truncate (file, length)
1646: char *file;
1647: int length;
1648: {
1649: int fd;
1650:
1651: if (length != 0) { /* XXX: too much work to get right */
1652: errno = EINVAL;
1653: return NOTOK;
1654: }
1655:
1656: if ((fd = open (file, O_WRONLY | O_TRUNC)) == NOTOK)
1657: return NOTOK;
1658:
1659: (void) close (fd);
1660: return OK;
1661: }
1662:
1663:
1664: /* ARGSUSED */
1665:
1666: int ftruncate (fd, length) /* works only 'cause we're lucky */
1667: int fd,
1668: length;
1669: {
1670: return truncate (myfile, length);
1671: }
1672: #endif
1673:
1674: /* DEBUG */
1675:
1676: #if defined(FTAMDEBUG) && defined(BSD42)
1677: #include <syscall.h>
1678:
1679:
1680: static int unlink (file)
1681: char *file;
1682: {
1683: if (debug) {
1684: int i,
1685: b;
1686:
1687: again: ;
1688: fprintf (stderr, "unlink(\"%s\")? y, w, l: ", file);
1689:
1690: i = b = getchar ();
1691: while (b != '\n' && b != EOF)
1692: b = getchar ();
1693:
1694: switch (i) {
1695: case 'y':
1696: break;
1697:
1698: case 'w':
1699: return OK;
1700:
1701: case 'l':
1702: return NOTOK;
1703:
1704: default:
1705: goto again;
1706: }
1707: }
1708:
1709: return syscall (SYS_unlink, file);
1710: }
1711:
1712:
1713: static int rmdir (dir)
1714: char *dir;
1715: {
1716: if (debug) {
1717: int i,
1718: b;
1719:
1720: again: ;
1721: fprintf (stderr, "rmdir(\"%s\")? y, w, l: ", dir);
1722:
1723: i = b = getchar ();
1724: while (b != '\n' && b != EOF)
1725: b = getchar ();
1726:
1727: switch (i) {
1728: case 'y':
1729: break;
1730:
1731: case 'w':
1732: return OK;
1733:
1734: case 'l':
1735: return NOTOK;
1736:
1737: default:
1738: goto again;
1739: }
1740: }
1741:
1742: return syscall (SYS_rmdir, dir);
1743: }
1744:
1745:
1746: /* VARARGS2 */
1747:
1748: static int open (file, flags, mode)
1749: char *file;
1750: int flags,
1751: mode;
1752: {
1753: if (debug) {
1754: int i,
1755: b;
1756:
1757: again: ;
1758: fprintf (stderr, "open(\"%s\",0x%x,0%o)? y, l: ", file, flags,
1759: (flags & O_CREAT) ? mode : 0);
1760:
1761: i = b = getchar ();
1762: while (b != '\n' && b != EOF)
1763: b = getchar ();
1764:
1765: switch (i) {
1766: case 'y':
1767: break;
1768:
1769: case 'l':
1770: return NOTOK;
1771:
1772: default:
1773: goto again;
1774: }
1775: }
1776:
1777: return syscall (SYS_open, file, flags, mode);
1778: }
1779:
1780:
1781: static int mkdir (dir, mode)
1782: char *dir;
1783: int mode;
1784: {
1785: if (debug) {
1786: int i,
1787: b;
1788:
1789: again: ;
1790: fprintf (stderr, "mkdir(\"%s\",0%o)? y, w, l: ", dir, mode);
1791:
1792: i = b = getchar ();
1793: while (b != '\n' && b != EOF)
1794: b = getchar ();
1795:
1796: switch (i) {
1797: case 'y':
1798: break;
1799:
1800: case 'w':
1801: return OK;
1802:
1803: case 'l':
1804: return NOTOK;
1805:
1806: default:
1807: goto again;
1808: }
1809: }
1810:
1811: return syscall (SYS_mkdir, dir, mode);
1812: }
1813:
1814:
1815: static int chown (file, uid, gid)
1816: char *file;
1817: int uid,
1818: gid;
1819: {
1820: if (debug) {
1821: int i,
1822: b;
1823:
1824: again: ;
1825: fprintf (stderr, "chown(\"%s\",%d,%d)? y, w, l: ", file, uid, gid);
1826:
1827: i = b = getchar ();
1828: while (b != '\n' && b != EOF)
1829: b = getchar ();
1830:
1831: switch (i) {
1832: case 'y':
1833: break;
1834:
1835: case 'w':
1836: return OK;
1837:
1838: case 'l':
1839: return NOTOK;
1840:
1841: default:
1842: goto again;
1843: }
1844: }
1845:
1846: return syscall (SYS_chown, file, uid, gid);
1847: }
1848:
1849:
1850: static int fchown (fd, uid, gid)
1851: int fd;
1852: int uid,
1853: gid;
1854: {
1855: if (debug) {
1856: int i,
1857: b;
1858:
1859: again: ;
1860: fprintf (stderr, "fchown(%d,%d,%d)? y, w, l: ", fd, uid, gid);
1861:
1862: i = b = getchar ();
1863: while (b != '\n' && b != EOF)
1864: b = getchar ();
1865:
1866: switch (i) {
1867: case 'y':
1868: break;
1869:
1870: case 'w':
1871: return OK;
1872:
1873: case 'l':
1874: return NOTOK;
1875:
1876: default:
1877: goto again;
1878: }
1879: }
1880:
1881: return syscall (SYS_fchown, fd, uid, gid);
1882: }
1883:
1884:
1885: static int truncate (file, length)
1886: char *file;
1887: int length;
1888: {
1889: if (debug) {
1890: int i,
1891: b;
1892:
1893: again: ;
1894: fprintf (stderr, "truncate(\"%s\",%d)? y, w, l: ", file, length);
1895:
1896: i = b = getchar ();
1897: while (b != '\n' && b != EOF)
1898: b = getchar ();
1899:
1900: switch (i) {
1901: case 'y':
1902: break;
1903:
1904: case 'w':
1905: return OK;
1906:
1907: case 'l':
1908: return NOTOK;
1909:
1910: default:
1911: goto again;
1912: }
1913: }
1914:
1915: return syscall (SYS_truncate, file, length);
1916: }
1917:
1918:
1919: static int rename (old, new)
1920: char *old;
1921: char *new;
1922: {
1923: if (debug) {
1924: int i,
1925: b;
1926:
1927: again: ;
1928: fprintf (stderr, "rename(\"%s\",\"%s\")? y, w, l: ", old, new);
1929:
1930: i = b = getchar ();
1931: while (b != '\n' && b != EOF)
1932: b = getchar ();
1933:
1934: switch (i) {
1935: case 'y':
1936: break;
1937:
1938: case 'w':
1939: return OK;
1940:
1941: case 'l':
1942: return NOTOK;
1943:
1944: default:
1945: goto again;
1946: }
1947: }
1948:
1949: return syscall (SYS_rename, old, new);
1950: }
1951:
1952:
1953: static int flock (fd, operation)
1954: int fd,
1955: operation;
1956: {
1957: if (debug) {
1958: int i,
1959: b;
1960:
1961: again: ;
1962: fprintf (stderr, "flock(%d,0x%x)? y, w, l: ", fd, operation);
1963:
1964: i = b = getchar ();
1965: while (b != '\n' && b != EOF)
1966: b = getchar ();
1967:
1968: switch (i) {
1969: case 'y':
1970: break;
1971:
1972: case 'w':
1973: return OK;
1974:
1975: case 'l':
1976: return NOTOK;
1977:
1978: default:
1979: goto again;
1980: }
1981: }
1982:
1983: return syscall (SYS_flock, fd, operation);
1984: }
1985: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.