|
177 | 177 |
|
178 | 178 | /* ioctl define end */
|
179 | 179 |
|
| 180 | +/* fcntl define start */ |
| 181 | + |
| 182 | +#define LINUX_F_DUPFD 0 |
| 183 | +#define LINUX_F_GETFD 1 |
| 184 | +#define LINUX_F_SETFD 2 |
| 185 | +#define LINUX_F_GETFL 3 |
| 186 | +#define LINUX_F_SETFL 4 |
| 187 | +#define LINUX_F_GETLK 5 |
| 188 | +#define LINUX_F_SETLK 6 |
| 189 | +#define LINUX_F_SETLKW 7 |
| 190 | +#define LINUX_F_SETOWN 8 |
| 191 | +#define LINUX_F_GETOWN 9 |
| 192 | +#define LINUX_F_OFD_GETLK 36 |
| 193 | +#define LINUX_F_OFD_SETLK 37 |
| 194 | +#define LINUX_F_OFD_SETLKW 38 |
| 195 | + |
| 196 | +#define LINUX_O_APPEND 0x400 |
| 197 | +#define LINUX_O_NONBLOCK 0x800 |
| 198 | +#define LINUX_O_ASYNC 0x2000 |
| 199 | +#define LINUX_O_DIRECT 0x4000 |
| 200 | +#define LINUX_O_NOATIME 0x40000 |
| 201 | +#define LINUX_O_CLOEXEC 0x80000 |
| 202 | + |
| 203 | +/* fcntl define end */ |
| 204 | + |
180 | 205 | /* af define start */
|
181 | 206 |
|
182 | 207 | #define LINUX_AF_INET6 10
|
@@ -246,6 +271,140 @@ struct linux_cmsghdr
|
246 | 271 |
|
247 | 272 | extern int sendit(struct thread *td, int s, struct msghdr *mp, int flags);
|
248 | 273 |
|
| 274 | +/* convert linux argp to freebsd argp. */ |
| 275 | +static inline int |
| 276 | +linux2freebsd_fcntl(int cmd, intptr_t *argp) |
| 277 | +{ |
| 278 | + switch(cmd) { |
| 279 | + case LINUX_F_DUPFD: |
| 280 | + return F_DUPFD; |
| 281 | + case LINUX_F_GETFD: |
| 282 | + return F_GETFD; |
| 283 | + case LINUX_F_SETFD: |
| 284 | + if (*argp & LINUX_O_CLOEXEC) { |
| 285 | + //clear linux O_CLOEXEC, set freebsd O_CLOEXEC. |
| 286 | + *argp &= ~LINUX_O_CLOEXEC; |
| 287 | + *argp |= O_CLOEXEC; |
| 288 | + } |
| 289 | + |
| 290 | + return F_SETFD; |
| 291 | + case LINUX_F_GETFL: |
| 292 | + return F_GETFL; |
| 293 | + case LINUX_F_SETFL: |
| 294 | + if (*argp & LINUX_O_NONBLOCK) { |
| 295 | + //clear linux O_NONBLOCK, set freebsd O_NONBLOCK. |
| 296 | + *argp &= ~LINUX_O_NONBLOCK; |
| 297 | + *argp |= O_NONBLOCK; |
| 298 | + } |
| 299 | + |
| 300 | + if (*argp & LINUX_O_APPEND) { |
| 301 | + //clear linux O_APPEND, set freebsd O_APPEND. |
| 302 | + *argp &= ~LINUX_O_APPEND; |
| 303 | + *argp |= O_APPEND; |
| 304 | + } |
| 305 | + |
| 306 | + if (*argp & LINUX_O_ASYNC) { |
| 307 | + //clear linux O_ASYNC, set freebsd O_ASYNC. |
| 308 | + *argp &= ~LINUX_O_ASYNC; |
| 309 | + *argp |= O_ASYNC; |
| 310 | + } |
| 311 | + |
| 312 | + if (*argp & LINUX_O_DIRECT) { |
| 313 | + //clear linux O_DIRECT, set freebsd O_DIRECT. |
| 314 | + *argp &= ~LINUX_O_DIRECT; |
| 315 | + *argp |= O_DIRECT; |
| 316 | + } |
| 317 | + |
| 318 | + return F_SETFL; |
| 319 | + case LINUX_F_GETLK: |
| 320 | + return F_GETLK; |
| 321 | + case LINUX_F_SETLK: |
| 322 | + return F_SETLK; |
| 323 | + case LINUX_F_SETLKW: |
| 324 | + return F_SETLKW; |
| 325 | + case LINUX_F_SETOWN: |
| 326 | + return F_SETOWN; |
| 327 | + case LINUX_F_GETOWN: |
| 328 | + return F_GETOWN; |
| 329 | + case LINUX_F_OFD_GETLK: |
| 330 | + return F_OGETLK; |
| 331 | + case LINUX_F_OFD_SETLK: |
| 332 | + return F_OSETLK; |
| 333 | + case LINUX_F_OFD_SETLKW: |
| 334 | + return F_OSETLKW; |
| 335 | + default: |
| 336 | + return cmd; |
| 337 | + } |
| 338 | +} |
| 339 | + |
| 340 | +/* |
| 341 | + * convert freebsd flags to linux flags. |
| 342 | + * cmd has been converted to freebsd mode. |
| 343 | + */ |
| 344 | +static inline int |
| 345 | +freebsd2linux_fcntl(int cmd, int flags) |
| 346 | +{ |
| 347 | + switch(cmd) { |
| 348 | + case F_DUPFD: |
| 349 | + return flags; |
| 350 | + case F_GETFD: |
| 351 | + if (flags & O_CLOEXEC) { |
| 352 | + //clear freebsd O_DIRECT, set linux O_DIRECT. |
| 353 | + flags &= ~O_CLOEXEC; |
| 354 | + flags |= LINUX_O_CLOEXEC; |
| 355 | + } |
| 356 | + return flags; |
| 357 | + case F_SETFD: |
| 358 | + return flags; |
| 359 | + case F_GETFL: |
| 360 | + if (flags & O_NONBLOCK) { |
| 361 | + //clear linux O_NONBLOCK, set freebsd O_NONBLOCK. |
| 362 | + flags &= ~O_NONBLOCK; |
| 363 | + flags |= LINUX_O_NONBLOCK; |
| 364 | + } |
| 365 | + |
| 366 | + if (flags & O_APPEND) { |
| 367 | + //clear linux O_APPEND, set freebsd O_APPEND. |
| 368 | + flags &= ~O_APPEND; |
| 369 | + flags |= LINUX_O_APPEND; |
| 370 | + } |
| 371 | + |
| 372 | + if (flags & O_ASYNC) { |
| 373 | + //clear linux O_ASYNC, set freebsd O_ASYNC. |
| 374 | + flags &= ~O_ASYNC; |
| 375 | + flags |= LINUX_O_ASYNC; |
| 376 | + } |
| 377 | + |
| 378 | + if (flags & O_DIRECT) { |
| 379 | + //clear linux O_DIRECT, set freebsd O_DIRECT. |
| 380 | + flags &= ~O_DIRECT; |
| 381 | + flags |= LINUX_O_DIRECT; |
| 382 | + } |
| 383 | + |
| 384 | + return flags; |
| 385 | + case LINUX_F_SETFL: |
| 386 | + return flags; |
| 387 | + case F_GETLK: |
| 388 | + return flags; |
| 389 | + case F_SETLK: |
| 390 | + return flags; |
| 391 | + case F_SETLKW: |
| 392 | + return flags; |
| 393 | + case F_SETOWN: |
| 394 | + return flags; |
| 395 | + case F_GETOWN: |
| 396 | + return flags; |
| 397 | + case F_OGETLK: |
| 398 | + return flags; |
| 399 | + case F_OSETLK: |
| 400 | + return flags; |
| 401 | + case F_OSETLKW: |
| 402 | + return flags; |
| 403 | + default: |
| 404 | + return flags; |
| 405 | + } |
| 406 | +} |
| 407 | + |
249 | 408 | static long
|
250 | 409 | linux2freebsd_ioctl(unsigned long request)
|
251 | 410 | {
|
@@ -1150,9 +1309,11 @@ ff_fcntl(int fd, int cmd, ...)
|
1150 | 1309 | argp = va_arg(ap, uintptr_t);
|
1151 | 1310 | va_end(ap);
|
1152 | 1311 |
|
| 1312 | + cmd = linux2freebsd_fcntl(cmd, &argp); |
| 1313 | + |
1153 | 1314 | if ((rc = kern_fcntl(curthread, fd, cmd, argp)))
|
1154 | 1315 | goto kern_fail;
|
1155 |
| - rc = curthread->td_retval[0]; |
| 1316 | + rc = freebsd2linux_fcntl(cmd, curthread->td_retval[0]); |
1156 | 1317 | return (rc);
|
1157 | 1318 | kern_fail:
|
1158 | 1319 | ff_os_errno(rc);
|
|
0 commit comments