| 291 | } |
| 292 | |
| 293 | static int fs_readdir(FSDevice *fs, FSFile *f, uint64_t offset, |
| 294 | uint8_t *buf, int count) |
| 295 | { |
| 296 | struct dirent *de; |
| 297 | int len, pos, name_len, type, d_type; |
| 298 | |
| 299 | if (!f->is_opened || !f->is_dir) |
| 300 | return -P9_EPROTO; |
| 301 | if (offset == 0) |
| 302 | rewinddir(f->u.dirp); |
| 303 | else |
| 304 | seekdir(f->u.dirp, offset); |
| 305 | pos = 0; |
| 306 | for(;;) { |
| 307 | de = readdir(f->u.dirp); |
| 308 | if (de == NULL) |
| 309 | break; |
| 310 | name_len = strlen(de->d_name); |
| 311 | len = 13 + 8 + 1 + 2 + name_len; |
| 312 | if ((pos + len) > count) |
| 313 | break; |
| 314 | offset = telldir(f->u.dirp); |
| 315 | d_type = de->d_type; |
| 316 | if (d_type == DT_UNKNOWN) { |
| 317 | char *path; |
| 318 | struct stat st; |
| 319 | path = compose_path(f->path, de->d_name); |
| 320 | if (lstat(path, &st) == 0) { |
| 321 | d_type = st.st_mode >> 12; |
| 322 | } else { |
| 323 | d_type = DT_REG; /* default */ |
| 324 | } |
| 325 | free(path); |
| 326 | } |
| 327 | if (d_type == DT_DIR) |
| 328 | type = P9_QTDIR; |
| 329 | else if (d_type == DT_LNK) |
| 330 | type = P9_QTSYMLINK; |
| 331 | else |
| 332 | type = P9_QTFILE; |
| 333 | buf[pos++] = type; |
| 334 | put_le32(buf + pos, 0); /* version */ |
| 335 | pos += 4; |
| 336 | put_le64(buf + pos, de->d_ino); |
| 337 | pos += 8; |
| 338 | put_le64(buf + pos, offset); |
| 339 | pos += 8; |
| 340 | buf[pos++] = d_type; |
| 341 | put_le16(buf + pos, name_len); |
| 342 | pos += 2; |
| 343 | memcpy(buf + pos, de->d_name, name_len); |
| 344 | pos += name_len; |
| 345 | } |
| 346 | return pos; |
| 347 | } |
| 348 | |
| 349 | static int fs_read(FSDevice *fs, FSFile *f, uint64_t offset, |
| 350 | uint8_t *buf, int count) |
nothing calls this directly
no test coverage detected