Hi Jan! On 2026-05-18T17:05:59+0200, Jan Kara wrote: > > I have more questions about quotactl(2). In the operations that ignore > > the 'id' argument, am I right to assume that QCMD() is unnecessary? My > > assumption is because if there's no user or group ID to be used, it also > > doesn't make sense to specify whether we want to affect a user or a > > group. > > > > So, for example, Q_QUOTAOFF would have the following synopsis: > > > > int quotactl(Q_QUOTAOFF, const char *_Nullable special, 0, NULL); > > > > While Q_QUOTAON would have the following one: > > > > int quotactl(QCMD(Q_QUOTAON, type), const char *_Nullable special, > > int fmt, caddr_t quota_path); > > > > Is that correct? > > No, QCMD() is always required. For example for Q_QUOTAOFF you still need to > tell whether you want to disable user or group quotas. And even if the type > would not matter for some quotactl, QCMD still does a mangling to the > passed arguments that is expected by the kernel (QCMD is ((cmd) << > SUBCMDSHIFT) | ((type) & SUBCMDMASK)). Ahh, thanks! Makes sense. > > Also, I wonder why caddr_t was used at all, instead of void*. It seems > > to unnecessarily require a cast, which could have been avoided with > > void*. In quotactl_fd(), since we need to use syscall(2), which is > > variadic, I'll document the correct pointer types, instead of caddr_t*. > > For this I don't have a good answer. It was like that for ages... I guess > you can ask glibc guys - the kernel uses void * but glibc uses caddr_t. Hmmmm. I'll ask; thanks! Cheers, Alex --