Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/kern_module.c
Show First 20 Lines • Show All 355 Lines • ▼ Show 20 Lines | else | ||||
td->td_retval[0] = 0; | td->td_retval[0] = 0; | ||||
} | } | ||||
MOD_SUNLOCK; | MOD_SUNLOCK; | ||||
return (error); | return (error); | ||||
} | } | ||||
struct module_stat_v1 { | struct module_stat_v1 { | ||||
int version; /* set to sizeof(struct module_stat) */ | int version; /* set to sizeof(struct module_stat) */ | ||||
char name[MAXMODNAME]; | char name[MAXMODNAMEV1V2]; | ||||
int refs; | int refs; | ||||
int id; | int id; | ||||
}; | }; | ||||
struct module_stat_v2 { | |||||
int version; /* set to sizeof(struct module_stat) */ | |||||
char name[MAXMODNAMEV1V2]; | |||||
int refs; | |||||
int id; | |||||
modspecific_t data; | |||||
}; | |||||
CTASSERT(sizeof(struct module_stat_v2) == sizeof(struct module_stat)); | |||||
int | int | ||||
sys_modstat(struct thread *td, struct modstat_args *uap) | sys_modstat(struct thread *td, struct modstat_args *uap) | ||||
{ | { | ||||
module_t mod; | module_t mod; | ||||
modspecific_t data; | modspecific_t data; | ||||
int error = 0; | int error = 0; | ||||
int id, namelen, refs, version; | int id, namelen, refs, version; | ||||
struct module_stat *stat; | struct module_stat *stat; | ||||
struct module_stat_v2 *stat_v2; | |||||
char *name; | char *name; | ||||
bool is_v1v2; | |||||
MOD_SLOCK; | MOD_SLOCK; | ||||
mod = module_lookupbyid(uap->modid); | mod = module_lookupbyid(uap->modid); | ||||
if (mod == NULL) { | if (mod == NULL) { | ||||
MOD_SUNLOCK; | MOD_SUNLOCK; | ||||
return (ENOENT); | return (ENOENT); | ||||
} | } | ||||
id = mod->id; | id = mod->id; | ||||
refs = mod->refs; | refs = mod->refs; | ||||
name = mod->name; | name = mod->name; | ||||
data = mod->data; | data = mod->data; | ||||
MOD_SUNLOCK; | MOD_SUNLOCK; | ||||
stat = uap->stat; | stat = uap->stat; | ||||
/* | /* | ||||
* Check the version of the user's structure. | * Check the version of the user's structure. | ||||
*/ | */ | ||||
if ((error = copyin(&stat->version, &version, sizeof(version))) != 0) | if ((error = copyin(&stat->version, &version, sizeof(version))) != 0) | ||||
return (error); | return (error); | ||||
if (version != sizeof(struct module_stat_v1) | is_v1v2 = (version == sizeof(struct module_stat_v1) || | ||||
&& version != sizeof(struct module_stat)) | version == sizeof(struct module_stat_v2)); | ||||
if (!is_v1v2 && version != sizeof(struct module_stat)) | |||||
return (EINVAL); | return (EINVAL); | ||||
namelen = strlen(mod->name) + 1; | namelen = strlen(mod->name) + 1; | ||||
if (namelen > MAXMODNAME) | if (is_v1v2 && namelen > MAXMODNAMEV1V2) | ||||
namelen = MAXMODNAME; | namelen = MAXMODNAMEV1V2; | ||||
else if (namelen > MAXMODNAMEV3) | |||||
namelen = MAXMODNAMEV3; | |||||
if ((error = copyout(name, &stat->name[0], namelen)) != 0) | if ((error = copyout(name, &stat->name[0], namelen)) != 0) | ||||
return (error); | return (error); | ||||
/* Extending MAXMODNAME gives an offset change for v3. */ | |||||
if (is_v1v2) { | |||||
stat_v2 = (struct module_stat_v2 *)stat; | |||||
if ((error = copyout(&refs, &stat_v2->refs, sizeof(int))) != 0) | |||||
return (error); | |||||
if ((error = copyout(&id, &stat_v2->id, sizeof(int))) != 0) | |||||
return (error); | |||||
} else { | |||||
if ((error = copyout(&refs, &stat->refs, sizeof(int))) != 0) | if ((error = copyout(&refs, &stat->refs, sizeof(int))) != 0) | ||||
return (error); | return (error); | ||||
if ((error = copyout(&id, &stat->id, sizeof(int))) != 0) | if ((error = copyout(&id, &stat->id, sizeof(int))) != 0) | ||||
return (error); | return (error); | ||||
} | |||||
/* | /* | ||||
* >v1 stat includes module data. | * >v1 stat includes module data. | ||||
*/ | */ | ||||
if (version == sizeof(struct module_stat)) | if (version == sizeof(struct module_stat_v2)) { | ||||
if ((error = copyout(&data, &stat_v2->data, | |||||
sizeof(data))) != 0) | |||||
return (error); | |||||
} else if (version == sizeof(struct module_stat)) { | |||||
if ((error = copyout(&data, &stat->data, | if ((error = copyout(&data, &stat->data, | ||||
sizeof(data))) != 0) | sizeof(data))) != 0) | ||||
return (error); | return (error); | ||||
} | |||||
td->td_retval[0] = 0; | td->td_retval[0] = 0; | ||||
return (error); | return (error); | ||||
} | } | ||||
int | int | ||||
sys_modfind(struct thread *td, struct modfind_args *uap) | sys_modfind(struct thread *td, struct modfind_args *uap) | ||||
{ | { | ||||
int error = 0; | int error = 0; | ||||
char name[MAXMODNAME]; | char name[MAXMODNAMEV3]; | ||||
module_t mod; | module_t mod; | ||||
if ((error = copyinstr(uap->name, name, sizeof name, 0)) != 0) | if ((error = copyinstr(uap->name, name, sizeof name, 0)) != 0) | ||||
return (error); | return (error); | ||||
MOD_SLOCK; | MOD_SLOCK; | ||||
mod = module_lookupbyname(name); | mod = module_lookupbyname(name); | ||||
if (mod == NULL) | if (mod == NULL) | ||||
Show All 15 Lines | |||||
typedef union modspecific32 { | typedef union modspecific32 { | ||||
int intval; | int intval; | ||||
uint32_t uintval; | uint32_t uintval; | ||||
int longval; | int longval; | ||||
uint32_t ulongval; | uint32_t ulongval; | ||||
} modspecific32_t; | } modspecific32_t; | ||||
struct module_stat32_v2 { | |||||
int version; | |||||
char name[MAXMODNAMEV1V2]; | |||||
int refs; | |||||
int id; | |||||
modspecific32_t data; | |||||
}; | |||||
hselasky: missing empty line here? | |||||
struct module_stat32 { | struct module_stat32 { | ||||
int version; | int version; | ||||
char name[MAXMODNAME]; | char name[MAXMODNAME]; /* XXX make V3 */ | ||||
int refs; | int refs; | ||||
int id; | int id; | ||||
modspecific32_t data; | modspecific32_t data; | ||||
}; | }; | ||||
CTASSERT(sizeof(struct module_stat32_v2) == sizeof(struct module_stat32)); | |||||
int | int | ||||
freebsd32_modstat(struct thread *td, struct freebsd32_modstat_args *uap) | freebsd32_modstat(struct thread *td, struct freebsd32_modstat_args *uap) | ||||
{ | { | ||||
module_t mod; | module_t mod; | ||||
modspecific32_t data32; | modspecific32_t data32; | ||||
int error = 0; | int error = 0; | ||||
int id, namelen, refs, version; | int id, namelen, refs, version; | ||||
struct module_stat32 *stat32; | struct module_stat32 *stat32; | ||||
struct module_stat32_v2 *stat32_v2; | |||||
char *name; | char *name; | ||||
bool is_v1v2; | |||||
MOD_SLOCK; | MOD_SLOCK; | ||||
mod = module_lookupbyid(uap->modid); | mod = module_lookupbyid(uap->modid); | ||||
if (mod == NULL) { | if (mod == NULL) { | ||||
MOD_SUNLOCK; | MOD_SUNLOCK; | ||||
return (ENOENT); | return (ENOENT); | ||||
} | } | ||||
id = mod->id; | id = mod->id; | ||||
refs = mod->refs; | refs = mod->refs; | ||||
name = mod->name; | name = mod->name; | ||||
CP(mod->data, data32, intval); | CP(mod->data, data32, intval); | ||||
CP(mod->data, data32, uintval); | CP(mod->data, data32, uintval); | ||||
CP(mod->data, data32, longval); | CP(mod->data, data32, longval); | ||||
CP(mod->data, data32, ulongval); | CP(mod->data, data32, ulongval); | ||||
MOD_SUNLOCK; | MOD_SUNLOCK; | ||||
stat32 = uap->stat; | stat32 = uap->stat; | ||||
if ((error = copyin(&stat32->version, &version, sizeof(version))) != 0) | if ((error = copyin(&stat32->version, &version, sizeof(version))) != 0) | ||||
return (error); | return (error); | ||||
if (version != sizeof(struct module_stat_v1) | is_v1v2 = (version == sizeof(struct module_stat_v1) || | ||||
&& version != sizeof(struct module_stat32)) | version == sizeof(struct module_stat32_v2)); | ||||
if (!is_v1v2 && version != sizeof(struct module_stat32)) | |||||
return (EINVAL); | return (EINVAL); | ||||
namelen = strlen(mod->name) + 1; | namelen = strlen(mod->name) + 1; | ||||
if (namelen > MAXMODNAME) | if (is_v1v2 && namelen > MAXMODNAMEV1V2) | ||||
namelen = MAXMODNAME; | namelen = MAXMODNAMEV1V2; | ||||
else if (namelen > MAXMODNAMEV3) | |||||
namelen = MAXMODNAMEV3; | |||||
if ((error = copyout(name, &stat32->name[0], namelen)) != 0) | if ((error = copyout(name, &stat32->name[0], namelen)) != 0) | ||||
return (error); | return (error); | ||||
/* Extending MAXMODNAME gives an offset change for v3. */ | |||||
if (is_v1v2) { | |||||
stat32_v2 = (struct module_stat32_v2 *)stat32; | |||||
if ((error = copyout(&refs, &stat32_v2->refs, sizeof(int))) != 0) | |||||
return (error); | |||||
if ((error = copyout(&id, &stat32_v2->id, sizeof(int))) != 0) | |||||
return (error); | |||||
} else { | |||||
if ((error = copyout(&refs, &stat32->refs, sizeof(int))) != 0) | if ((error = copyout(&refs, &stat32->refs, sizeof(int))) != 0) | ||||
return (error); | return (error); | ||||
if ((error = copyout(&id, &stat32->id, sizeof(int))) != 0) | if ((error = copyout(&id, &stat32->id, sizeof(int))) != 0) | ||||
return (error); | return (error); | ||||
} | |||||
/* | /* | ||||
* >v1 stat includes module data. | * >v1 stat includes module data. | ||||
*/ | */ | ||||
if (version == sizeof(struct module_stat32)) | if (version == sizeof(struct module_stat32_v2)) { | ||||
if ((error = copyout(&data32, &stat32_v2->data, | |||||
sizeof(data32))) != 0) | |||||
return (error); | |||||
} else if (version == sizeof(struct module_stat32)) { | |||||
if ((error = copyout(&data32, &stat32->data, | if ((error = copyout(&data32, &stat32->data, | ||||
sizeof(data32))) != 0) | sizeof(data32))) != 0) | ||||
return (error); | return (error); | ||||
} | |||||
td->td_retval[0] = 0; | td->td_retval[0] = 0; | ||||
return (error); | return (error); | ||||
} | } | ||||
#endif | #endif |
missing empty line here?