vsta

Check-in [e2e9f5f71e]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add support for preallocating contiguous files. Fix exposure to invalid arguments in stat(). Add info on file allocation so we can determine sector address of a given file from stat() results.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | master | trunk
Files: files | file ages | folders
SHA3-256:e2e9f5f71eb69c01a6e22a27316e4997088e771fb5e88187693f1ab6441d2c89
User & Date: vandys 2001-12-18 10:06:54
Context
2001-12-19
13:26
Add dirname(1) check-in: 879326aa9d user: vandys tags: master, trunk
2001-12-18
10:06
Add support for preallocating contiguous files. Fix exposure to invalid arguments in stat(). Add info on file allocation so we can determine sector address of a given file from stat() results. check-in: e2e9f5f71e user: vandys tags: master, trunk
2001-12-17
14:00
Fix up some old edge cases in the stat() support code. check-in: 1e2cf28f7c user: vandys tags: master, trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to vsta/src/srv/dos/dos.h.

238
239
240
241
242
243
244
245

246
247
248
249
250
251
252
...
262
263
264
265
266
267
268
269

270
271
272
273
274
275
276
/*
 * Cluster handling routines
 */
extern void clust_init(void);
extern struct clust *alloc_clust(struct directory *);
extern void free_clust(struct clust *);
extern void fat_sync(void);
extern int clust_setlen(struct clust *, ulong);

extern claddr_t get_clust(struct clust *, uint);

/*
 * Other routines
 */
extern int valid_fname(char *, int);
extern struct node *dir_look(struct node *, char *),
................................................................................
	dos_rename(struct msg *, struct file *),
	cancel_rename(struct file *),
	dos_read(struct msg *, struct file *),
	dos_write(struct msg *, struct file *),
	dos_remove(struct msg *, struct file *),
	dos_stat(struct msg *, struct file *),
	dos_wstat(struct msg *, struct file *),
	dos_fid(struct msg *, struct file *);

extern void timestamp(struct directory *, time_t),
	dir_timestamp(struct node *, time_t);
extern int dir_set_type(struct file *, char *);
extern void dir_readonly(struct file *f, int);
extern ulong inum(struct node *);
extern void do_unhash(ulong);
extern int assemble_vfat_name(char *name, struct directory *d,







|
>







 







|
>







238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
...
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
/*
 * Cluster handling routines
 */
extern void clust_init(void);
extern struct clust *alloc_clust(struct directory *);
extern void free_clust(struct clust *);
extern void fat_sync(void);
extern int clust_setlen(struct clust *, ulong),
	clust_prealloc(struct clust *, ulong);
extern claddr_t get_clust(struct clust *, uint);

/*
 * Other routines
 */
extern int valid_fname(char *, int);
extern struct node *dir_look(struct node *, char *),
................................................................................
	dos_rename(struct msg *, struct file *),
	cancel_rename(struct file *),
	dos_read(struct msg *, struct file *),
	dos_write(struct msg *, struct file *),
	dos_remove(struct msg *, struct file *),
	dos_stat(struct msg *, struct file *),
	dos_wstat(struct msg *, struct file *),
	dos_fid(struct msg *, struct file *),
	dos_prealloc(struct msg *, struct file *, ulong);
extern void timestamp(struct directory *, time_t),
	dir_timestamp(struct node *, time_t);
extern int dir_set_type(struct file *, char *);
extern void dir_readonly(struct file *f, int);
extern ulong inum(struct node *);
extern void do_unhash(ulong);
extern int assemble_vfat_name(char *name, struct directory *d,

Changes to vsta/src/srv/dos/fat.c.

205
206
207
208
209
210
211























 */
claddr_t
get_clust(struct clust *c, uint idx)
{
	ASSERT_DEBUG(c->c_nclust > idx, "get_clust: bad index");
	return(c->c_clust[idx]);
}






























>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
 */
claddr_t
get_clust(struct clust *c, uint idx)
{
	ASSERT_DEBUG(c->c_nclust > idx, "get_clust: bad index");
	return(c->c_clust[idx]);
}

/*
 * prealloc()
 *	Allocate contiguous disk storage to a file
 *
 * Returns 0 on success, 1 on failure.
 */
int
clust_prealloc(struct clust *c, ulong newlen)
{
	ulong newclust = roundup(newlen, clsize) / clsize;

	/* Can't have any existing space allocated */
	ASSERT_DEBUG(c->c_nclust == 0, "clust_prealloc: nclust > 0");

	/* Make sure the FAT layer supports it */
	if (!fatops->prealloc) {
		return(1);
	}

	/* Vector out to the FAT layer */
	return(fatops->prealloc(c, newclust));
}

Changes to vsta/src/srv/dos/fat.h.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27
 */
struct fatops {
	void (*init)(void);			/* Initialize */
	int (*setlen)(struct clust *, uint);	/* Set length */
	struct clust *((*alloc)			/* Allocate new */
		(struct clust *, struct directory *));
	void (*sync)(void);			/* Flush to disk */

};

/*
 * Shared variabls among different FAT implementations
 */
extern int fat_dirty;		/* A change has occurred in the FAT */
extern uint fat_size;		/* FAT format (12, 16, or 32) */
extern uint nclust;		/* # clusters in filesystem */

#endif /* FAT_H */







>










11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 */
struct fatops {
	void (*init)(void);			/* Initialize */
	int (*setlen)(struct clust *, uint);	/* Set length */
	struct clust *((*alloc)			/* Allocate new */
		(struct clust *, struct directory *));
	void (*sync)(void);			/* Flush to disk */
	int (*prealloc)(struct clust *, uint);	/* Allocate contiguous */
};

/*
 * Shared variabls among different FAT implementations
 */
extern int fat_dirty;		/* A change has occurred in the FAT */
extern uint fat_size;		/* FAT format (12, 16, or 32) */
extern uint nclust;		/* # clusters in filesystem */

#endif /* FAT_H */

Changes to vsta/src/srv/dos/fat12.c.

370
371
372
373
374
375
376
377

378
/*
 * Our registered vectors
 */
struct fatops fat12ops = {
	fat12_init,
	fat12_setlen,
	fat12_alloc,
	fat12_sync

};







|
>

370
371
372
373
374
375
376
377
378
379
/*
 * Our registered vectors
 */
struct fatops fat12ops = {
	fat12_init,
	fat12_setlen,
	fat12_alloc,
	fat12_sync,
	NULL
};

Changes to vsta/src/srv/dos/fat16.c.

320
321
322
323
324
325
326
327

328
/*
 * Our registered vectors
 */
struct fatops fat16ops = {
	fat16_init,
	fat16_setlen,
	fat16_alloc,
	fat16_sync

};







|
>

320
321
322
323
324
325
326
327
328
329
/*
 * Our registered vectors
 */
struct fatops fat16ops = {
	fat16_init,
	fat16_setlen,
	fat16_alloc,
	fat16_sync,
	NULL
};

Changes to vsta/src/srv/dos/fat32.c.

501
502
503
504
505
506
507
508
509



























































































510
511
512
513
514
515
516

517
		lseek(blkdev, infobase * SECSZ, 0);
		if (write(blkdev, info, infosize) != infosize) {
			syslog(LOG_ERR, "write of info sector failed");
			exit(1);
		}
	}
}

/*



























































































 * Our registered vectors
 */
struct fatops fat32ops = {
	fat32_init,
	fat32_setlen,
	fat32_alloc,
	fat32_sync

};









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






|
>

501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
		lseek(blkdev, infobase * SECSZ, 0);
		if (write(blkdev, info, infosize) != infosize) {
			syslog(LOG_ERR, "write of info sector failed");
			exit(1);
		}
	}
}

/*
 * fat32_prealloc()
 *	Allocate contiguous blocks
 *
 * Returns 0 if it could be done; 1 if it failed.
 */
static int
fat32_prealloc(struct clust *c, uint newclust)
{
	uint clust_cnt, x;
	claddr_t cl, cl2, *ctmp;

	/*
	 * Scan for a contiguous run of blocks which satisfy
	 * the requested amount.
	 */
	clust_cnt = 0;
	for (cl = 0; cl < nclust; ++cl) {
		/* Allocated... continue scan */
		if (get(cl)) {
			continue;
		}

		/* See if there's enough starting from here */
		cl2 = cl;
		clust_cnt = 0;
		for (cl2 = cl; cl2 < nclust; ++cl2) {
			if (get(cl2)) {
				cl = cl2;
				break;
			}
			if (++clust_cnt >= newclust) {
				break;
			}
		}

		/* End loop if we found a sufficient run here */
		if (clust_cnt >= newclust) {
			break;
		}
	}

	/*
	 * If we couldn't find it, return failure
	 */
	if (clust_cnt < newclust) {
		return(1);
	}

	/*
	 * Get the cluster list to hold these blocks
	 */
	ctmp = malloc(newclust * sizeof(claddr_t));
	if (ctmp == NULL) {
		return(1);
	}

	/*
	 * Fill in list of cluster numbers and mark FAT entries consumed
	 */
	for (x = 0; x < newclust; ++x) {
		cl2 = ctmp[x] = cl + x;

		/*
		 * All but the last points to the next one up.  The
		 * last flags EOF.
		 */
		if (x < newclust-1) {
			set(cl2, cl2 + 1);
		} else {
			set(cl2, FAT_EOF);
		}
	}

	/*
	 * Attach to the cluster struct
	 */
	c->c_clust = ctmp;
	c->c_nclust = newclust;

	/*
	 * Update the free list count
	 */
	if (info) {
		info->free -= newclust;
	}

	fat_dirty = 1;
	return(0);
}

/*
 * Our registered vectors
 */
struct fatops fat32ops = {
	fat32_init,
	fat32_setlen,
	fat32_alloc,
	fat32_sync,
	fat32_prealloc
};

Changes to vsta/src/srv/dos/makefile.

1
2
3
4
5
6
7
8
9
10
11
12
13
COPTS=-Wall -DDEBUG
OBJS=main.o fat.o node.o dir.o open.o rw.o stat.o fat16.o fat12.o fat32.o
OUT=dos

include ../../makefile.all

dos: $(OBJS)
	rm -f dos
	$(LD) $(LDFLAGS) -o dos $(CRT0SRV) $(OBJS) -lsrv

install: all
	strip dos
	cp dos $(ROOT)/boot
|












1
2
3
4
5
6
7
8
9
10
11
12
13
COPTS=-Wall -DDEBUG -g
OBJS=main.o fat.o node.o dir.o open.o rw.o stat.o fat16.o fat12.o fat32.o
OUT=dos

include ../../makefile.all

dos: $(OBJS)
	rm -f dos
	$(LD) $(LDFLAGS) -o dos $(CRT0SRV) $(OBJS) -lsrv

install: all
	strip dos
	cp dos $(ROOT)/boot

Changes to vsta/src/srv/dos/rw.c.

144
145
146
147
148
149
150















































151
152
153
154
155
156
157
		return;
	}
	m->m_arg = m->m_buflen;
	f->f_pos += m->m_buflen;
	m->m_buflen = m->m_arg1 = m->m_nseg = 0;
	msg_reply(m->m_sender, m);
}
















































/*
 * pack_name()
 *	Pack a DOS name into a UNIX-ish format
 */
void
pack_name(struct directory *d, char *file)







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
		return;
	}
	m->m_arg = m->m_buflen;
	f->f_pos += m->m_buflen;
	m->m_buflen = m->m_arg1 = m->m_nseg = 0;
	msg_reply(m->m_sender, m);
}

/*
 * dos_prealloc()
 *	Preallocate contiguous storage to file
 *
 * Note that this routine is invoked in response to a wstat().
 */
void
dos_prealloc(struct msg *m, struct file *f, ulong newsize)
{
	struct node *n = f->f_node;

	/*
	 * Can only change files, and only if open for writing
	 */
	if ((n->n_type == T_DIR) || !(f->f_perm & ACC_WRITE)) {
		msg_err(m->m_sender, EPERM);
		return;
	}

	/*
	 * Must be zero length until now
	 */
	if (n->n_len > 0) {
		msg_err(m->m_sender, EBUSY);
		return;
	}

	/*
	 * Try to get the clusters
	 */
	if (clust_prealloc(n->n_clust, newsize)) {
		msg_err(m->m_sender, ENOSPC);
		return;
	}

	/*
	 * It worked; update the file's state
	 */
	n->n_len = newsize;
	write_zero(n, 0, newsize);
	n->n_flags |= N_DIRTY;

	/* Return success */
	m->m_arg = m->m_arg1 = m->m_nseg = 0;
	msg_reply(m->m_sender, m);
}

/*
 * pack_name()
 *	Pack a DOS name into a UNIX-ish format
 */
void
pack_name(struct directory *d, char *file)

Changes to vsta/src/srv/dos/stat.c.

174
175
176
177
178
179
180
181

182
183
184
185
186
187
188
...
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
...
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304



305
306
307
308
309
310
311
	 * No dir entry for root, otherwise get a copy of it
	 */
	bzero(&d, sizeof(d));
	if (n != procroot) {
		(void)dir_copy(n->n_dir, n->n_slot, &d);
		p = result;
	} else {
		sprintf(result, "clsize=%d\n", CLSIZE);

		p = result + strlen(result);
	}
	sprintf(p,
"perm=1/1\nacc=%s\ntype=%c\nsize=%lu\nowner=0\ninode=%lu\n"
"mtime=%lu\nshortname=%s\nstart=%u\n",
		dos_acc(&d),
		(isdir ? 'd' : 'f'),
................................................................................
 *
 * We support setting of modification time only, plus the usual
 * shared code to set access to the filesystem.
 */
void
dos_wstat(struct msg *m, struct file *f)
{
	char *field, *val;
	struct prot *prot, tmp_prot;
	struct node *n = f->f_node;
	int was_ro = 0;

	/*
	 * Use the root protection node for root dir, a private
	 * copy otherwise.
................................................................................
		 */
		if ((prot == &tmp_prot) &&
				(was_ro != accum_ro(prot))) {
			dir_readonly(f, !was_ro);
		}
		return;
	}
	if (!strcmp(field, "mtime")) {
		time_t t;

		/*
		 * Convert to number, write to dir entry
		 */
		t = atoi(val);
		dir_timestamp(n, t);
	} else if (!strcmp(field, "atime")) {
		/* Do nothing, but don't return an error */ ;
	} else if (!strcmp(field, "type")) {
		if (dir_set_type(f, val)) {
			msg_err(m->m_sender, EINVAL);
			return;
		}



	} else {
		/*
		 * Unsupported operation
		 */
		msg_err(m->m_sender, EINVAL);
		return;
	}







|
>







 







|







 







|









|




>
>
>







174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
...
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
...
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
	 * No dir entry for root, otherwise get a copy of it
	 */
	bzero(&d, sizeof(d));
	if (n != procroot) {
		(void)dir_copy(n->n_dir, n->n_slot, &d);
		p = result;
	} else {
		sprintf(result, "clsize=%d\ndata0=%lu\n",
			CLSIZE, data0);
		p = result + strlen(result);
	}
	sprintf(p,
"perm=1/1\nacc=%s\ntype=%c\nsize=%lu\nowner=0\ninode=%lu\n"
"mtime=%lu\nshortname=%s\nstart=%u\n",
		dos_acc(&d),
		(isdir ? 'd' : 'f'),
................................................................................
 *
 * We support setting of modification time only, plus the usual
 * shared code to set access to the filesystem.
 */
void
dos_wstat(struct msg *m, struct file *f)
{
	char *field, *val = NULL;
	struct prot *prot, tmp_prot;
	struct node *n = f->f_node;
	int was_ro = 0;

	/*
	 * Use the root protection node for root dir, a private
	 * copy otherwise.
................................................................................
		 */
		if ((prot == &tmp_prot) &&
				(was_ro != accum_ro(prot))) {
			dir_readonly(f, !was_ro);
		}
		return;
	}
	if (!strcmp(field, "mtime") && val) {
		time_t t;

		/*
		 * Convert to number, write to dir entry
		 */
		t = atoi(val);
		dir_timestamp(n, t);
	} else if (!strcmp(field, "atime")) {
		/* Do nothing, but don't return an error */ ;
	} else if (!strcmp(field, "type") && val) {
		if (dir_set_type(f, val)) {
			msg_err(m->m_sender, EINVAL);
			return;
		}
	} else if (!strcmp(field, "contig") && val) {
		ulong sz = atoi(val);
		dos_prealloc(m, f, sz);
	} else {
		/*
		 * Unsupported operation
		 */
		msg_err(m->m_sender, EINVAL);
		return;
	}