|
|
1.1 root 1: /*
2: * Copyright (c) 1995-1994 The University of Utah and
3: * the Computer Systems Laboratory at the University of Utah (CSL).
4: * All rights reserved.
5: *
6: * Permission to use, copy, modify and distribute this software is hereby
7: * granted provided that (1) source code retains these copyright, permission,
8: * and disclaimer notices, and (2) redistributions including binaries
9: * reproduce the notices in supporting documentation, and (3) all advertising
10: * materials mentioning features or use of this software display the following
11: * acknowledgement: ``This product includes software developed by the
12: * Computer Systems Laboratory at the University of Utah.''
13: *
14: * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
15: * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
16: * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17: *
18: * CSL requests users of this software to return to [email protected] any
19: * improvements that they make and grant CSL redistribution rights.
20: *
21: * Author: Bryan Ford, University of Utah CSL
22: */
23:
24: #include <sys/types.h>
25: #include <sys/stat.h>
26: #include <fcntl.h>
27: #include <stdio.h>
28: #include <errno.h>
29:
30: #include "dos_io.h"
31: #include "vm_param.h"
32: #include "debug.h"
33:
34: int dos_open(const char *s, int flags, int mode, dos_fd_t *out_fh)
35: {
36: struct real_call_data real_call_data;
37: int err = EINVAL; /*XXX*/
38: vm_offset_t dos_buf_phys = (vm_offset_t)kvtophys(dos_buf);
39:
40: assert(dos_buf); assert(dos_buf_phys);
41: assert(dos_buf_phys < 0x100000);
42:
43: dos_init_rcd(&real_call_data);
44:
45: if (strlen(s)+1 > DOS_BUF_SIZE)
46: return E2BIG;
47: strcpy(dos_buf, s);
48: real_call_data.ds = dos_buf_phys >> 4;
49: real_call_data.edx = dos_buf_phys & 15;
50:
51: /* Possible situations:
52:
53: - 3d
54: C 3d || 3c
55: T 3d (ensure that it exists), close, 3c
56: CT 3c
57: X 3d
58: C X 3d (ensure that it doesn't exist), 3c
59: TX 3d (ensure that it exists), close, 3c
60: CTX 3d (ensure that it doesn't exist), 3c
61: */
62:
63: if ((flags & (O_CREAT | O_EXCL | O_TRUNC)) != (O_CREAT | O_TRUNC))
64: {
65: /* First try opening the file with function 0x3D. */
66: real_call_data.eax = 0x3d40 | (flags & O_ACCMODE);
67: real_call_data.ecx = 0;
68: real_int(0x21, &real_call_data);
69: err = dos_check_err(&real_call_data);
70: if (!err)
71: *out_fh = real_call_data.eax & 0xffff;
72: }
73:
74: /* Now based on the result, determine what to do next. */
75: switch (flags & (O_CREAT | O_EXCL | O_TRUNC))
76: {
77: case 0:
78: case 0 | O_EXCL:
79: if (!err)
80: goto success;
81: else
82: return err;
83: case O_CREAT:
84: if (!err)
85: goto success;
86: else
87: break;
88: case O_CREAT | O_EXCL:
89: case O_CREAT | O_TRUNC | O_EXCL:
90: if (!err)
91: {
92: /* The file exists, but wasn't supposed to.
93: Close it and return an error. */
94: dos_close(real_call_data.eax & 0xffff);
95: return EEXIST;
96: }
97: else
98: break;
99: case O_TRUNC:
100: case O_TRUNC | O_EXCL:
101: if (!err)
102: {
103: /* We've verified that the file exists -
104: now close it and reopen it with CREAT
105: so it'll be truncated as requested. */
106: dos_close(real_call_data.eax & 0xffff);
107: break;
108: }
109: else
110: return err;
111: case O_CREAT | O_TRUNC:
112: /* This is the one case in which
113: we didn't try to open the file above at all.
114: Just fall on through and open it with CREAT. */
115: break;
116: }
117:
118: /* Now try opening the file with DOS's CREAT call,
119: which truncates the file if it already exists. */
120: real_call_data.eax = 0x3c00;
121: real_call_data.ecx = mode & S_IWUSR ? 0 : 1;
122: real_int(0x21, &real_call_data);
123: if (!(err = dos_check_err(&real_call_data)))
124: {
125: *out_fh = real_call_data.eax & 0xffff;
126:
127: /* We don't have to worry about O_APPEND here,
128: because we know the file starts out empty. */
129:
130: return 0;
131: }
132:
133: return err;
134:
135: success:
136:
137: /* If the caller requested append access,
138: just seek to the end of the file once on open.
139: We can't implement full POSIX behavior here without help,
140: since DOS file descriptors don't have an append mode.
141: To get full POSIX behavior,
142: the caller must seek to the end of the file before every write.
143: However, seeking to the end only on open
144: is probably enough for most typical uses. */
145: if (flags & O_APPEND)
146: {
147: vm_offset_t newpos;
148: err = dos_seek(*out_fh, 0, SEEK_END, &newpos);
149: if (err)
150: {
151: dos_close(*out_fh);
152: return err;
153: }
154: }
155:
156: return 0;
157: }
158:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.