Changeset View
Changeset View
Standalone View
Standalone View
stand/libsa/tftp.c
Show First 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | |||||
static ssize_t recvtftp(struct iodesc *, void **, void **, time_t, void *); | static ssize_t recvtftp(struct iodesc *, void **, void **, time_t, void *); | ||||
static int tftp_open(const char *, struct open_file *); | static int tftp_open(const char *, struct open_file *); | ||||
static int tftp_close(struct open_file *); | static int tftp_close(struct open_file *); | ||||
static int tftp_parse_oack(struct tftp_handle *, char *, size_t); | static int tftp_parse_oack(struct tftp_handle *, char *, size_t); | ||||
static int tftp_read(struct open_file *, void *, size_t, size_t *); | static int tftp_read(struct open_file *, void *, size_t, size_t *); | ||||
static off_t tftp_seek(struct open_file *, off_t, int); | static off_t tftp_seek(struct open_file *, off_t, int); | ||||
static int tftp_set_blksize(struct tftp_handle *, const char *); | static int tftp_set_blksize(struct tftp_handle *, const char *); | ||||
static int tftp_stat(struct open_file *, struct stat *); | static int tftp_stat(struct open_file *, struct stat *); | ||||
static int tftp_preload(struct open_file *); | |||||
struct fs_ops tftp_fsops = { | struct fs_ops tftp_fsops = { | ||||
.fs_name = "tftp", | .fs_name = "tftp", | ||||
.fo_open = tftp_open, | .fo_open = tftp_open, | ||||
.fo_close = tftp_close, | .fo_close = tftp_close, | ||||
.fo_read = tftp_read, | .fo_read = tftp_read, | ||||
.fo_write = null_write, | .fo_write = null_write, | ||||
.fo_seek = tftp_seek, | .fo_seek = tftp_seek, | ||||
.fo_stat = tftp_stat, | .fo_stat = tftp_stat, | ||||
.fo_preload = tftp_preload, | |||||
.fo_readdir = null_readdir | .fo_readdir = null_readdir | ||||
}; | }; | ||||
static int tftpport = 2000; | static int tftpport = 2000; | ||||
static int is_open = 0; | static int is_open = 0; | ||||
/* | /* | ||||
* The legacy TFTP_BLKSIZE value was SEGSIZE(512). | * The legacy TFTP_BLKSIZE value was SEGSIZE(512). | ||||
▲ Show 20 Lines • Show All 423 Lines • ▼ Show 20 Lines | tftp_read(struct open_file *f, void *addr, size_t size, | ||||
tftpfile = f->f_fsdata; | tftpfile = f->f_fsdata; | ||||
/* Make sure we will not read past file end */ | /* Make sure we will not read past file end */ | ||||
if (tftpfile->tftp_tsize > 0 && | if (tftpfile->tftp_tsize > 0 && | ||||
tftpfile->off + size > tftpfile->tftp_tsize) { | tftpfile->off + size > tftpfile->tftp_tsize) { | ||||
size = tftpfile->tftp_tsize - tftpfile->off; | size = tftpfile->tftp_tsize - tftpfile->off; | ||||
} | } | ||||
if (tftpfile->tftp_cache != NULL) { | |||||
bcopy(tftpfile->tftp_cache + tftpfile->off, | |||||
addr, size); | |||||
addr = (char *)addr + size; | |||||
tftpfile->off += size; | |||||
res -= size; | |||||
goto out; | |||||
} | |||||
while (size > 0) { | while (size > 0) { | ||||
int needblock, count; | int needblock, count; | ||||
twiddle(32); | twiddle(32); | ||||
needblock = tftpfile->off / tftpfile->tftp_blksize + 1; | needblock = tftpfile->off / tftpfile->tftp_blksize + 1; | ||||
if (tftpfile->currblock > needblock) { /* seek backwards */ | if (tftpfile->currblock > needblock) { /* seek backwards */ | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | |||||
#ifdef TFTP_DEBUG | #ifdef TFTP_DEBUG | ||||
printf("tftp: block %d not found\n", needblock); | printf("tftp: block %d not found\n", needblock); | ||||
#endif | #endif | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
} | } | ||||
out: | |||||
if (resid != NULL) | if (resid != NULL) | ||||
*resid = res; | *resid = res; | ||||
return (rc); | return (rc); | ||||
} | } | ||||
static int | static int | ||||
tftp_close(struct open_file *f) | tftp_close(struct open_file *f) | ||||
{ | { | ||||
struct tftp_handle *tftpfile; | struct tftp_handle *tftpfile; | ||||
tftpfile = f->f_fsdata; | tftpfile = f->f_fsdata; | ||||
if (tftpfile->lastacksent == false) | if (tftpfile->lastacksent == false) | ||||
tftp_senderr(tftpfile, 0, "No error: file closed"); | tftp_senderr(tftpfile, 0, "No error: file closed"); | ||||
if (tftpfile) { | if (tftpfile) { | ||||
free(tftpfile->path); | free(tftpfile->path); | ||||
free(tftpfile->pkt); | free(tftpfile->pkt); | ||||
free(tftpfile->tftp_cache); | |||||
imp: You don't need this if. free(NULL) works in the loader. | |||||
Done Inline ActionsFixed locally. manu: Fixed locally.
I'll push the series tomorow. | |||||
free(tftpfile); | free(tftpfile); | ||||
} | } | ||||
is_open = 0; | is_open = 0; | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
tftp_stat(struct open_file *f, struct stat *sb) | tftp_stat(struct open_file *f, struct stat *sb) | ||||
Show All 22 Lines | tftp_seek(struct open_file *f, off_t offset, int where) | ||||
case SEEK_CUR: | case SEEK_CUR: | ||||
tftpfile->off += offset; | tftpfile->off += offset; | ||||
break; | break; | ||||
default: | default: | ||||
errno = EOFFSET; | errno = EOFFSET; | ||||
return (-1); | return (-1); | ||||
} | } | ||||
return (tftpfile->off); | return (tftpfile->off); | ||||
} | |||||
static int | |||||
tftp_preload(struct open_file *f) | |||||
{ | |||||
struct tftp_handle *tftpfile; | |||||
char *cache; | |||||
int rc; | |||||
#ifdef TFTP_DEBUG | |||||
time_t start, end; | |||||
#endif | |||||
Done Inline Actionsmalloc can fail. tsoome: malloc can fail. | |||||
tftpfile = f->f_fsdata; | |||||
cache = malloc(sizeof(char) * tftpfile->tftp_tsize); | |||||
if (cache == NULL) { | |||||
Done Inline ActionsProbably should be printed if TFTP_DEBUG is defined. tsoome: Probably should be printed if TFTP_DEBUG is defined. | |||||
printf("Couldn't allocate %ju bytes for preload caching" | |||||
Not Done Inline ActionsWe're not aborting, we're moving to uncached operations. The calls to preload() don't fail the whole transfer. imp: We're not aborting, we're moving to uncached operations. The calls to preload() don't fail the… | |||||
Done Inline ActionsWell we are aborting preloading, but if you have better wording I'm ok to change it. manu: Well we are aborting preloading, but if you have better wording I'm ok to change it. | |||||
Not Done Inline Actions"Couldn't allocate %ju bytes for preload caching, disabling caching." imp: "Couldn't allocate %ju bytes for preload caching, disabling caching." | |||||
", disabling caching\n", | |||||
(uintmax_t)sizeof(char) * tftpfile->tftp_tsize); | |||||
return (-1); | |||||
} | |||||
mmelUnsubmitted Not Done Inline Actionstftpfile->currblock = 0; mmel: ```
tftpfile->currblock = 0;
``` | |||||
#ifdef TFTP_DEBUG | |||||
start = getsecs(); | |||||
printf("Preloading %s ", tftpfile->path); | |||||
#endif | |||||
while (tftpfile->islastblock == 0) { | |||||
twiddle(32); | |||||
rc = tftp_getnextblock(tftpfile); | |||||
if (rc) { | |||||
Done Inline ActionsDo you need to invalidate and flush the cache when there's an error filling it? Maybe it's just as simple as freeing cache. imp: Do you need to invalidate and flush the cache when there's an error filling it? Maybe it's just… | |||||
Done Inline ActionsYeah freeing the cache file we avoid leeking. manu: Yeah freeing the cache file we avoid leeking.
I'll add that and some error message too. | |||||
free(cache); | |||||
printf("Got TFTP error %d, disabling caching\n", rc); | |||||
return (rc); | |||||
} | |||||
bcopy(tftpfile->tftp_hdr->th_data, | |||||
cache + (tftpfile->tftp_blksize * (tftpfile->currblock - 1)), | |||||
tftpfile->validsize); | |||||
} | |||||
#ifdef TFTP_DEBUG | |||||
end = getsecs(); | |||||
printf("\nPreloaded %s (%ju bytes) during %jd seconds\n", | |||||
tftpfile->path, (intmax_t)tftpfile->tftp_tsize, | |||||
(intmax_t)end - start); | |||||
#endif | |||||
tftpfile->tftp_cache = cache; | |||||
return (0); | |||||
} | } | ||||
static int | static int | ||||
tftp_set_blksize(struct tftp_handle *h, const char *str) | tftp_set_blksize(struct tftp_handle *h, const char *str) | ||||
{ | { | ||||
char *endptr; | char *endptr; | ||||
int new_blksize; | int new_blksize; | ||||
int ret = 0; | int ret = 0; | ||||
▲ Show 20 Lines • Show All 121 Lines • Show Last 20 Lines |
You don't need this if. free(NULL) works in the loader.